Make remaining OLE interface vtables const.
[wine/wine64.git] / dlls / oleaut32 / typelib.c
blob31f4cd42b65ef18f28c384eaff4152835cc91dd1
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
47 * behaviour.
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
55 #include "config.h"
56 #include "wine/port.h"
58 #include <stdlib.h>
59 #include <string.h>
60 #include <stdarg.h>
61 #include <stdio.h>
62 #include <ctype.h>
64 #define COBJMACROS
65 #define NONAMELESSUNION
66 #define NONAMELESSSTRUCT
68 #include "winerror.h"
69 #include "windef.h"
70 #include "winbase.h"
71 #include "winnls.h"
72 #include "winreg.h"
73 #include "winuser.h"
75 #include "wine/unicode.h"
76 #include "objbase.h"
77 #include "typelib.h"
78 #include "wine/debug.h"
79 #include "variant.h"
81 WINE_DEFAULT_DEBUG_CHANNEL(ole);
82 WINE_DECLARE_DEBUG_CHANNEL(typelib);
84 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
85 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
87 /****************************************************************************
88 * FromLExxx
90 * Takes p_iVal (which is in little endian) and returns it
91 * in the host machine's byte order.
93 #ifdef WORDS_BIGENDIAN
94 static WORD FromLEWord(WORD p_iVal)
96 return (((p_iVal & 0x00FF) << 8) |
97 ((p_iVal & 0xFF00) >> 8));
101 static DWORD FromLEDWord(DWORD p_iVal)
103 return (((p_iVal & 0x000000FF) << 24) |
104 ((p_iVal & 0x0000FF00) << 8) |
105 ((p_iVal & 0x00FF0000) >> 8) |
106 ((p_iVal & 0xFF000000) >> 24));
108 #else
109 #define FromLEWord(X) (X)
110 #define FromLEDWord(X) (X)
111 #endif
114 /****************************************************************************
115 * FromLExxx
117 * Fix byte order in any structure if necessary
119 #ifdef WORDS_BIGENDIAN
120 static void FromLEWords(void *p_Val, int p_iSize)
122 WORD *Val = p_Val;
124 p_iSize /= sizeof(WORD);
126 while (p_iSize) {
127 *Val = FromLEWord(*Val);
128 Val++;
129 p_iSize--;
134 static void FromLEDWords(void *p_Val, int p_iSize)
136 DWORD *Val = p_Val;
138 p_iSize /= sizeof(DWORD);
140 while (p_iSize) {
141 *Val = FromLEDWord(*Val);
142 Val++;
143 p_iSize--;
146 #else
147 #define FromLEWords(X,Y) /*nothing*/
148 #define FromLEDWords(X,Y) /*nothing*/
149 #endif
151 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
152 /* buffer must be at least 60 characters long */
153 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
155 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
156 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
158 memcpy( buffer, TypelibW, sizeof(TypelibW) );
159 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
160 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
161 return buffer;
164 /* get the path of an interface key, in the form "Interface\\<guid>" */
165 /* buffer must be at least 50 characters long */
166 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
168 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
170 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
171 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
172 return buffer;
175 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
176 /* buffer must be at least 16 characters long */
177 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
179 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
180 static const WCHAR win16W[] = {'w','i','n','1','6',0};
181 static const WCHAR win32W[] = {'w','i','n','3','2',0};
183 sprintfW( buffer, LcidFormatW, lcid );
184 switch(syskind)
186 case SYS_WIN16: strcatW( buffer, win16W ); break;
187 case SYS_WIN32: strcatW( buffer, win32W ); break;
188 default:
189 TRACE("Typelib is for unsupported syskind %i\n", syskind);
190 return NULL;
192 return buffer;
195 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
198 /****************************************************************************
199 * QueryPathOfRegTypeLib [OLEAUT32.164]
201 * Gets the path to a registered type library.
203 * PARAMS
204 * guid [I] referenced guid
205 * wMaj [I] major version
206 * wMin [I] minor version
207 * lcid [I] locale id
208 * path [O] path of typelib
210 * RETURNS
211 * Success: S_OK.
212 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
213 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
214 * opened.
216 HRESULT WINAPI QueryPathOfRegTypeLib(
217 REFGUID guid,
218 WORD wMaj,
219 WORD wMin,
220 LCID lcid,
221 LPBSTR path )
223 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
224 LCID myLCID = lcid;
225 HKEY hkey;
226 WCHAR buffer[60];
227 WCHAR Path[MAX_PATH];
228 LONG res;
230 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
232 get_typelib_key( guid, wMaj, wMin, buffer );
234 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
235 if (res == ERROR_FILE_NOT_FOUND)
237 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
238 return TYPE_E_LIBNOTREGISTERED;
240 else if (res != ERROR_SUCCESS)
242 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
243 return TYPE_E_REGISTRYACCESS;
246 while (hr != S_OK)
248 DWORD dwPathLen = sizeof(Path);
250 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
252 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
254 if (!lcid)
255 break;
256 else if (myLCID == lcid)
258 /* try with sub-langid */
259 myLCID = SUBLANGID(lcid);
261 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
263 /* try with system langid */
264 myLCID = 0;
266 else
268 break;
271 else
273 *path = SysAllocString( Path );
274 hr = S_OK;
277 RegCloseKey( hkey );
278 TRACE_(typelib)("-- 0x%08lx\n", hr);
279 return hr;
282 /******************************************************************************
283 * CreateTypeLib [OLEAUT32.160] creates a typelib
285 * RETURNS
286 * Success: S_OK
287 * Failure: Status
289 HRESULT WINAPI CreateTypeLib(
290 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
292 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
293 return E_FAIL;
296 /******************************************************************************
297 * LoadTypeLib [OLEAUT32.161]
299 * Loads a type library
301 * PARAMS
302 * szFile [I] Name of file to load from.
303 * pptLib [O] Pointer that receives ITypeLib object on success.
305 * RETURNS
306 * Success: S_OK
307 * Failure: Status
309 * SEE
310 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
312 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
314 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
315 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
318 /******************************************************************************
319 * LoadTypeLibEx [OLEAUT32.183]
321 * Loads and optionally registers a type library
323 * RETURNS
324 * Success: S_OK
325 * Failure: Status
327 HRESULT WINAPI LoadTypeLibEx(
328 LPCOLESTR szFile, /* [in] Name of file to load from */
329 REGKIND regkind, /* [in] Specify kind of registration */
330 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
332 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
333 WCHAR *pIndexStr;
334 HRESULT res;
335 INT index = 1;
337 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
339 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
340 memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR));
342 *pptLib = NULL;
343 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
344 NULL)) {
346 /* Look for a trailing '\\' followed by an index */
347 pIndexStr = strrchrW(szFile, '\\');
348 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
349 index = atoiW(pIndexStr);
350 memcpy(szFileCopy, szFile,
351 (pIndexStr - szFile - 1) * sizeof(WCHAR));
352 szFileCopy[pIndexStr - szFile - 1] = '\0';
353 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
354 szPath,NULL))
355 return TYPE_E_CANTLOADLIBRARY;
356 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
357 return TYPE_E_CANTLOADLIBRARY;
361 TRACE("File %s index %d\n", debugstr_w(szPath), index);
363 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
365 if (SUCCEEDED(res))
366 switch(regkind)
368 case REGKIND_DEFAULT:
369 /* don't register typelibs supplied with full path. Experimentation confirms the following */
370 if ((!szFile) ||
371 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
372 (szFile[0] && (szFile[1] == ':'))) break;
373 /* else fall-through */
375 case REGKIND_REGISTER:
376 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
378 IUnknown_Release(*pptLib);
379 *pptLib = 0;
381 break;
382 case REGKIND_NONE:
383 break;
386 TRACE(" returns %08lx\n",res);
387 return res;
390 /******************************************************************************
391 * LoadRegTypeLib [OLEAUT32.162]
393 * Loads a registered type library.
395 * PARAMS
396 * rguid [I] GUID of the registered type library.
397 * wVerMajor [I] major version.
398 * wVerMinor [I] minor version.
399 * lcid [I] locale ID.
400 * ppTLib [O] pointer that receives an ITypeLib object on success.
402 * RETURNS
403 * Success: S_OK.
404 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
405 * LoadTypeLib.
407 HRESULT WINAPI LoadRegTypeLib(
408 REFGUID rguid,
409 WORD wVerMajor,
410 WORD wVerMinor,
411 LCID lcid,
412 ITypeLib **ppTLib)
414 BSTR bstr=NULL;
415 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
417 if(SUCCEEDED(res))
419 res= LoadTypeLib(bstr, ppTLib);
420 SysFreeString(bstr);
423 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
425 return res;
429 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
430 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
431 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
432 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
433 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
434 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
436 /******************************************************************************
437 * RegisterTypeLib [OLEAUT32.163]
438 * Adds information about a type library to the System Registry
439 * NOTES
440 * Docs: ITypeLib FAR * ptlib
441 * Docs: OLECHAR FAR* szFullPath
442 * Docs: OLECHAR FAR* szHelpDir
444 * RETURNS
445 * Success: S_OK
446 * Failure: Status
448 HRESULT WINAPI RegisterTypeLib(
449 ITypeLib * ptlib, /* [in] Pointer to the library*/
450 OLECHAR * szFullPath, /* [in] full Path of the library*/
451 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
452 may be NULL*/
454 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
455 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
456 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
457 HRESULT res;
458 TLIBATTR *attr;
459 WCHAR keyName[60];
460 WCHAR tmp[16];
461 HKEY key, subKey;
462 UINT types, tidx;
463 TYPEKIND kind;
464 DWORD disposition;
466 if (ptlib == NULL || szFullPath == NULL)
467 return E_INVALIDARG;
469 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
470 return E_FAIL;
472 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
474 res = S_OK;
475 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
476 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
478 LPOLESTR doc;
480 /* Set the human-readable name of the typelib */
481 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
483 if (RegSetValueExW(key, NULL, 0, REG_SZ,
484 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
485 res = E_FAIL;
487 SysFreeString(doc);
489 else
490 res = E_FAIL;
492 /* Make up the name of the typelib path subkey */
493 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
495 /* Create the typelib path subkey */
496 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
497 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
499 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
500 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
501 res = E_FAIL;
503 RegCloseKey(subKey);
505 else
506 res = E_FAIL;
508 /* Create the flags subkey */
509 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
510 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
512 /* FIXME: is %u correct? */
513 static const WCHAR formatW[] = {'%','u',0};
514 WCHAR buf[20];
515 sprintfW(buf, formatW, attr->wLibFlags);
516 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
517 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
518 res = E_FAIL;
520 RegCloseKey(subKey);
522 else
523 res = E_FAIL;
525 /* create the helpdir subkey */
526 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
527 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
529 BOOL freeHelpDir = FALSE;
530 OLECHAR* pIndexStr;
532 /* if we created a new key, and helpDir was null, set the helpdir
533 to the directory which contains the typelib. However,
534 if we just opened an existing key, we leave the helpdir alone */
535 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
536 szHelpDir = SysAllocString(szFullPath);
537 pIndexStr = strrchrW(szHelpDir, '\\');
538 if (pIndexStr) {
539 *pIndexStr = 0;
541 freeHelpDir = TRUE;
544 /* if we have an szHelpDir, set it! */
545 if (szHelpDir != NULL) {
546 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
547 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
548 res = E_FAIL;
552 /* tidy up */
553 if (freeHelpDir) SysFreeString(szHelpDir);
554 RegCloseKey(subKey);
556 } else {
557 res = E_FAIL;
560 RegCloseKey(key);
562 else
563 res = E_FAIL;
565 /* register OLE Automation-compatible interfaces for this typelib */
566 types = ITypeLib_GetTypeInfoCount(ptlib);
567 for (tidx=0; tidx<types; tidx++) {
568 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
569 LPOLESTR name = NULL;
570 ITypeInfo *tinfo = NULL;
572 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
574 switch (kind) {
575 case TKIND_INTERFACE:
576 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
577 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
578 break;
580 case TKIND_DISPATCH:
581 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
582 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
583 break;
585 default:
586 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
587 break;
590 if (tinfo) {
591 TYPEATTR *tattr = NULL;
592 ITypeInfo_GetTypeAttr(tinfo, &tattr);
594 if (tattr) {
595 TRACE_(typelib)("guid=%s, flags=%04x (",
596 debugstr_guid(&tattr->guid),
597 tattr->wTypeFlags);
599 if (TRACE_ON(typelib)) {
600 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
601 XX(FAPPOBJECT);
602 XX(FCANCREATE);
603 XX(FLICENSED);
604 XX(FPREDECLID);
605 XX(FHIDDEN);
606 XX(FCONTROL);
607 XX(FDUAL);
608 XX(FNONEXTENSIBLE);
609 XX(FOLEAUTOMATION);
610 XX(FRESTRICTED);
611 XX(FAGGREGATABLE);
612 XX(FREPLACEABLE);
613 XX(FDISPATCHABLE);
614 XX(FREVERSEBIND);
615 XX(FPROXY);
616 #undef XX
617 MESSAGE("\n");
621 * FIXME: The 1 is just here until we implement rpcrt4
622 * stub/proxy handling. Until then it helps IShield
623 * v6 to work.
625 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
627 if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {
628 FIXME("Registering non-oleautomation interface!\n");
631 /* register interface<->typelib coupling */
632 get_interface_key( &tattr->guid, keyName );
633 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
634 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
636 if (name)
637 RegSetValueExW(key, NULL, 0, REG_SZ,
638 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
640 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
641 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
642 RegSetValueExW(subKey, NULL, 0, REG_SZ,
643 (BYTE*)PSOA, sizeof PSOA);
644 RegCloseKey(subKey);
647 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
648 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
649 RegSetValueExW(subKey, NULL, 0, REG_SZ,
650 (BYTE*)PSOA, sizeof PSOA);
651 RegCloseKey(subKey);
654 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
655 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
657 WCHAR buffer[40];
658 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
659 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
661 StringFromGUID2(&attr->guid, buffer, 40);
662 RegSetValueExW(subKey, NULL, 0, REG_SZ,
663 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
664 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
665 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
666 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
667 RegCloseKey(subKey);
670 RegCloseKey(key);
674 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
677 ITypeInfo_Release(tinfo);
680 SysFreeString(name);
684 ITypeLib_ReleaseTLibAttr(ptlib, attr);
686 return res;
690 /******************************************************************************
691 * UnRegisterTypeLib [OLEAUT32.186]
692 * Removes information about a type library from the System Registry
693 * NOTES
695 * RETURNS
696 * Success: S_OK
697 * Failure: Status
699 HRESULT WINAPI UnRegisterTypeLib(
700 REFGUID libid, /* [in] Guid of the library */
701 WORD wVerMajor, /* [in] major version */
702 WORD wVerMinor, /* [in] minor version */
703 LCID lcid, /* [in] locale id */
704 SYSKIND syskind)
706 BSTR tlibPath = NULL;
707 DWORD tmpLength;
708 WCHAR keyName[60];
709 WCHAR subKeyName[50];
710 int result = S_OK;
711 DWORD i = 0;
712 BOOL deleteOtherStuff;
713 HKEY key = NULL;
714 HKEY subKey = NULL;
715 TYPEATTR* typeAttr = NULL;
716 TYPEKIND kind;
717 ITypeInfo* typeInfo = NULL;
718 ITypeLib* typeLib = NULL;
719 int numTypes;
721 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
723 /* Create the path to the key */
724 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
726 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
728 TRACE("Unsupported syskind %i\n", syskind);
729 result = E_INVALIDARG;
730 goto end;
733 /* get the path to the typelib on disk */
734 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
735 result = E_INVALIDARG;
736 goto end;
739 /* Try and open the key to the type library. */
740 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
741 result = E_INVALIDARG;
742 goto end;
745 /* Try and load the type library */
746 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
747 result = TYPE_E_INVALIDSTATE;
748 goto end;
751 /* remove any types registered with this typelib */
752 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
753 for (i=0; i<numTypes; i++) {
754 /* get the kind of type */
755 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
756 goto enddeleteloop;
759 /* skip non-interfaces, and get type info for the type */
760 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
761 goto enddeleteloop;
763 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
764 goto enddeleteloop;
766 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
767 goto enddeleteloop;
770 /* the path to the type */
771 get_interface_key( &typeAttr->guid, subKeyName );
773 /* Delete its bits */
774 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
775 goto enddeleteloop;
777 RegDeleteKeyW(subKey, ProxyStubClsidW);
778 RegDeleteKeyW(subKey, ProxyStubClsid32W);
779 RegDeleteKeyW(subKey, TypeLibW);
780 RegCloseKey(subKey);
781 subKey = NULL;
782 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
784 enddeleteloop:
785 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
786 typeAttr = NULL;
787 if (typeInfo) ITypeInfo_Release(typeInfo);
788 typeInfo = NULL;
791 /* Now, delete the type library path subkey */
792 get_lcid_subkey( lcid, syskind, subKeyName );
793 RegDeleteKeyW(key, subKeyName);
794 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
795 RegDeleteKeyW(key, subKeyName);
797 /* check if there is anything besides the FLAGS/HELPDIR keys.
798 If there is, we don't delete them */
799 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
800 deleteOtherStuff = TRUE;
801 i = 0;
802 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
803 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
805 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
806 if (!strcmpW(subKeyName, FLAGSW)) continue;
807 if (!strcmpW(subKeyName, HELPDIRW)) continue;
808 deleteOtherStuff = FALSE;
809 break;
812 /* only delete the other parts of the key if we're absolutely sure */
813 if (deleteOtherStuff) {
814 RegDeleteKeyW(key, FLAGSW);
815 RegDeleteKeyW(key, HELPDIRW);
816 RegCloseKey(key);
817 key = NULL;
819 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
820 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
821 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
824 end:
825 if (tlibPath) SysFreeString(tlibPath);
826 if (typeLib) ITypeLib_Release(typeLib);
827 if (subKey) RegCloseKey(subKey);
828 if (key) RegCloseKey(key);
829 return result;
832 /*======================= ITypeLib implementation =======================*/
834 typedef struct tagTLBCustData
836 GUID guid;
837 VARIANT data;
838 struct tagTLBCustData* next;
839 } TLBCustData;
841 /* data structure for import typelibs */
842 typedef struct tagTLBImpLib
844 int offset; /* offset in the file (MSFT)
845 offset in nametable (SLTG)
846 just used to identify library while reading
847 data from file */
848 GUID guid; /* libid */
849 BSTR name; /* name */
851 LCID lcid; /* lcid of imported typelib */
853 WORD wVersionMajor; /* major version number */
854 WORD wVersionMinor; /* minor version number */
856 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
857 NULL if not yet loaded */
858 struct tagTLBImpLib * next;
859 } TLBImpLib;
861 /* internal ITypeLib data */
862 typedef struct tagITypeLibImpl
864 const ITypeLib2Vtbl *lpVtbl;
865 const ITypeCompVtbl *lpVtblTypeComp;
866 ULONG ref;
867 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
869 /* strings can be stored in tlb as multibyte strings BUT they are *always*
870 * exported to the application as a UNICODE string.
872 BSTR Name;
873 BSTR DocString;
874 BSTR HelpFile;
875 BSTR HelpStringDll;
876 unsigned long dwHelpContext;
877 int TypeInfoCount; /* nr of typeinfo's in librarry */
878 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
879 int ctCustData; /* number of items in cust data list */
880 TLBCustData * pCustData; /* linked list to cust data */
881 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
882 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
883 libary. Only used while read MSFT
884 typelibs */
886 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
887 struct tagITypeLibImpl *next, *prev;
888 WCHAR *path;
889 INT index;
890 } ITypeLibImpl;
892 static const ITypeLib2Vtbl tlbvt;
893 static const ITypeCompVtbl tlbtcvt;
895 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
896 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
898 /* ITypeLib methods */
899 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
900 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
902 /*======================= ITypeInfo implementation =======================*/
904 /* data for referenced types */
905 typedef struct tagTLBRefType
907 INT index; /* Type index for internal ref or for external ref
908 it the format is SLTG. -2 indicates to
909 use guid */
911 GUID guid; /* guid of the referenced type */
912 /* if index == TLB_REF_USE_GUID */
914 HREFTYPE reference; /* The href of this ref */
915 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
916 TLB_REF_INTERNAL for internal refs
917 TLB_REF_NOT_FOUND for broken refs */
919 struct tagTLBRefType * next;
920 } TLBRefType;
922 #define TLB_REF_USE_GUID -2
924 #define TLB_REF_INTERNAL (void*)-2
925 #define TLB_REF_NOT_FOUND (void*)-1
927 /* internal Parameter data */
928 typedef struct tagTLBParDesc
930 BSTR Name;
931 int ctCustData;
932 TLBCustData * pCustData; /* linked list to cust data */
933 } TLBParDesc;
935 /* internal Function data */
936 typedef struct tagTLBFuncDesc
938 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
939 BSTR Name; /* the name of this function */
940 TLBParDesc *pParamDesc; /* array with param names and custom data */
941 int helpcontext;
942 int HelpStringContext;
943 BSTR HelpString;
944 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
945 int ctCustData;
946 TLBCustData * pCustData; /* linked list to cust data; */
947 struct tagTLBFuncDesc * next;
948 } TLBFuncDesc;
950 /* internal Variable data */
951 typedef struct tagTLBVarDesc
953 VARDESC vardesc; /* lots of info on the variable and its attributes. */
954 BSTR Name; /* the name of this variable */
955 int HelpContext;
956 int HelpStringContext; /* FIXME: where? */
957 BSTR HelpString;
958 int ctCustData;
959 TLBCustData * pCustData;/* linked list to cust data; */
960 struct tagTLBVarDesc * next;
961 } TLBVarDesc;
963 /* internal implemented interface data */
964 typedef struct tagTLBImplType
966 HREFTYPE hRef; /* hRef of interface */
967 int implflags; /* IMPLFLAG_*s */
968 int ctCustData;
969 TLBCustData * pCustData;/* linked list to custom data; */
970 struct tagTLBImplType *next;
971 } TLBImplType;
973 /* internal TypeInfo data */
974 typedef struct tagITypeInfoImpl
976 const ITypeInfo2Vtbl *lpVtbl;
977 const ITypeCompVtbl *lpVtblTypeComp;
978 ULONG ref;
979 TYPEATTR TypeAttr ; /* _lots_ of type information. */
980 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
981 int index; /* index in this typelib; */
982 /* type libs seem to store the doc strings in ascii
983 * so why should we do it in unicode?
985 BSTR Name;
986 BSTR DocString;
987 unsigned long dwHelpContext;
988 unsigned long dwHelpStringContext;
990 /* functions */
991 TLBFuncDesc * funclist; /* linked list with function descriptions */
993 /* variables */
994 TLBVarDesc * varlist; /* linked list with variable descriptions */
996 /* Implemented Interfaces */
997 TLBImplType * impltypelist;
999 TLBRefType * reflist;
1000 int ctCustData;
1001 TLBCustData * pCustData; /* linked list to cust data; */
1002 struct tagITypeInfoImpl * next;
1003 } ITypeInfoImpl;
1005 static const ITypeInfo2Vtbl tinfvt;
1006 static const ITypeCompVtbl tcompvt;
1008 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1010 typedef struct tagTLBContext
1012 unsigned int oStart; /* start of TLB in file */
1013 unsigned int pos; /* current pos */
1014 unsigned int length; /* total length */
1015 void *mapping; /* memory mapping */
1016 MSFT_SegDir * pTblDir;
1017 ITypeLibImpl* pLibInfo;
1018 } TLBContext;
1021 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1024 debug
1026 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1027 if (pTD->vt & VT_RESERVED)
1028 szVarType += strlen(strcpy(szVarType, "reserved | "));
1029 if (pTD->vt & VT_BYREF)
1030 szVarType += strlen(strcpy(szVarType, "ref to "));
1031 if (pTD->vt & VT_ARRAY)
1032 szVarType += strlen(strcpy(szVarType, "array of "));
1033 if (pTD->vt & VT_VECTOR)
1034 szVarType += strlen(strcpy(szVarType, "vector of "));
1035 switch(pTD->vt & VT_TYPEMASK) {
1036 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1037 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1038 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1039 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1040 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1041 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1042 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1043 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1044 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1045 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1046 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1047 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1048 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1049 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1050 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1051 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1052 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1053 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1054 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1055 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1056 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1057 pTD->u.hreftype); break;
1058 case VT_PTR: sprintf(szVarType, "ptr to ");
1059 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1060 break;
1061 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1062 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1063 break;
1064 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1065 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1066 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1067 break;
1069 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1073 void dump_ELEMDESC(ELEMDESC *edesc) {
1074 char buf[200];
1075 dump_TypeDesc(&edesc->tdesc,buf);
1076 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1077 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
1078 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1080 void dump_FUNCDESC(FUNCDESC *funcdesc) {
1081 int i;
1082 MESSAGE("memid is %08lx\n",funcdesc->memid);
1083 for (i=0;i<funcdesc->cParams;i++) {
1084 MESSAGE("Param %d:\n",i);
1085 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1087 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1088 switch (funcdesc->funckind) {
1089 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1090 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1091 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1092 case FUNC_STATIC: MESSAGE("static");break;
1093 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1094 default: MESSAGE("unknown");break;
1096 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1097 switch (funcdesc->invkind) {
1098 case INVOKE_FUNC: MESSAGE("func");break;
1099 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1100 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1101 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1103 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1104 switch (funcdesc->callconv) {
1105 case CC_CDECL: MESSAGE("cdecl");break;
1106 case CC_PASCAL: MESSAGE("pascal");break;
1107 case CC_STDCALL: MESSAGE("stdcall");break;
1108 case CC_SYSCALL: MESSAGE("syscall");break;
1109 default:break;
1111 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1112 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1113 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1115 MESSAGE("\telemdescFunc (return value type):\n");
1116 dump_ELEMDESC(&funcdesc->elemdescFunc);
1119 void dump_IDLDESC(IDLDESC *idl) {
1120 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
1123 static const char * typekind_desc[] =
1125 "TKIND_ENUM",
1126 "TKIND_RECORD",
1127 "TKIND_MODULE",
1128 "TKIND_INTERFACE",
1129 "TKIND_DISPATCH",
1130 "TKIND_COCLASS",
1131 "TKIND_ALIAS",
1132 "TKIND_UNION",
1133 "TKIND_MAX"
1136 void dump_TYPEATTR(TYPEATTR *tattr) {
1137 char buf[200];
1138 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
1139 MESSAGE("\tlcid: %ld\n",tattr->lcid);
1140 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
1141 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
1142 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
1143 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
1144 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
1145 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
1146 MESSAGE("\tcVars: %d\n", tattr->cVars);
1147 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
1148 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
1149 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
1150 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
1151 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
1152 dump_TypeDesc(&tattr->tdescAlias,buf);
1153 MESSAGE("\ttypedesc: %s\n", buf);
1154 dump_IDLDESC(&tattr->idldescType);
1157 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1159 int i;
1160 if (!TRACE_ON(typelib))
1161 return;
1162 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1163 for (i=0;i<pfd->funcdesc.cParams;i++)
1164 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1167 dump_FUNCDESC(&(pfd->funcdesc));
1169 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1170 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1172 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1174 while (pfd)
1176 dump_TLBFuncDescOne(pfd);
1177 pfd = pfd->next;
1180 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1182 while (pvd)
1184 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1185 pvd = pvd->next;
1189 static void dump_TLBImpLib(TLBImpLib *import)
1191 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1192 debugstr_w(import->name));
1193 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1194 import->wVersionMinor, import->lcid, import->offset);
1197 static void dump_TLBRefType(TLBRefType * prt)
1199 while (prt)
1201 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1202 if(prt->index == -1)
1203 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1204 else
1205 TRACE_(typelib)("type no: %d\n", prt->index);
1207 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1208 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1209 TRACE_(typelib)("in lib\n");
1210 dump_TLBImpLib(prt->pImpTLInfo);
1212 prt = prt->next;
1216 static void dump_TLBImplType(TLBImplType * impl)
1218 while (impl) {
1219 TRACE_(typelib)(
1220 "implementing/inheriting interface hRef = %lx implflags %x\n",
1221 impl->hRef, impl->implflags);
1222 impl = impl->next;
1226 void dump_Variant(VARIANT * pvar)
1228 SYSTEMTIME st;
1230 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1232 if (pvar)
1234 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1235 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1237 TRACE(",%p", V_BYREF(pvar));
1239 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1241 TRACE(",FIXME");
1243 else switch (V_TYPE(pvar))
1245 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1246 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1247 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1248 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1249 case VT_INT:
1250 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1251 case VT_UINT:
1252 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1253 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1254 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1255 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1256 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1257 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1258 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1259 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1260 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1261 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1262 V_CY(pvar).s.Lo); break;
1263 case VT_DATE:
1264 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1265 TRACE(",<invalid>");
1266 else
1267 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1268 st.wHour, st.wMinute, st.wSecond);
1269 break;
1270 case VT_ERROR:
1271 case VT_VOID:
1272 case VT_USERDEFINED:
1273 case VT_EMPTY:
1274 case VT_NULL: break;
1275 default: TRACE(",?"); break;
1278 TRACE("}\n");
1281 static void dump_DispParms(DISPPARAMS * pdp)
1283 int index = 0;
1285 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1287 while (index < pdp->cArgs)
1289 dump_Variant( &pdp->rgvarg[index] );
1290 ++index;
1294 static void dump_TypeInfo(ITypeInfoImpl * pty)
1296 TRACE("%p ref=%lu\n", pty, pty->ref);
1297 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1298 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1299 TRACE("fct:%u var:%u impl:%u\n",
1300 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1301 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1302 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1303 dump_TLBFuncDesc(pty->funclist);
1304 dump_TLBVarDesc(pty->varlist);
1305 dump_TLBImplType(pty->impltypelist);
1308 void dump_VARDESC(VARDESC *v)
1310 MESSAGE("memid %ld\n",v->memid);
1311 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1312 MESSAGE("oInst %ld\n",v->u.oInst);
1313 dump_ELEMDESC(&(v->elemdescVar));
1314 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1315 MESSAGE("varkind %d\n",v->varkind);
1318 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1320 /* VT_LPWSTR is largest type that */
1321 /* may appear in type description*/
1322 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1323 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1324 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1325 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1326 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1327 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1328 {{0},30},{{0},31}
1331 static void TLB_abort()
1333 DebugBreak();
1335 static void * TLB_Alloc(unsigned size)
1337 void * ret;
1338 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1339 /* FIXME */
1340 ERR("cannot allocate memory\n");
1342 return ret;
1345 static void TLB_Free(void * ptr)
1347 HeapFree(GetProcessHeap(), 0, ptr);
1350 /* deep copy a typedesc */
1351 static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in)
1353 out->vt = in->vt;
1354 switch(in->vt) {
1355 case VT_PTR:
1356 out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC));
1357 copy_typedesc(out->u.lptdesc, in->u.lptdesc);
1358 break;
1359 case VT_USERDEFINED:
1360 out->u.hreftype = in->u.hreftype;
1361 break;
1362 case VT_CARRAY:
1363 out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) +
1364 (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND));
1365 copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem);
1366 out->u.lpadesc->cDims = in->u.lpadesc->cDims;
1367 memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND));
1368 break;
1369 default:
1370 break;
1374 /* free()s any allocated memory pointed to by the tdesc. NB does not
1375 free the tdesc itself - this is because the tdesc is typically part
1376 of a larger structure */
1377 static void free_deep_typedesc(TYPEDESC *tdesc)
1379 switch(tdesc->vt) {
1380 case VT_PTR:
1381 free_deep_typedesc(tdesc->u.lptdesc);
1382 HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc);
1383 tdesc->u.lptdesc = NULL;
1384 break;
1385 case VT_CARRAY:
1386 free_deep_typedesc(&tdesc->u.lpadesc->tdescElem);
1387 HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc);
1388 tdesc->u.lpadesc = NULL;
1389 break;
1390 default:
1391 break;
1395 /**********************************************************************
1397 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1399 /* read function */
1400 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1402 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1403 pcx->pos, count, pcx->oStart, pcx->length, where);
1405 if (where != DO_NOT_SEEK)
1407 where += pcx->oStart;
1408 if (where > pcx->length)
1410 /* FIXME */
1411 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1412 TLB_abort();
1414 pcx->pos = where;
1416 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1417 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1418 pcx->pos += count;
1419 return count;
1422 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1423 long where )
1425 DWORD ret;
1427 ret = MSFT_Read(buffer, count, pcx, where);
1428 FromLEDWords(buffer, ret);
1430 return ret;
1433 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1434 long where )
1436 DWORD ret;
1438 ret = MSFT_Read(buffer, count, pcx, where);
1439 FromLEWords(buffer, ret);
1441 return ret;
1444 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1446 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1447 memset(pGuid,0, sizeof(GUID));
1448 return;
1450 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1451 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1452 pGuid->Data2 = FromLEWord(pGuid->Data2);
1453 pGuid->Data3 = FromLEWord(pGuid->Data3);
1454 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1457 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1459 char * name;
1460 MSFT_NameIntro niName;
1461 int lengthInChars;
1462 WCHAR* pwstring = NULL;
1463 BSTR bstrName = NULL;
1465 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1466 pcx->pTblDir->pNametab.offset+offset);
1467 niName.namelen &= 0xFF; /* FIXME: correct ? */
1468 name=TLB_Alloc((niName.namelen & 0xff) +1);
1469 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1470 name[niName.namelen & 0xff]='\0';
1472 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1473 name, -1, NULL, 0);
1475 /* no invalid characters in string */
1476 if (lengthInChars)
1478 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1480 /* don't check for invalid character since this has been done previously */
1481 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1483 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1484 lengthInChars = SysStringLen(bstrName);
1485 HeapFree(GetProcessHeap(), 0, pwstring);
1488 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1489 return bstrName;
1492 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1494 char * string;
1495 INT16 length;
1496 int lengthInChars;
1497 BSTR bstr = NULL;
1499 if(offset<0) return NULL;
1500 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1501 if(length <= 0) return 0;
1502 string=TLB_Alloc(length +1);
1503 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1504 string[length]='\0';
1506 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1507 string, -1, NULL, 0);
1509 /* no invalid characters in string */
1510 if (lengthInChars)
1512 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1514 /* don't check for invalid character since this has been done previously */
1515 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1517 bstr = SysAllocStringLen(pwstring, lengthInChars);
1518 lengthInChars = SysStringLen(bstr);
1519 HeapFree(GetProcessHeap(), 0, pwstring);
1522 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1523 return bstr;
1526 * read a value and fill a VARIANT structure
1528 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1530 int size;
1532 TRACE_(typelib)("\n");
1534 if(offset <0) { /* data are packed in here */
1535 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1536 V_I2(pVar) = offset & 0x3ffffff;
1537 return;
1539 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1540 pcx->pTblDir->pCustData.offset + offset );
1541 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1542 switch (V_VT(pVar)){
1543 case VT_EMPTY: /* FIXME: is this right? */
1544 case VT_NULL: /* FIXME: is this right? */
1545 case VT_I2 : /* this should not happen */
1546 case VT_I4 :
1547 case VT_R4 :
1548 case VT_ERROR :
1549 case VT_BOOL :
1550 case VT_I1 :
1551 case VT_UI1 :
1552 case VT_UI2 :
1553 case VT_UI4 :
1554 case VT_INT :
1555 case VT_UINT :
1556 case VT_VOID : /* FIXME: is this right? */
1557 case VT_HRESULT :
1558 size=4; break;
1559 case VT_R8 :
1560 case VT_CY :
1561 case VT_DATE :
1562 case VT_I8 :
1563 case VT_UI8 :
1564 case VT_DECIMAL : /* FIXME: is this right? */
1565 case VT_FILETIME :
1566 size=8;break;
1567 /* pointer types with known behaviour */
1568 case VT_BSTR :{
1569 char * ptr;
1570 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1571 if(size < 0) {
1572 FIXME("BSTR length = %d?\n", size);
1573 } else {
1574 ptr=TLB_Alloc(size);/* allocate temp buffer */
1575 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1576 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1577 /* FIXME: do we need a AtoW conversion here? */
1578 V_UNION(pVar, bstrVal[size])=L'\0';
1579 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1580 TLB_Free(ptr);
1583 size=-4; break;
1584 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1585 case VT_DISPATCH :
1586 case VT_VARIANT :
1587 case VT_UNKNOWN :
1588 case VT_PTR :
1589 case VT_SAFEARRAY :
1590 case VT_CARRAY :
1591 case VT_USERDEFINED :
1592 case VT_LPSTR :
1593 case VT_LPWSTR :
1594 case VT_BLOB :
1595 case VT_STREAM :
1596 case VT_STORAGE :
1597 case VT_STREAMED_OBJECT :
1598 case VT_STORED_OBJECT :
1599 case VT_BLOB_OBJECT :
1600 case VT_CF :
1601 case VT_CLSID :
1602 default:
1603 size=0;
1604 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1605 V_VT(pVar));
1608 if(size>0) /* (big|small) endian correct? */
1609 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1610 return;
1613 * create a linked list with custom data
1615 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1617 MSFT_CDGuid entry;
1618 TLBCustData* pNew;
1619 int count=0;
1621 TRACE_(typelib)("\n");
1623 while(offset >=0){
1624 count++;
1625 pNew=TLB_Alloc(sizeof(TLBCustData));
1626 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1627 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1628 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1629 /* add new custom data at head of the list */
1630 pNew->next=*ppCustData;
1631 *ppCustData=pNew;
1632 offset = entry.next;
1634 return count;
1637 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1638 ITypeInfoImpl *pTI)
1640 if(type <0)
1641 pTd->vt=type & VT_TYPEMASK;
1642 else
1643 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1645 if(pTd->vt == VT_USERDEFINED)
1646 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1648 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1651 static void
1652 MSFT_DoFuncs(TLBContext* pcx,
1653 ITypeInfoImpl* pTI,
1654 int cFuncs,
1655 int cVars,
1656 int offset,
1657 TLBFuncDesc** pptfd)
1660 * member information is stored in a data structure at offset
1661 * indicated by the memoffset field of the typeinfo structure
1662 * There are several distinctive parts.
1663 * The first part starts with a field that holds the total length
1664 * of this (first) part excluding this field. Then follow the records,
1665 * for each member there is one record.
1667 * The first entry is always the length of the record (including this
1668 * length word).
1669 * The rest of the record depends on the type of the member. If there is
1670 * a field indicating the member type (function, variable, interface, etc)
1671 * I have not found it yet. At this time we depend on the information
1672 * in the type info and the usual order how things are stored.
1674 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1675 * for each member;
1677 * Third is an equal sized array with file offsets to the name entry
1678 * of each member.
1680 * The fourth and last (?) part is an array with offsets to the records
1681 * in the first part of this file segment.
1684 int infolen, nameoffset, reclength, nrattributes, i;
1685 int recoffset = offset + sizeof(INT);
1687 char recbuf[512];
1688 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1690 TRACE_(typelib)("\n");
1692 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1694 for ( i = 0; i < cFuncs ; i++ )
1696 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1698 /* name, eventually add to a hash table */
1699 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1700 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1702 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1704 /* read the function information record */
1705 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1707 reclength &= 0x1ff;
1709 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1711 /* do the attributes */
1712 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1713 / sizeof(int);
1715 if ( nrattributes > 0 )
1717 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1719 if ( nrattributes > 1 )
1721 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1722 pFuncRec->OptAttr[1]) ;
1724 if ( nrattributes > 2 )
1726 if ( pFuncRec->FKCCIC & 0x2000 )
1728 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1730 else
1732 (*pptfd)->Entry = MSFT_ReadString(pcx,
1733 pFuncRec->OptAttr[2]);
1735 if( nrattributes > 5 )
1737 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1739 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1741 MSFT_CustData(pcx,
1742 pFuncRec->OptAttr[6],
1743 &(*pptfd)->pCustData);
1750 /* fill the FuncDesc Structure */
1751 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1752 offset + infolen + ( i + 1) * sizeof(INT));
1754 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1755 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1756 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1757 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1758 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1759 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1760 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1762 MSFT_GetTdesc(pcx,
1763 pFuncRec->DataType,
1764 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1765 pTI);
1767 /* do the parameters/arguments */
1768 if(pFuncRec->nrargs)
1770 int j = 0;
1771 MSFT_ParameterInfo paraminfo;
1773 (*pptfd)->funcdesc.lprgelemdescParam =
1774 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1776 (*pptfd)->pParamDesc =
1777 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1779 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1780 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1782 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1784 TYPEDESC* lpArgTypeDesc = 0;
1786 MSFT_GetTdesc(pcx,
1787 paraminfo.DataType,
1788 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1789 pTI);
1791 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1793 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1795 /* SEEK value = jump to offset,
1796 * from there jump to the end of record,
1797 * go back by (j-1) arguments
1799 MSFT_ReadLEDWords( &paraminfo ,
1800 sizeof(MSFT_ParameterInfo), pcx,
1801 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1802 * sizeof(MSFT_ParameterInfo)));
1803 lpArgTypeDesc =
1804 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1806 while ( lpArgTypeDesc != NULL )
1808 switch ( lpArgTypeDesc->vt )
1810 case VT_PTR:
1811 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1812 break;
1814 case VT_CARRAY:
1815 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1816 break;
1818 case VT_USERDEFINED:
1819 MSFT_DoRefType(pcx, pTI,
1820 lpArgTypeDesc->u.hreftype);
1822 lpArgTypeDesc = NULL;
1823 break;
1825 default:
1826 lpArgTypeDesc = NULL;
1832 /* parameter is the return value! */
1833 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1835 TYPEDESC* lpArgTypeDesc;
1837 (*pptfd)->funcdesc.elemdescFunc =
1838 (*pptfd)->funcdesc.lprgelemdescParam[j];
1840 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1842 while ( lpArgTypeDesc != NULL )
1844 switch ( lpArgTypeDesc->vt )
1846 case VT_PTR:
1847 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1848 break;
1849 case VT_CARRAY:
1850 lpArgTypeDesc =
1851 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1853 break;
1855 case VT_USERDEFINED:
1856 MSFT_DoRefType(pcx,
1857 pTI,
1858 lpArgTypeDesc->u.hreftype);
1860 lpArgTypeDesc = NULL;
1861 break;
1863 default:
1864 lpArgTypeDesc = NULL;
1869 /* second time around */
1870 for(j=0;j<pFuncRec->nrargs;j++)
1872 /* name */
1873 (*pptfd)->pParamDesc[j].Name =
1874 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1876 /* default value */
1877 if ( (PARAMFLAG_FHASDEFAULT &
1878 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1879 ((pFuncRec->FKCCIC) & 0x1000) )
1881 INT* pInt = (INT *)((char *)pFuncRec +
1882 reclength -
1883 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1885 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1887 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1888 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1890 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1891 pInt[j], pcx);
1893 /* custom info */
1894 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1896 MSFT_CustData(pcx,
1897 pFuncRec->OptAttr[7+j],
1898 &(*pptfd)->pParamDesc[j].pCustData);
1903 /* scode is not used: archaic win16 stuff FIXME: right? */
1904 (*pptfd)->funcdesc.cScodes = 0 ;
1905 (*pptfd)->funcdesc.lprgscode = NULL ;
1907 pptfd = & ((*pptfd)->next);
1908 recoffset += reclength;
1912 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1913 int cVars, int offset, TLBVarDesc ** pptvd)
1915 int infolen, nameoffset, reclength;
1916 char recbuf[256];
1917 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1918 int i;
1919 int recoffset;
1921 TRACE_(typelib)("\n");
1923 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1924 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1925 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1926 recoffset += offset+sizeof(INT);
1927 for(i=0;i<cVars;i++){
1928 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1929 /* name, eventually add to a hash table */
1930 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1931 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1932 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1933 /* read the variable information record */
1934 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1935 reclength &=0xff;
1936 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1937 /* Optional data */
1938 if(reclength >(6*sizeof(INT)) )
1939 (*pptvd)->HelpContext=pVarRec->HelpContext;
1940 if(reclength >(7*sizeof(INT)) )
1941 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1942 if(reclength >(8*sizeof(INT)) )
1943 if(reclength >(9*sizeof(INT)) )
1944 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1945 /* fill the VarDesc Structure */
1946 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1947 offset + infolen + ( i + 1) * sizeof(INT));
1948 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1949 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1950 MSFT_GetTdesc(pcx, pVarRec->DataType,
1951 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1952 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1953 if(pVarRec->VarKind == VAR_CONST ){
1954 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1955 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1956 pVarRec->OffsValue, pcx);
1957 } else
1958 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1959 pptvd=&((*pptvd)->next);
1960 recoffset += reclength;
1963 /* fill in data for a hreftype (offset). When the referenced type is contained
1964 * in the typelib, it's just an (file) offset in the type info base dir.
1965 * If comes from import, it's an offset+1 in the ImpInfo table
1966 * */
1967 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1968 int offset)
1970 int j;
1971 TLBRefType **ppRefType = &pTI->reflist;
1973 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1975 while(*ppRefType) {
1976 if((*ppRefType)->reference == offset)
1977 return;
1978 ppRefType = &(*ppRefType)->next;
1981 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1982 sizeof(**ppRefType));
1984 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1985 /* external typelib */
1986 MSFT_ImpInfo impinfo;
1987 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1989 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1991 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1992 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1993 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1994 if(pImpLib->offset==impinfo.oImpFile) break;
1995 pImpLib=pImpLib->next;
1997 if(pImpLib){
1998 (*ppRefType)->reference=offset;
1999 (*ppRefType)->pImpTLInfo = pImpLib;
2000 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
2001 (*ppRefType)->index = TLB_REF_USE_GUID;
2002 }else{
2003 ERR("Cannot find a reference\n");
2004 (*ppRefType)->reference=-1;
2005 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2007 }else{
2008 /* in this typelib */
2009 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2010 (*ppRefType)->reference=offset;
2011 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2015 /* process Implemented Interfaces of a com class */
2016 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2017 int offset)
2019 int i;
2020 MSFT_RefRecord refrec;
2021 TLBImplType **ppImpl = &pTI->impltypelist;
2023 TRACE_(typelib)("\n");
2025 for(i=0;i<count;i++){
2026 if(offset<0) break; /* paranoia */
2027 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2028 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2029 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2030 (*ppImpl)->hRef = refrec.reftype;
2031 (*ppImpl)->implflags=refrec.flags;
2032 (*ppImpl)->ctCustData=
2033 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2034 offset=refrec.onext;
2035 ppImpl=&((*ppImpl)->next);
2039 * process a typeinfo record
2041 ITypeInfoImpl * MSFT_DoTypeInfo(
2042 TLBContext *pcx,
2043 int count,
2044 ITypeLibImpl * pLibInfo)
2046 MSFT_TypeInfoBase tiBase;
2047 ITypeInfoImpl *ptiRet;
2049 TRACE_(typelib)("count=%u\n", count);
2051 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2052 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2053 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2054 /* this is where we are coming from */
2055 ptiRet->pTypeLib = pLibInfo;
2056 ptiRet->index=count;
2057 /* fill in the typeattr fields */
2058 WARN("Assign constructor/destructor memid\n");
2060 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2061 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2062 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2063 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2064 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2065 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2066 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2067 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2068 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2069 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2070 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2071 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2072 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2073 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2074 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2075 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2076 MSFT_GetTdesc(pcx, tiBase.datatype1,
2077 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2079 /* FIXME: */
2080 /* IDLDESC idldescType; *//* never saw this one != zero */
2082 /* name, eventually add to a hash table */
2083 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2084 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2085 /* help info */
2086 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2087 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2088 ptiRet->dwHelpContext=tiBase.helpcontext;
2089 /* note: InfoType's Help file and HelpStringDll come from the containing
2090 * library. Further HelpString and Docstring appear to be the same thing :(
2092 /* functions */
2093 if(ptiRet->TypeAttr.cFuncs >0 )
2094 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2095 ptiRet->TypeAttr.cVars,
2096 tiBase.memoffset, & ptiRet->funclist);
2097 /* variables */
2098 if(ptiRet->TypeAttr.cVars >0 )
2099 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2100 ptiRet->TypeAttr.cVars,
2101 tiBase.memoffset, & ptiRet->varlist);
2102 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2103 switch(ptiRet->TypeAttr.typekind)
2105 case TKIND_COCLASS:
2106 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2107 tiBase.datatype1);
2108 break;
2109 case TKIND_DISPATCH:
2110 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2112 if (tiBase.datatype1 != -1)
2114 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2115 ptiRet->impltypelist->hRef = tiBase.datatype1;
2117 else
2118 { /* FIXME: This is a really bad hack to add IDispatch */
2119 const char* szStdOle = "stdole2.tlb\0";
2120 int nStdOleLen = strlen(szStdOle);
2121 TLBRefType **ppRef = &ptiRet->reflist;
2123 while(*ppRef) {
2124 if((*ppRef)->reference == -1)
2125 break;
2126 ppRef = &(*ppRef)->next;
2128 if(!*ppRef) {
2129 *ppRef = TLB_Alloc(sizeof(**ppRef));
2130 (*ppRef)->guid = IID_IDispatch;
2131 (*ppRef)->reference = -1;
2132 (*ppRef)->index = TLB_REF_USE_GUID;
2133 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2134 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2135 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2136 nStdOleLen + 1);
2138 MultiByteToWideChar(CP_ACP,
2139 MB_PRECOMPOSED,
2140 szStdOle,
2142 (*ppRef)->pImpTLInfo->name,
2143 SysStringLen((*ppRef)->pImpTLInfo->name));
2145 (*ppRef)->pImpTLInfo->lcid = 0;
2146 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2147 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2150 break;
2151 default:
2152 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2153 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2154 ptiRet->impltypelist->hRef = tiBase.datatype1;
2155 break;
2158 ptiRet->ctCustData=
2159 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2161 TRACE_(typelib)("%s guid: %s kind:%s\n",
2162 debugstr_w(ptiRet->Name),
2163 debugstr_guid(&ptiRet->TypeAttr.guid),
2164 typekind_desc[ptiRet->TypeAttr.typekind]);
2166 return ptiRet;
2169 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2170 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2171 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2172 * tradeoff here.
2174 static ITypeLibImpl *tlb_cache_first;
2175 static CRITICAL_SECTION cache_section;
2176 static CRITICAL_SECTION_DEBUG cache_section_debug =
2178 0, 0, &cache_section,
2179 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2180 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
2182 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2185 /****************************************************************************
2186 * TLB_ReadTypeLib
2188 * find the type of the typelib file and map the typelib resource into
2189 * the memory
2191 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2192 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2193 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2195 ITypeLibImpl *entry;
2196 int ret = TYPE_E_CANTLOADLIBRARY;
2197 DWORD dwSignature = 0;
2198 HANDLE hFile;
2200 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2202 *ppTypeLib = NULL;
2204 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2205 EnterCriticalSection(&cache_section);
2206 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2208 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2210 TRACE("cache hit\n");
2211 *ppTypeLib = (ITypeLib2*)entry;
2212 ITypeLib_AddRef(*ppTypeLib);
2213 LeaveCriticalSection(&cache_section);
2214 return S_OK;
2217 LeaveCriticalSection(&cache_section);
2219 /* check the signature of the file */
2220 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2221 if (INVALID_HANDLE_VALUE != hFile)
2223 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2224 if (hMapping)
2226 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2227 if(pBase)
2229 /* retrieve file size */
2230 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2232 /* first try to load as *.tlb */
2233 dwSignature = FromLEDWord(*((DWORD*) pBase));
2234 if ( dwSignature == MSFT_SIGNATURE)
2236 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2238 else if ( dwSignature == SLTG_SIGNATURE)
2240 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2242 UnmapViewOfFile(pBase);
2244 CloseHandle(hMapping);
2246 CloseHandle(hFile);
2248 else
2250 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2253 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2254 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2256 /* find the typelibrary resource*/
2257 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2258 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2259 if (hinstDLL)
2261 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2262 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2263 if (hrsrc)
2265 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2266 if (hGlobal)
2268 LPVOID pBase = LockResource(hGlobal);
2269 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2271 if (pBase)
2273 /* try to load as incore resource */
2274 dwSignature = FromLEDWord(*((DWORD*) pBase));
2275 if ( dwSignature == MSFT_SIGNATURE)
2277 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2279 else if ( dwSignature == SLTG_SIGNATURE)
2281 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2283 else
2285 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2288 FreeResource( hGlobal );
2291 FreeLibrary(hinstDLL);
2295 if(*ppTypeLib) {
2296 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2298 TRACE("adding to cache\n");
2299 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2300 lstrcpyW(impl->path, pszFileName);
2301 /* We should really canonicalise the path here. */
2302 impl->index = index;
2304 /* FIXME: check if it has added already in the meantime */
2305 EnterCriticalSection(&cache_section);
2306 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2307 impl->prev = NULL;
2308 tlb_cache_first = impl;
2309 LeaveCriticalSection(&cache_section);
2310 ret = S_OK;
2311 } else
2312 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2314 return ret;
2317 /*================== ITypeLib(2) Methods ===================================*/
2319 /****************************************************************************
2320 * ITypeLib2_Constructor_MSFT
2322 * loading an MSFT typelib from an in-memory image
2324 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2326 TLBContext cx;
2327 long lPSegDir;
2328 MSFT_Header tlbHeader;
2329 MSFT_SegDir tlbSegDir;
2330 ITypeLibImpl * pTypeLibImpl;
2332 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2334 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2335 if (!pTypeLibImpl) return NULL;
2337 pTypeLibImpl->lpVtbl = &tlbvt;
2338 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2339 pTypeLibImpl->ref = 1;
2341 /* get pointer to beginning of typelib data */
2342 cx.pos = 0;
2343 cx.oStart=0;
2344 cx.mapping = pLib;
2345 cx.pLibInfo = pTypeLibImpl;
2346 cx.length = dwTLBLength;
2348 /* read header */
2349 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2350 TRACE("header:\n");
2351 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2352 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2353 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2354 return NULL;
2356 /* there is a small amount of information here until the next important
2357 * part:
2358 * the segment directory . Try to calculate the amount of data */
2359 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2361 /* now read the segment directory */
2362 TRACE("read segment directory (at %ld)\n",lPSegDir);
2363 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2364 cx.pTblDir = &tlbSegDir;
2366 /* just check two entries */
2367 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2369 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2370 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2371 return NULL;
2374 /* now fill our internal data */
2375 /* TLIBATTR fields */
2376 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2378 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2379 /* Windows seems to have zero here, is this correct? */
2380 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2381 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2382 else
2383 pTypeLibImpl->LibAttr.lcid = 0;
2385 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2386 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2387 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2388 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2390 /* name, eventually add to a hash table */
2391 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2393 /* help info */
2394 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2395 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2397 if( tlbHeader.varflags & HELPDLLFLAG)
2399 int offset;
2400 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2401 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2404 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2406 /* custom data */
2407 if(tlbHeader.CustomDataOffset >= 0)
2409 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2412 /* fill in typedescriptions */
2413 if(tlbSegDir.pTypdescTab.length > 0)
2415 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2416 INT16 td[4];
2417 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2418 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2419 for(i=0; i<cTD; )
2421 /* FIXME: add several sanity checks here */
2422 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2423 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2425 /* FIXME: check safearray */
2426 if(td[3] < 0)
2427 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2428 else
2429 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2431 else if(td[0] == VT_CARRAY)
2433 /* array descr table here */
2434 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2436 else if(td[0] == VT_USERDEFINED)
2438 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2440 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2443 /* second time around to fill the array subscript info */
2444 for(i=0;i<cTD;i++)
2446 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2447 if(tlbSegDir.pArrayDescriptions.offset>0)
2449 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2450 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2452 if(td[1]<0)
2453 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2454 else
2455 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2457 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2459 for(j = 0; j<td[2]; j++)
2461 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2462 sizeof(INT), &cx, DO_NOT_SEEK);
2463 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2464 sizeof(INT), &cx, DO_NOT_SEEK);
2467 else
2469 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2470 ERR("didn't find array description data\n");
2475 /* imported type libs */
2476 if(tlbSegDir.pImpFiles.offset>0)
2478 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2479 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2480 UINT16 size;
2482 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2484 char *name;
2485 DWORD len;
2487 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2488 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2489 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2491 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2492 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2493 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2494 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2496 size >>= 2;
2497 name = TLB_Alloc(size+1);
2498 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2499 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2500 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2501 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2502 TLB_Free(name);
2504 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2505 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2507 ppImpLib = &(*ppImpLib)->next;
2511 /* type info's */
2512 if(tlbHeader.nrtypeinfos >= 0 )
2514 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2515 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2516 int i;
2518 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2520 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2522 ppTI = &((*ppTI)->next);
2523 (pTypeLibImpl->TypeInfoCount)++;
2527 TRACE("(%p)\n", pTypeLibImpl);
2528 return (ITypeLib2*) pTypeLibImpl;
2532 static BSTR TLB_MultiByteToBSTR(char *ptr)
2534 DWORD len;
2535 WCHAR *nameW;
2536 BSTR ret;
2538 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2539 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2540 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2541 ret = SysAllocString(nameW);
2542 HeapFree(GetProcessHeap(), 0, nameW);
2543 return ret;
2546 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2548 char b[3];
2549 int i;
2550 short s;
2552 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2553 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2554 return FALSE;
2557 guid->Data4[0] = s >> 8;
2558 guid->Data4[1] = s & 0xff;
2560 b[2] = '\0';
2561 for(i = 0; i < 6; i++) {
2562 memcpy(b, str + 24 + 2 * i, 2);
2563 guid->Data4[i + 2] = strtol(b, NULL, 16);
2565 return TRUE;
2568 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2570 WORD bytelen;
2571 DWORD len;
2572 WCHAR *nameW;
2574 *pBstr = NULL;
2575 bytelen = *(WORD*)ptr;
2576 if(bytelen == 0xffff) return 2;
2577 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2578 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2579 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2580 *pBstr = SysAllocStringLen(nameW, len);
2581 HeapFree(GetProcessHeap(), 0, nameW);
2582 return bytelen + 2;
2585 static WORD SLTG_ReadStringA(char *ptr, char **str)
2587 WORD bytelen;
2589 *str = NULL;
2590 bytelen = *(WORD*)ptr;
2591 if(bytelen == 0xffff) return 2;
2592 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2593 memcpy(*str, ptr + 2, bytelen);
2594 (*str)[bytelen] = '\0';
2595 return bytelen + 2;
2598 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2600 char *ptr = pLibBlk;
2601 WORD w;
2603 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2604 FIXME("libblk magic = %04x\n", w);
2605 return 0;
2608 ptr += 6;
2609 if((w = *(WORD*)ptr) != 0xffff) {
2610 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2611 ptr += w;
2613 ptr += 2;
2615 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2617 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2619 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2620 ptr += 4;
2622 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2623 ptr += 2;
2625 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2626 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2627 else
2628 pTypeLibImpl->LibAttr.lcid = 0;
2629 ptr += 2;
2631 ptr += 4; /* skip res12 */
2633 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2634 ptr += 2;
2636 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2637 ptr += 2;
2639 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2640 ptr += 2;
2642 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2643 ptr += sizeof(GUID);
2645 return ptr - (char*)pLibBlk;
2648 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2650 BOOL done = FALSE;
2651 TYPEDESC *pTD = &pElem->tdesc;
2653 /* Handle [in/out] first */
2654 if((*pType & 0xc000) == 0xc000)
2655 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2656 else if(*pType & 0x8000)
2657 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2658 else if(*pType & 0x4000)
2659 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2660 else
2661 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2663 if(*pType & 0x2000)
2664 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2666 if(*pType & 0x80)
2667 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2669 while(!done) {
2670 if((*pType & 0xe00) == 0xe00) {
2671 pTD->vt = VT_PTR;
2672 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2673 sizeof(TYPEDESC));
2674 pTD = pTD->u.lptdesc;
2676 switch(*pType & 0x7f) {
2677 case VT_PTR:
2678 pTD->vt = VT_PTR;
2679 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2680 sizeof(TYPEDESC));
2681 pTD = pTD->u.lptdesc;
2682 break;
2684 case VT_USERDEFINED:
2685 pTD->vt = VT_USERDEFINED;
2686 pTD->u.hreftype = *(++pType) / 4;
2687 done = TRUE;
2688 break;
2690 case VT_CARRAY:
2692 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2693 array */
2695 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2697 pTD->vt = VT_CARRAY;
2698 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2699 sizeof(ARRAYDESC) +
2700 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2701 pTD->u.lpadesc->cDims = pSA->cDims;
2702 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2703 pSA->cDims * sizeof(SAFEARRAYBOUND));
2705 pTD = &pTD->u.lpadesc->tdescElem;
2706 break;
2709 case VT_SAFEARRAY:
2711 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2712 useful? */
2714 pType++;
2715 pTD->vt = VT_SAFEARRAY;
2716 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2717 sizeof(TYPEDESC));
2718 pTD = pTD->u.lptdesc;
2719 break;
2721 default:
2722 pTD->vt = *pType & 0x7f;
2723 done = TRUE;
2724 break;
2726 pType++;
2728 return pType;
2732 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2733 char *pNameTable)
2735 int ref;
2736 char *name;
2737 TLBRefType **ppRefType;
2739 if(pRef->magic != SLTG_REF_MAGIC) {
2740 FIXME("Ref magic = %x\n", pRef->magic);
2741 return;
2743 name = ( (char*)(&pRef->names) + pRef->number);
2745 ppRefType = &pTI->reflist;
2746 for(ref = 0; ref < pRef->number >> 3; ref++) {
2747 char *refname;
2748 unsigned int lib_offs, type_num;
2750 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2751 sizeof(**ppRefType));
2753 name += SLTG_ReadStringA(name, &refname);
2754 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2755 FIXME("Can't sscanf ref\n");
2756 if(lib_offs != 0xffff) {
2757 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2759 while(*import) {
2760 if((*import)->offset == lib_offs)
2761 break;
2762 import = &(*import)->next;
2764 if(!*import) {
2765 char fname[MAX_PATH+1];
2766 int len;
2768 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2769 sizeof(**import));
2770 (*import)->offset = lib_offs;
2771 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2772 &(*import)->guid);
2773 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2774 &(*import)->wVersionMajor,
2775 &(*import)->wVersionMinor,
2776 &(*import)->lcid, fname) != 4) {
2777 FIXME("can't sscanf ref %s\n",
2778 pNameTable + lib_offs + 40);
2780 len = strlen(fname);
2781 if(fname[len-1] != '#')
2782 FIXME("fname = %s\n", fname);
2783 fname[len-1] = '\0';
2784 (*import)->name = TLB_MultiByteToBSTR(fname);
2786 (*ppRefType)->pImpTLInfo = *import;
2787 } else { /* internal ref */
2788 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2790 (*ppRefType)->reference = ref;
2791 (*ppRefType)->index = type_num;
2793 HeapFree(GetProcessHeap(), 0, refname);
2794 ppRefType = &(*ppRefType)->next;
2796 if((BYTE)*name != SLTG_REF_MAGIC)
2797 FIXME("End of ref block magic = %x\n", *name);
2798 dump_TLBRefType(pTI->reflist);
2801 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2802 BOOL OneOnly)
2804 SLTG_ImplInfo *info;
2805 TLBImplType **ppImplType = &pTI->impltypelist;
2806 /* I don't really get this structure, usually it's 0x16 bytes
2807 long, but iuser.tlb contains some that are 0x18 bytes long.
2808 That's ok because we can use the next ptr to jump to the next
2809 one. But how do we know the length of the last one? The WORD
2810 at offs 0x8 might be the clue. For now I'm just assuming that
2811 the last one is the regular 0x16 bytes. */
2813 info = (SLTG_ImplInfo*)pBlk;
2814 while(1) {
2815 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2816 sizeof(**ppImplType));
2817 (*ppImplType)->hRef = info->ref;
2818 (*ppImplType)->implflags = info->impltypeflags;
2819 pTI->TypeAttr.cImplTypes++;
2820 ppImplType = &(*ppImplType)->next;
2822 if(info->next == 0xffff)
2823 break;
2824 if(OneOnly)
2825 FIXME("Interface inheriting more than one interface\n");
2826 info = (SLTG_ImplInfo*)(pBlk + info->next);
2828 info++; /* see comment at top of function */
2829 return (char*)info;
2832 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2833 char *pNameTable)
2835 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2836 SLTG_MemberHeader *pMemHeader;
2837 char *pFirstItem, *pNextItem;
2839 if(pTIHeader->href_table != 0xffffffff) {
2840 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2841 pNameTable);
2845 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2847 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2849 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2850 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2853 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2857 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2858 char *pNameTable)
2860 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2861 SLTG_MemberHeader *pMemHeader;
2862 SLTG_Function *pFunc;
2863 char *pFirstItem, *pNextItem;
2864 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2865 int num = 0;
2867 if(pTIHeader->href_table != 0xffffffff) {
2868 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2869 pNameTable);
2872 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2874 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2876 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2877 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2880 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2881 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2883 int param;
2884 WORD *pType, *pArg;
2886 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2887 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2888 FIXME("func magic = %02x\n", pFunc->magic);
2889 return NULL;
2891 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2892 sizeof(**ppFuncDesc));
2893 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2895 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2896 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2897 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2898 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2899 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2900 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2902 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2903 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2905 if(pFunc->retnextopt & 0x80)
2906 pType = &pFunc->rettype;
2907 else
2908 pType = (WORD*)(pFirstItem + pFunc->rettype);
2911 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2913 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2914 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2915 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2916 (*ppFuncDesc)->pParamDesc =
2917 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2918 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2920 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2922 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2923 char *paramName = pNameTable + *pArg;
2924 BOOL HaveOffs;
2925 /* If arg type follows then paramName points to the 2nd
2926 letter of the name, else the next WORD is an offset to
2927 the arg type and paramName points to the first letter.
2928 So let's take one char off paramName and see if we're
2929 pointing at an alpha-numeric char. However if *pArg is
2930 0xffff or 0xfffe then the param has no name, the former
2931 meaning that the next WORD is the type, the latter
2932 meaning the the next WORD is an offset to the type. */
2934 HaveOffs = FALSE;
2935 if(*pArg == 0xffff)
2936 paramName = NULL;
2937 else if(*pArg == 0xfffe) {
2938 paramName = NULL;
2939 HaveOffs = TRUE;
2941 else if(!isalnum(*(paramName-1)))
2942 HaveOffs = TRUE;
2944 pArg++;
2946 if(HaveOffs) { /* the next word is an offset to type */
2947 pType = (WORD*)(pFirstItem + *pArg);
2948 SLTG_DoType(pType, pFirstItem,
2949 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2950 pArg++;
2951 } else {
2952 if(paramName)
2953 paramName--;
2954 pArg = SLTG_DoType(pArg, pFirstItem,
2955 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2958 /* Are we an optional param ? */
2959 if((*ppFuncDesc)->funcdesc.cParams - param <=
2960 (*ppFuncDesc)->funcdesc.cParamsOpt)
2961 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2963 if(paramName) {
2964 (*ppFuncDesc)->pParamDesc[param].Name =
2965 TLB_MultiByteToBSTR(paramName);
2969 ppFuncDesc = &((*ppFuncDesc)->next);
2970 if(pFunc->next == 0xffff) break;
2972 pTI->TypeAttr.cFuncs = num;
2973 dump_TLBFuncDesc(pTI->funclist);
2974 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2977 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2978 char *pNameTable)
2980 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2981 SLTG_MemberHeader *pMemHeader;
2982 SLTG_RecordItem *pItem;
2983 char *pFirstItem;
2984 TLBVarDesc **ppVarDesc = &pTI->varlist;
2985 int num = 0;
2986 WORD *pType;
2987 char buf[300];
2989 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2991 pFirstItem = (char*)(pMemHeader + 1);
2992 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2993 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2994 if(pItem->magic != SLTG_RECORD_MAGIC) {
2995 FIXME("record magic = %02x\n", pItem->magic);
2996 return NULL;
2998 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2999 sizeof(**ppVarDesc));
3000 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3001 (*ppVarDesc)->vardesc.memid = pItem->memid;
3002 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3003 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3005 if(pItem->typepos == 0x02)
3006 pType = &pItem->type;
3007 else if(pItem->typepos == 0x00)
3008 pType = (WORD*)(pFirstItem + pItem->type);
3009 else {
3010 FIXME("typepos = %02x\n", pItem->typepos);
3011 break;
3014 SLTG_DoType(pType, pFirstItem,
3015 &(*ppVarDesc)->vardesc.elemdescVar);
3017 /* FIXME("helpcontext, helpstring\n"); */
3019 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3021 ppVarDesc = &((*ppVarDesc)->next);
3022 if(pItem->next == 0xffff) break;
3024 pTI->TypeAttr.cVars = num;
3025 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3028 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3029 char *pNameTable)
3031 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3032 SLTG_MemberHeader *pMemHeader;
3033 SLTG_AliasItem *pItem;
3034 int i, mustbelast;
3036 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3037 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3039 mustbelast = 0;
3040 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3041 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3042 if (pItem->vt == 0xffff) {
3043 if (i<(pMemHeader->cbExtra/4-1))
3044 FIXME("Endmarker too early in process alias data!\n");
3045 break;
3047 if (mustbelast) {
3048 FIXME("Chain extends over last entry?\n");
3049 break;
3051 if (pItem->vt == VT_USERDEFINED) {
3052 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3053 /* guessing here ... */
3054 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3055 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3056 mustbelast = 1;
3057 } else {
3058 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3059 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3061 pItem++;
3063 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3066 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3067 char *pNameTable)
3069 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3070 SLTG_MemberHeader *pMemHeader;
3071 SLTG_AliasItem *pItem;
3073 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3074 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3075 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3076 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3077 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3080 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3081 char *pNameTable)
3083 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3084 SLTG_MemberHeader *pMemHeader;
3085 SLTG_EnumItem *pItem;
3086 char *pFirstItem;
3087 TLBVarDesc **ppVarDesc = &pTI->varlist;
3088 int num = 0;
3090 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3092 pFirstItem = (char*)(pMemHeader + 1);
3093 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3094 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3095 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3096 FIXME("enumitem magic = %04x\n", pItem->magic);
3097 return NULL;
3099 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3100 sizeof(**ppVarDesc));
3101 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3102 (*ppVarDesc)->vardesc.memid = pItem->memid;
3103 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3104 sizeof(VARIANT));
3105 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3106 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3107 *(INT*)(pItem->value + pFirstItem);
3108 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3109 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3110 /* FIXME("helpcontext, helpstring\n"); */
3112 ppVarDesc = &((*ppVarDesc)->next);
3113 if(pItem->next == 0xffff) break;
3115 pTI->TypeAttr.cVars = num;
3116 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3119 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3120 managable copy of it into this */
3121 typedef struct {
3122 WORD small_no;
3123 char *index_name;
3124 char *other_name;
3125 WORD res1a;
3126 WORD name_offs;
3127 WORD more_bytes;
3128 char *extra;
3129 WORD res20;
3130 DWORD helpcontext;
3131 WORD res26;
3132 GUID uuid;
3133 } SLTG_InternalOtherTypeInfo;
3135 /****************************************************************************
3136 * ITypeLib2_Constructor_SLTG
3138 * loading a SLTG typelib from an in-memory image
3140 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3142 ITypeLibImpl *pTypeLibImpl;
3143 SLTG_Header *pHeader;
3144 SLTG_BlkEntry *pBlkEntry;
3145 SLTG_Magic *pMagic;
3146 SLTG_Index *pIndex;
3147 SLTG_Pad9 *pPad9;
3148 LPVOID pBlk, pFirstBlk;
3149 SLTG_LibBlk *pLibBlk;
3150 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3151 char *pAfterOTIBlks = NULL;
3152 char *pNameTable, *ptr;
3153 int i;
3154 DWORD len, order;
3155 ITypeInfoImpl **ppTypeInfoImpl;
3157 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3159 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3160 if (!pTypeLibImpl) return NULL;
3162 pTypeLibImpl->lpVtbl = &tlbvt;
3163 pTypeLibImpl->ref = 1;
3165 pHeader = pLib;
3167 TRACE("header:\n");
3168 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3169 pHeader->nrOfFileBlks );
3170 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3171 FIXME("Header type magic 0x%08lx not supported.\n",
3172 pHeader->SLTG_magic);
3173 return NULL;
3176 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3177 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3179 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3180 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3182 /* Next we have a magic block */
3183 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3185 /* Let's see if we're still in sync */
3186 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3187 sizeof(SLTG_COMPOBJ_MAGIC))) {
3188 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3189 return NULL;
3191 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3192 sizeof(SLTG_DIR_MAGIC))) {
3193 FIXME("dir magic = %s\n", pMagic->dir_magic);
3194 return NULL;
3197 pIndex = (SLTG_Index*)(pMagic+1);
3199 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3201 pFirstBlk = (LPVOID)(pPad9 + 1);
3203 /* We'll set up a ptr to the main library block, which is the last one. */
3205 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3206 pBlkEntry[order].next != 0;
3207 order = pBlkEntry[order].next - 1, i++) {
3208 pBlk = (char*)pBlk + pBlkEntry[order].len;
3210 pLibBlk = pBlk;
3212 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3214 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3215 interspersed */
3217 len += 0x40;
3219 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3221 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3222 sizeof(*pOtherTypeInfoBlks) *
3223 pTypeLibImpl->TypeInfoCount);
3226 ptr = (char*)pLibBlk + len;
3228 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3229 WORD w, extra;
3230 len = 0;
3232 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3234 w = *(WORD*)(ptr + 2);
3235 if(w != 0xffff) {
3236 len += w;
3237 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3238 w+1);
3239 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3240 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3242 w = *(WORD*)(ptr + 4 + len);
3243 if(w != 0xffff) {
3244 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3245 len += w;
3246 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3247 w+1);
3248 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3249 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3251 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3252 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3253 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3254 if(extra) {
3255 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3256 extra);
3257 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3258 len += extra;
3260 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3261 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3262 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3263 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3264 len += sizeof(SLTG_OtherTypeInfo);
3265 ptr += len;
3268 pAfterOTIBlks = ptr;
3270 /* Skip this WORD and get the next DWORD */
3271 len = *(DWORD*)(pAfterOTIBlks + 2);
3273 /* Now add this to pLibBLk look at what we're pointing at and
3274 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3275 dust and we should be pointing at the beginning of the name
3276 table */
3278 pNameTable = (char*)pLibBlk + len;
3280 switch(*(WORD*)pNameTable) {
3281 case 0xffff:
3282 break;
3283 case 0x0200:
3284 pNameTable += 0x20;
3285 break;
3286 default:
3287 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3288 break;
3291 pNameTable += 0x216;
3293 pNameTable += 2;
3295 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3297 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3300 /* Hopefully we now have enough ptrs set up to actually read in
3301 some TypeInfos. It's not clear which order to do them in, so
3302 I'll just follow the links along the BlkEntry chain and read
3303 them in in the order in which they're in the file */
3305 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3307 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3308 pBlkEntry[order].next != 0;
3309 order = pBlkEntry[order].next - 1, i++) {
3311 SLTG_TypeInfoHeader *pTIHeader;
3312 SLTG_TypeInfoTail *pTITail;
3314 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3315 pOtherTypeInfoBlks[i].index_name)) {
3316 FIXME("Index strings don't match\n");
3317 return NULL;
3320 pTIHeader = pBlk;
3321 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3322 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3323 return NULL;
3325 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3326 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3327 (*ppTypeInfoImpl)->index = i;
3328 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3329 pOtherTypeInfoBlks[i].name_offs +
3330 pNameTable);
3331 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3332 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3333 sizeof(GUID));
3334 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3335 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3336 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3337 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3338 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3340 if((pTIHeader->typeflags1 & 7) != 2)
3341 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3342 if(pTIHeader->typeflags3 != 2)
3343 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3345 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3346 debugstr_w((*ppTypeInfoImpl)->Name),
3347 typekind_desc[pTIHeader->typekind],
3348 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3349 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3351 switch(pTIHeader->typekind) {
3352 case TKIND_ENUM:
3353 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3354 break;
3356 case TKIND_RECORD:
3357 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3358 break;
3360 case TKIND_INTERFACE:
3361 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3362 break;
3364 case TKIND_COCLASS:
3365 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3366 break;
3368 case TKIND_ALIAS:
3369 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3370 if (pTITail->tdescalias_vt)
3371 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3372 break;
3374 case TKIND_DISPATCH:
3375 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3376 break;
3378 default:
3379 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3380 pTITail = NULL;
3381 break;
3385 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3386 but we've already set those */
3387 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3388 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3389 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3391 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3392 X(06);
3393 X(08);
3394 X(0a);
3395 X(0c);
3396 X(0e);
3397 X(10);
3398 X(12);
3399 X(16);
3400 X(18);
3401 X(1a);
3402 X(1c);
3403 X(1e);
3404 X(24);
3405 X(26);
3406 X(2a);
3407 X(2c);
3408 X(2e);
3409 X(30);
3410 X(32);
3411 X(34);
3413 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3414 pBlk = (char*)pBlk + pBlkEntry[order].len;
3417 if(i != pTypeLibImpl->TypeInfoCount) {
3418 FIXME("Somehow processed %d TypeInfos\n", i);
3419 return NULL;
3422 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3423 return (ITypeLib2*)pTypeLibImpl;
3426 /* ITypeLib::QueryInterface
3428 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3429 ITypeLib2 * iface,
3430 REFIID riid,
3431 VOID **ppvObject)
3433 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3435 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3437 *ppvObject=NULL;
3438 if(IsEqualIID(riid, &IID_IUnknown) ||
3439 IsEqualIID(riid,&IID_ITypeLib)||
3440 IsEqualIID(riid,&IID_ITypeLib2))
3442 *ppvObject = This;
3445 if(*ppvObject)
3447 ITypeLib2_AddRef(iface);
3448 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3449 return S_OK;
3451 TRACE("-- Interface: E_NOINTERFACE\n");
3452 return E_NOINTERFACE;
3455 /* ITypeLib::AddRef
3457 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3459 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3460 ULONG ref = InterlockedIncrement(&This->ref);
3462 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3464 return ref;
3467 /* ITypeLib::Release
3469 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3471 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3472 ULONG ref = InterlockedDecrement(&This->ref);
3474 TRACE("(%p)->(%lu)\n",This, ref);
3476 if (!ref)
3478 /* remove cache entry */
3479 TRACE("removing from cache list\n");
3480 EnterCriticalSection(&cache_section);
3481 if (This->next) This->next->prev = This->prev;
3482 if (This->prev) This->prev->next = This->next;
3483 else tlb_cache_first = This->next;
3484 LeaveCriticalSection(&cache_section);
3486 /* FIXME destroy child objects */
3487 TRACE(" destroying ITypeLib(%p)\n",This);
3489 if (This->Name)
3491 SysFreeString(This->Name);
3492 This->Name = NULL;
3495 if (This->DocString)
3497 SysFreeString(This->DocString);
3498 This->DocString = NULL;
3501 if (This->HelpFile)
3503 SysFreeString(This->HelpFile);
3504 This->HelpFile = NULL;
3507 if (This->HelpStringDll)
3509 SysFreeString(This->HelpStringDll);
3510 This->HelpStringDll = NULL;
3513 if (This->pTypeInfo) /* can be NULL */
3514 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3515 HeapFree(GetProcessHeap(),0,This);
3516 return 0;
3519 return ref;
3522 /* ITypeLib::GetTypeInfoCount
3524 * Returns the number of type descriptions in the type library
3526 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3528 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3529 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3530 return This->TypeInfoCount;
3533 /* ITypeLib::GetTypeInfo
3535 * retrieves the specified type description in the library.
3537 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3538 ITypeLib2 *iface,
3539 UINT index,
3540 ITypeInfo **ppTInfo)
3542 int i;
3544 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3545 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3547 TRACE("(%p)->(index=%d) \n", This, index);
3549 if (!ppTInfo) return E_INVALIDARG;
3551 /* search element n in list */
3552 for(i=0; i < index; i++)
3554 pTypeInfo = pTypeInfo->next;
3555 if (!pTypeInfo)
3557 TRACE("-- element not found\n");
3558 return TYPE_E_ELEMENTNOTFOUND;
3562 *ppTInfo = (ITypeInfo *) pTypeInfo;
3564 ITypeInfo_AddRef(*ppTInfo);
3565 TRACE("-- found (%p)\n",*ppTInfo);
3566 return S_OK;
3570 /* ITypeLibs::GetTypeInfoType
3572 * Retrieves the type of a type description.
3574 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3575 ITypeLib2 *iface,
3576 UINT index,
3577 TYPEKIND *pTKind)
3579 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3580 int i;
3581 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3583 TRACE("(%p) index %d \n",This, index);
3585 if(!pTKind) return E_INVALIDARG;
3587 /* search element n in list */
3588 for(i=0; i < index; i++)
3590 if(!pTInfo)
3592 TRACE("-- element not found\n");
3593 return TYPE_E_ELEMENTNOTFOUND;
3595 pTInfo = pTInfo->next;
3598 *pTKind = pTInfo->TypeAttr.typekind;
3599 TRACE("-- found Type (%d)\n", *pTKind);
3600 return S_OK;
3603 /* ITypeLib::GetTypeInfoOfGuid
3605 * Retrieves the type description that corresponds to the specified GUID.
3608 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3609 ITypeLib2 *iface,
3610 REFGUID guid,
3611 ITypeInfo **ppTInfo)
3613 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3614 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3616 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3618 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3620 /* search linked list for guid */
3621 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3623 pTypeInfo = pTypeInfo->next;
3625 if (!pTypeInfo)
3627 /* end of list reached */
3628 TRACE("-- element not found\n");
3629 return TYPE_E_ELEMENTNOTFOUND;
3633 TRACE("-- found (%p, %s)\n",
3634 pTypeInfo,
3635 debugstr_w(pTypeInfo->Name));
3637 *ppTInfo = (ITypeInfo*)pTypeInfo;
3638 ITypeInfo_AddRef(*ppTInfo);
3639 return S_OK;
3642 /* ITypeLib::GetLibAttr
3644 * Retrieves the structure that contains the library's attributes.
3647 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3648 ITypeLib2 *iface,
3649 LPTLIBATTR *ppTLibAttr)
3651 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3652 TRACE("(%p)\n",This);
3653 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3654 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3655 return S_OK;
3658 /* ITypeLib::GetTypeComp
3660 * Enables a client compiler to bind to a library's types, variables,
3661 * constants, and global functions.
3664 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3665 ITypeLib2 *iface,
3666 ITypeComp **ppTComp)
3668 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3670 TRACE("(%p)->(%p)\n",This,ppTComp);
3671 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3672 ITypeComp_AddRef(*ppTComp);
3674 return S_OK;
3677 /* ITypeLib::GetDocumentation
3679 * Retrieves the library's documentation string, the complete Help file name
3680 * and path, and the context identifier for the library Help topic in the Help
3681 * file.
3683 * On a successful return all non-null BSTR pointers will have been set,
3684 * possibly to NULL.
3686 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3687 ITypeLib2 *iface,
3688 INT index,
3689 BSTR *pBstrName,
3690 BSTR *pBstrDocString,
3691 DWORD *pdwHelpContext,
3692 BSTR *pBstrHelpFile)
3694 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3696 HRESULT result = E_INVALIDARG;
3698 ITypeInfo *pTInfo;
3701 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3702 This, index,
3703 pBstrName, pBstrDocString,
3704 pdwHelpContext, pBstrHelpFile);
3706 if(index<0)
3708 /* documentation for the typelib */
3709 if(pBstrName)
3711 if (This->Name)
3712 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3713 else
3714 *pBstrName = NULL;
3716 if(pBstrDocString)
3718 if (This->DocString)
3719 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3720 else if (This->Name)
3721 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3722 else
3723 *pBstrDocString = NULL;
3725 if(pdwHelpContext)
3727 *pdwHelpContext = This->dwHelpContext;
3729 if(pBstrHelpFile)
3731 if (This->HelpFile)
3732 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3733 else
3734 *pBstrHelpFile = NULL;
3737 result = S_OK;
3739 else
3741 /* for a typeinfo */
3742 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3744 if(SUCCEEDED(result))
3746 result = ITypeInfo_GetDocumentation(pTInfo,
3747 MEMBERID_NIL,
3748 pBstrName,
3749 pBstrDocString,
3750 pdwHelpContext, pBstrHelpFile);
3752 ITypeInfo_Release(pTInfo);
3755 return result;
3756 memerr3:
3757 if (pBstrDocString) SysFreeString (*pBstrDocString);
3758 memerr2:
3759 if (pBstrName) SysFreeString (*pBstrName);
3760 memerr1:
3761 return STG_E_INSUFFICIENTMEMORY;
3764 /* ITypeLib::IsName
3766 * Indicates whether a passed-in string contains the name of a type or member
3767 * described in the library.
3770 static HRESULT WINAPI ITypeLib2_fnIsName(
3771 ITypeLib2 *iface,
3772 LPOLESTR szNameBuf,
3773 ULONG lHashVal,
3774 BOOL *pfName)
3776 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3777 ITypeInfoImpl *pTInfo;
3778 TLBFuncDesc *pFInfo;
3779 TLBVarDesc *pVInfo;
3780 int i;
3781 UINT nNameBufLen = SysStringLen(szNameBuf);
3783 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3784 pfName);
3786 *pfName=TRUE;
3787 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3788 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3789 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3790 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3791 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3792 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3793 goto ITypeLib2_fnIsName_exit;
3795 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3796 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3799 *pfName=FALSE;
3801 ITypeLib2_fnIsName_exit:
3802 TRACE("(%p)slow! search for %s: %s found!\n", This,
3803 debugstr_w(szNameBuf), *pfName?"NOT":"");
3805 return S_OK;
3808 /* ITypeLib::FindName
3810 * Finds occurrences of a type description in a type library. This may be used
3811 * to quickly verify that a name exists in a type library.
3814 static HRESULT WINAPI ITypeLib2_fnFindName(
3815 ITypeLib2 *iface,
3816 LPOLESTR szNameBuf,
3817 ULONG lHashVal,
3818 ITypeInfo **ppTInfo,
3819 MEMBERID *rgMemId,
3820 UINT16 *pcFound)
3822 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3823 ITypeInfoImpl *pTInfo;
3824 TLBFuncDesc *pFInfo;
3825 TLBVarDesc *pVInfo;
3826 int i,j = 0;
3828 UINT nNameBufLen = SysStringLen(szNameBuf);
3830 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3831 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3832 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3833 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3834 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3835 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3836 goto ITypeLib2_fnFindName_exit;
3838 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3839 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3840 continue;
3841 ITypeLib2_fnFindName_exit:
3842 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3843 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3844 j++;
3846 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3847 This, *pcFound, debugstr_w(szNameBuf), j);
3849 *pcFound=j;
3851 return S_OK;
3854 /* ITypeLib::ReleaseTLibAttr
3856 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3859 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3860 ITypeLib2 *iface,
3861 TLIBATTR *pTLibAttr)
3863 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3864 TRACE("freeing (%p)\n",This);
3865 HeapFree(GetProcessHeap(),0,pTLibAttr);
3869 /* ITypeLib2::GetCustData
3871 * gets the custom data
3873 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3874 ITypeLib2 * iface,
3875 REFGUID guid,
3876 VARIANT *pVarVal)
3878 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3879 TLBCustData *pCData;
3881 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3883 if( IsEqualIID(guid, &pCData->guid)) break;
3886 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3888 if(pCData)
3890 VariantInit( pVarVal);
3891 VariantCopy( pVarVal, &pCData->data);
3892 return S_OK;
3894 return E_INVALIDARG; /* FIXME: correct? */
3897 /* ITypeLib2::GetLibStatistics
3899 * Returns statistics about a type library that are required for efficient
3900 * sizing of hash tables.
3903 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3904 ITypeLib2 * iface,
3905 ULONG *pcUniqueNames,
3906 ULONG *pcchUniqueNames)
3908 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3910 FIXME("(%p): stub!\n", This);
3912 if(pcUniqueNames) *pcUniqueNames=1;
3913 if(pcchUniqueNames) *pcchUniqueNames=1;
3914 return S_OK;
3917 /* ITypeLib2::GetDocumentation2
3919 * Retrieves the library's documentation string, the complete Help file name
3920 * and path, the localization context to use, and the context ID for the
3921 * library Help topic in the Help file.
3924 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3925 ITypeLib2 * iface,
3926 INT index,
3927 LCID lcid,
3928 BSTR *pbstrHelpString,
3929 DWORD *pdwHelpStringContext,
3930 BSTR *pbstrHelpStringDll)
3932 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3933 HRESULT result;
3934 ITypeInfo *pTInfo;
3936 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3938 /* the help string should be obtained from the helpstringdll,
3939 * using the _DLLGetDocumentation function, based on the supplied
3940 * lcid. Nice to do sometime...
3942 if(index<0)
3944 /* documentation for the typelib */
3945 if(pbstrHelpString)
3946 *pbstrHelpString=SysAllocString(This->DocString);
3947 if(pdwHelpStringContext)
3948 *pdwHelpStringContext=This->dwHelpContext;
3949 if(pbstrHelpStringDll)
3950 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3952 result = S_OK;
3954 else
3956 /* for a typeinfo */
3957 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3959 if(SUCCEEDED(result))
3961 ITypeInfo2 * pTInfo2;
3962 result = ITypeInfo_QueryInterface(pTInfo,
3963 &IID_ITypeInfo2,
3964 (LPVOID*) &pTInfo2);
3966 if(SUCCEEDED(result))
3968 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3969 MEMBERID_NIL,
3970 lcid,
3971 pbstrHelpString,
3972 pdwHelpStringContext,
3973 pbstrHelpStringDll);
3975 ITypeInfo2_Release(pTInfo2);
3978 ITypeInfo_Release(pTInfo);
3981 return result;
3984 /* ITypeLib2::GetAllCustData
3986 * Gets all custom data items for the library.
3989 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3990 ITypeLib2 * iface,
3991 CUSTDATA *pCustData)
3993 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3994 TLBCustData *pCData;
3995 int i;
3996 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3997 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3998 if(pCustData->prgCustData ){
3999 pCustData->cCustData=This->ctCustData;
4000 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4001 pCustData->prgCustData[i].guid=pCData->guid;
4002 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4004 }else{
4005 ERR(" OUT OF MEMORY! \n");
4006 return E_OUTOFMEMORY;
4008 return S_OK;
4011 static const ITypeLib2Vtbl tlbvt = {
4012 ITypeLib2_fnQueryInterface,
4013 ITypeLib2_fnAddRef,
4014 ITypeLib2_fnRelease,
4015 ITypeLib2_fnGetTypeInfoCount,
4016 ITypeLib2_fnGetTypeInfo,
4017 ITypeLib2_fnGetTypeInfoType,
4018 ITypeLib2_fnGetTypeInfoOfGuid,
4019 ITypeLib2_fnGetLibAttr,
4020 ITypeLib2_fnGetTypeComp,
4021 ITypeLib2_fnGetDocumentation,
4022 ITypeLib2_fnIsName,
4023 ITypeLib2_fnFindName,
4024 ITypeLib2_fnReleaseTLibAttr,
4026 ITypeLib2_fnGetCustData,
4027 ITypeLib2_fnGetLibStatistics,
4028 ITypeLib2_fnGetDocumentation2,
4029 ITypeLib2_fnGetAllCustData
4033 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4035 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4037 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
4040 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4042 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4044 return ITypeInfo_AddRef((ITypeInfo *)This);
4047 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4049 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4051 return ITypeInfo_Release((ITypeInfo *)This);
4054 static HRESULT WINAPI ITypeLibComp_fnBind(
4055 ITypeComp * iface,
4056 OLECHAR * szName,
4057 ULONG lHash,
4058 WORD wFlags,
4059 ITypeInfo ** ppTInfo,
4060 DESCKIND * pDescKind,
4061 BINDPTR * pBindPtr)
4063 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4064 return E_NOTIMPL;
4067 static HRESULT WINAPI ITypeLibComp_fnBindType(
4068 ITypeComp * iface,
4069 OLECHAR * szName,
4070 ULONG lHash,
4071 ITypeInfo ** ppTInfo,
4072 ITypeComp ** ppTComp)
4074 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4075 return E_NOTIMPL;
4078 static const ITypeCompVtbl tlbtcvt =
4081 ITypeLibComp_fnQueryInterface,
4082 ITypeLibComp_fnAddRef,
4083 ITypeLibComp_fnRelease,
4085 ITypeLibComp_fnBind,
4086 ITypeLibComp_fnBindType
4089 /*================== ITypeInfo(2) Methods ===================================*/
4090 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4092 ITypeInfoImpl * pTypeInfoImpl;
4094 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4095 if (pTypeInfoImpl)
4097 pTypeInfoImpl->lpVtbl = &tinfvt;
4098 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4099 pTypeInfoImpl->ref=1;
4101 TRACE("(%p)\n", pTypeInfoImpl);
4102 return (ITypeInfo2*) pTypeInfoImpl;
4105 /* ITypeInfo::QueryInterface
4107 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4108 ITypeInfo2 *iface,
4109 REFIID riid,
4110 VOID **ppvObject)
4112 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4114 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4116 *ppvObject=NULL;
4117 if(IsEqualIID(riid, &IID_IUnknown) ||
4118 IsEqualIID(riid,&IID_ITypeInfo)||
4119 IsEqualIID(riid,&IID_ITypeInfo2))
4120 *ppvObject = This;
4122 if(*ppvObject){
4123 ITypeInfo_AddRef(iface);
4124 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4125 return S_OK;
4127 TRACE("-- Interface: E_NOINTERFACE\n");
4128 return E_NOINTERFACE;
4131 /* ITypeInfo::AddRef
4133 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4135 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4136 ULONG ref = InterlockedIncrement(&This->ref);
4138 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4140 TRACE("(%p)->ref is %lu\n",This, ref);
4141 return ref;
4144 /* ITypeInfo::Release
4146 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4148 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4149 ULONG ref = InterlockedDecrement(&This->ref);
4151 TRACE("(%p)->(%lu)\n",This, ref);
4153 if (ref) {
4154 /* We don't release ITypeLib when ref=0 because
4155 it means that function is called by ITypeLib2_Release */
4156 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4157 } else {
4158 FIXME("destroy child objects\n");
4160 TRACE("destroying ITypeInfo(%p)\n",This);
4161 if (This->Name)
4163 SysFreeString(This->Name);
4164 This->Name = 0;
4167 if (This->DocString)
4169 SysFreeString(This->DocString);
4170 This->DocString = 0;
4173 if (This->next)
4175 ITypeInfo_Release((ITypeInfo*)This->next);
4178 HeapFree(GetProcessHeap(),0,This);
4179 return 0;
4181 return ref;
4184 /* ITypeInfo::GetTypeAttr
4186 * Retrieves a TYPEATTR structure that contains the attributes of the type
4187 * description.
4190 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4191 LPTYPEATTR *ppTypeAttr)
4193 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4194 TRACE("(%p)\n",This);
4195 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr));
4196 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4198 if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */
4199 copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias);
4201 if((*ppTypeAttr)->typekind == TKIND_DISPATCH && (*ppTypeAttr)->wTypeFlags & TYPEFLAG_FDUAL) {
4202 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4203 funcs */
4204 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4205 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4207 return S_OK;
4210 /* ITypeInfo::GetTypeComp
4212 * Retrieves the ITypeComp interface for the type description, which enables a
4213 * client compiler to bind to the type description's members.
4216 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4217 ITypeComp * *ppTComp)
4219 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4221 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4223 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4224 ITypeComp_AddRef(*ppTComp);
4225 return S_OK;
4228 /* ITypeInfo::GetFuncDesc
4230 * Retrieves the FUNCDESC structure that contains information about a
4231 * specified function.
4234 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4235 LPFUNCDESC *ppFuncDesc)
4237 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4238 int i;
4239 TLBFuncDesc * pFDesc;
4240 TRACE("(%p) index %d\n", This, index);
4241 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4243 if(pFDesc){
4244 /* FIXME: must do a copy here */
4245 *ppFuncDesc=&pFDesc->funcdesc;
4246 return S_OK;
4248 return E_INVALIDARG;
4251 /* ITypeInfo::GetVarDesc
4253 * Retrieves a VARDESC structure that describes the specified variable.
4256 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4257 LPVARDESC *ppVarDesc)
4259 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4260 int i;
4261 TLBVarDesc * pVDesc;
4262 TRACE("(%p) index %d\n", This, index);
4263 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4265 if(pVDesc){
4266 /* FIXME: must do a copy here */
4267 *ppVarDesc=&pVDesc->vardesc;
4268 return S_OK;
4270 return E_INVALIDARG;
4273 /* ITypeInfo_GetNames
4275 * Retrieves the variable with the specified member ID (or the name of the
4276 * property or method and its parameters) that correspond to the specified
4277 * function ID.
4279 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4280 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4282 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4283 TLBFuncDesc * pFDesc;
4284 TLBVarDesc * pVDesc;
4285 int i;
4286 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4287 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4288 if(pFDesc)
4290 /* function found, now return function and parameter names */
4291 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4293 if(!i)
4294 *rgBstrNames=SysAllocString(pFDesc->Name);
4295 else
4296 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4298 *pcNames=i;
4300 else
4302 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4303 if(pVDesc)
4305 *rgBstrNames=SysAllocString(pVDesc->Name);
4306 *pcNames=1;
4308 else
4310 if(This->TypeAttr.cImplTypes &&
4311 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4312 /* recursive search */
4313 ITypeInfo *pTInfo;
4314 HRESULT result;
4315 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4316 &pTInfo);
4317 if(SUCCEEDED(result))
4319 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4320 ITypeInfo_Release(pTInfo);
4321 return result;
4323 WARN("Could not search inherited interface!\n");
4325 else
4327 WARN("no names found\n");
4329 *pcNames=0;
4330 return TYPE_E_ELEMENTNOTFOUND;
4333 return S_OK;
4337 /* ITypeInfo::GetRefTypeOfImplType
4339 * If a type description describes a COM class, it retrieves the type
4340 * description of the implemented interface types. For an interface,
4341 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4342 * if any exist.
4345 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4346 ITypeInfo2 *iface,
4347 UINT index,
4348 HREFTYPE *pRefType)
4350 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4351 int(i);
4352 TLBImplType *pImpl = This->impltypelist;
4354 TRACE("(%p) index %d\n", This, index);
4355 if (TRACE_ON(ole)) dump_TypeInfo(This);
4357 if(index==(UINT)-1)
4359 /* only valid on dual interfaces;
4360 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4362 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4364 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4365 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4367 *pRefType = -1;
4369 else
4371 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4372 *pRefType = pImpl->hRef;
4375 else
4377 /* get element n from linked list */
4378 for(i=0; pImpl && i<index; i++)
4380 pImpl = pImpl->next;
4383 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4385 *pRefType = pImpl->hRef;
4387 TRACE("-- 0x%08lx\n", pImpl->hRef );
4390 return S_OK;
4394 /* ITypeInfo::GetImplTypeFlags
4396 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4397 * or base interface in a type description.
4399 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4400 UINT index, INT *pImplTypeFlags)
4402 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4403 int i;
4404 TLBImplType *pImpl;
4406 TRACE("(%p) index %d\n", This, index);
4407 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4408 i++, pImpl=pImpl->next)
4410 if(i==index && pImpl){
4411 *pImplTypeFlags=pImpl->implflags;
4412 return S_OK;
4414 *pImplTypeFlags=0;
4415 return TYPE_E_ELEMENTNOTFOUND;
4418 /* GetIDsOfNames
4419 * Maps between member names and member IDs, and parameter names and
4420 * parameter IDs.
4422 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4423 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4425 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4426 TLBFuncDesc * pFDesc;
4427 TLBVarDesc * pVDesc;
4428 HRESULT ret=S_OK;
4430 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4431 cNames);
4432 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4433 int i, j;
4434 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4435 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4436 for(i=1; i < cNames; i++){
4437 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4438 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4439 break;
4440 if( j<pFDesc->funcdesc.cParams)
4441 pMemId[i]=j;
4442 else
4443 ret=DISP_E_UNKNOWNNAME;
4445 return ret;
4448 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4449 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4450 if(cNames) *pMemId=pVDesc->vardesc.memid;
4451 return ret;
4454 /* not found, see if this is and interface with an inheritance */
4455 if(This->TypeAttr.cImplTypes &&
4456 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4457 /* recursive search */
4458 ITypeInfo *pTInfo;
4459 ret=ITypeInfo_GetRefTypeInfo(iface,
4460 This->impltypelist->hRef, &pTInfo);
4461 if(SUCCEEDED(ret)){
4462 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4463 ITypeInfo_Release(pTInfo);
4464 return ret;
4466 WARN("Could not search inherited interface!\n");
4467 } else
4468 WARN("no names found\n");
4469 return DISP_E_UNKNOWNNAME;
4472 /* ITypeInfo::Invoke
4474 * Invokes a method, or accesses a property of an object, that implements the
4475 * interface described by the type description.
4477 DWORD
4478 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4479 DWORD res;
4481 if (TRACE_ON(ole)) {
4482 int i;
4483 TRACE("Calling %p(",func);
4484 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4485 TRACE(")\n");
4488 switch (callconv) {
4489 case CC_STDCALL:
4491 switch (nrargs) {
4492 case 0:
4493 res = func();
4494 break;
4495 case 1:
4496 res = func(args[0]);
4497 break;
4498 case 2:
4499 res = func(args[0],args[1]);
4500 break;
4501 case 3:
4502 res = func(args[0],args[1],args[2]);
4503 break;
4504 case 4:
4505 res = func(args[0],args[1],args[2],args[3]);
4506 break;
4507 case 5:
4508 res = func(args[0],args[1],args[2],args[3],args[4]);
4509 break;
4510 case 6:
4511 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4512 break;
4513 case 7:
4514 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4515 break;
4516 case 8:
4517 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4518 break;
4519 case 9:
4520 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4521 break;
4522 case 10:
4523 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4524 break;
4525 case 11:
4526 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4527 break;
4528 default:
4529 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4530 res = -1;
4531 break;
4533 break;
4534 default:
4535 FIXME("unsupported calling convention %d\n",callconv);
4536 res = -1;
4537 break;
4539 TRACE("returns %08lx\n",res);
4540 return res;
4543 extern int _argsize(DWORD vt);
4545 /****************************************************************************
4546 * Helper functions for Dispcall / Invoke, which copies one variant
4547 * with target type onto the argument stack.
4549 static HRESULT
4550 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4551 DWORD *argpos, VARIANT *arg, VARTYPE vt
4553 UINT arglen = _argsize(vt)*sizeof(DWORD);
4554 VARIANT va;
4556 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4557 memcpy(argpos,&arg,sizeof(void*));
4558 return S_OK;
4561 if (V_VT(arg) == vt) {
4562 memcpy(argpos, &V_I4(arg), arglen);
4563 return S_OK;
4566 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4567 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4568 return S_OK;
4571 if (vt == VT_VARIANT) {
4572 memcpy(argpos, arg, arglen);
4573 return S_OK;
4575 /* Deref BYREF vars if there is need */
4576 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4577 memcpy(argpos,(void*)V_I4(arg), arglen);
4578 return S_OK;
4580 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4581 /* in this context, if the type lib specifies IUnknown*, giving an
4582 IDispatch* is correct; so, don't invoke VariantChangeType */
4583 memcpy(argpos,&V_I4(arg), arglen);
4584 return S_OK;
4586 if ((vt == VT_PTR) && tdesc)
4587 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4589 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4590 ITypeInfo *tinfo2 = NULL;
4591 TYPEATTR *tattr = NULL;
4592 HRESULT hres;
4594 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4595 if (hres) {
4596 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4597 "while coercing from vt 0x%x. Copying 4 byte.\n",
4598 tdesc->u.hreftype,V_VT(arg));
4599 memcpy(argpos, &V_I4(arg), 4);
4600 return S_OK;
4602 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4603 if( hres )
4605 ERR("GetTypeAttr failed\n");
4606 ITypeInfo_Release(tinfo2);
4607 return hres;
4609 switch (tattr->typekind) {
4610 case TKIND_ENUM:
4611 switch ( V_VT( arg ) ) {
4612 case VT_I2:
4613 *argpos = V_I2(arg);
4614 hres = S_OK;
4615 break;
4616 case VT_I4:
4617 memcpy(argpos, &V_I4(arg), 4);
4618 hres = S_OK;
4619 break;
4620 default:
4621 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4622 hres = E_FAIL;
4623 break;
4625 break;
4627 case TKIND_ALIAS:
4628 tdesc = &(tattr->tdescAlias);
4629 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4630 break;
4632 case TKIND_INTERFACE:
4633 if (V_VT(arg) == VT_DISPATCH) {
4634 IDispatch *disp;
4635 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4636 memcpy(argpos, &V_DISPATCH(arg), 4);
4637 hres = S_OK;
4638 break;
4640 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4641 &IID_IDispatch,(LPVOID*)&disp);
4642 if (SUCCEEDED(hres)) {
4643 memcpy(argpos,&disp,4);
4644 IUnknown_Release(V_DISPATCH(arg));
4645 hres = S_OK;
4646 break;
4648 FIXME("Failed to query IDispatch interface from %s while "
4649 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4650 hres = E_FAIL;
4651 break;
4653 if (V_VT(arg) == VT_UNKNOWN) {
4654 memcpy(argpos, &V_UNKNOWN(arg), 4);
4655 hres = S_OK;
4656 break;
4658 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4659 V_VT(arg),debugstr_guid(&(tattr->guid)));
4660 hres = E_FAIL;
4661 break;
4663 case TKIND_DISPATCH:
4664 if (V_VT(arg) == VT_DISPATCH) {
4665 memcpy(argpos, &V_DISPATCH(arg), 4);
4666 hres = S_OK;
4668 else {
4669 hres = E_FAIL;
4670 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4672 break;
4673 case TKIND_RECORD:
4674 FIXME("TKIND_RECORD unhandled.\n");
4675 hres = E_FAIL;
4676 break;
4677 default:
4678 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4679 hres = E_FAIL;
4680 break;
4682 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4683 ITypeInfo_Release(tinfo2);
4684 return hres;
4687 VariantInit(&va);
4688 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4689 memcpy(argpos,&V_I4(&va), arglen);
4690 FIXME("Should not use VariantChangeType here."
4691 " (conversion from 0x%x -> 0x%x) %08lx\n",
4692 V_VT(arg), vt, *argpos
4694 return S_OK;
4696 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4697 return E_FAIL;
4700 /***********************************************************************
4701 * DispCallFunc (OLEAUT32.@)
4703 HRESULT WINAPI
4704 DispCallFunc(
4705 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4706 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4708 int i, argsize, argspos;
4709 DWORD *args;
4710 HRESULT hres;
4712 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4713 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4715 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4716 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4717 argsize = 1;
4718 for (i=0;i<cActuals;i++) {
4719 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4720 dump_Variant(prgpvarg[i]);
4721 argsize += _argsize(prgvt[i]);
4723 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4724 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4725 argspos = 1;
4726 for (i=0;i<cActuals;i++) {
4727 VARIANT *arg = prgpvarg[i];
4728 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4729 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4730 argspos += _argsize(prgvt[i]);
4733 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4735 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4736 hres=S_OK;
4738 else
4740 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4741 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4742 FIXME("Method returned %lx\n",hres);
4744 HeapFree(GetProcessHeap(),0,args);
4745 return hres;
4748 static HRESULT WINAPI ITypeInfo_fnInvoke(
4749 ITypeInfo2 *iface,
4750 VOID *pIUnk,
4751 MEMBERID memid,
4752 UINT16 dwFlags,
4753 DISPPARAMS *pDispParams,
4754 VARIANT *pVarResult,
4755 EXCEPINFO *pExcepInfo,
4756 UINT *pArgErr)
4758 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4759 int i;
4760 unsigned int func_index, var_index;
4761 TYPEKIND type_kind;
4762 HRESULT hres;
4764 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4765 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4767 dump_DispParms(pDispParams);
4769 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4770 if (SUCCEEDED(hres)) {
4771 FUNCDESC *func_desc;
4773 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4774 if(FAILED(hres)) return hres;
4776 switch (func_desc->funckind) {
4777 case FUNC_PUREVIRTUAL:
4778 case FUNC_VIRTUAL: {
4779 DWORD res;
4780 int numargs, numargs2, argspos, args2pos;
4781 DWORD *args , *args2;
4782 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4783 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4785 hres = S_OK;
4786 numargs = 1; numargs2 = 0;
4787 for (i = 0; i < func_desc->cParams; i++) {
4788 if (i<pDispParams->cArgs)
4789 numargs += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4790 else {
4791 numargs += 1; /* sizeof(lpvoid) */
4792 numargs2 += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4796 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4797 args2 = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4799 args[0] = (DWORD)pIUnk;
4800 argspos = 1; args2pos = 0;
4801 for (i = 0; i < func_desc->cParams; i++) {
4802 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4803 if (i<pDispParams->cArgs) {
4804 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4805 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4806 USHORT paramFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
4807 if (paramFlags & PARAMFLAG_FOPT) {
4808 if(i < func_desc->cParams - func_desc->cParamsOpt)
4809 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4810 if(V_VT(arg) == VT_EMPTY
4811 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
4812 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4813 How to determine it? */
4815 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4816 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4817 V_VT(arg) = VT_ERROR;
4818 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4819 arglen = _argsize(VT_ERROR);
4822 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4823 if (FAILED(hres)) goto func_fail;
4824 argspos += arglen;
4825 } else if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FOPT) {
4826 VARIANT *arg = &rgvarg[i];
4827 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4828 if(i < func_desc->cParams - func_desc->cParamsOpt)
4829 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4830 if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4831 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4832 V_VT(arg) = VT_ERROR;
4833 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4834 arglen = _argsize(VT_ERROR);
4835 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4836 if (FAILED(hres)) goto func_fail;
4837 argspos += arglen;
4838 } else {
4839 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i].tdesc);
4840 if (tdesc->vt != VT_PTR)
4841 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4842 /*FIXME: give pointers for the rest, so propertyget works*/
4843 args[argspos] = (DWORD)&args2[args2pos];
4845 /* If pointer to variant, pass reference it. */
4846 if ((tdesc->vt == VT_PTR) &&
4847 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4848 pVarResult
4850 args[argspos]= (DWORD)pVarResult;
4851 argspos += 1;
4852 args2pos += arglen;
4855 if (func_desc->cParamsOpt < 0)
4856 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
4858 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
4859 func_desc->callconv,
4860 numargs,
4861 args
4864 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4865 args2pos = 0;
4866 for (i = 0; i < func_desc->cParams - pDispParams->cArgs; i++) {
4867 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4868 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i + pDispParams->cArgs].tdesc);
4869 TYPEDESC i4_tdesc;
4870 i4_tdesc.vt = VT_I4;
4872 /* If we are a pointer to a variant, we are done already */
4873 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4874 continue;
4876 VariantInit(pVarResult);
4877 memcpy(&V_INT(pVarResult),&args2[args2pos],arglen*sizeof(DWORD));
4879 if (tdesc->vt == VT_PTR)
4880 tdesc = tdesc->u.lptdesc;
4881 if (tdesc->vt == VT_USERDEFINED) {
4882 ITypeInfo *tinfo2;
4883 TYPEATTR *tattr;
4885 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4886 if (FAILED(hres)) {
4887 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4888 goto func_fail;
4890 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4891 switch (tattr->typekind) {
4892 case TKIND_ENUM:
4893 /* force the return type to be VT_I4 */
4894 tdesc = &i4_tdesc;
4895 break;
4896 case TKIND_ALIAS:
4897 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4898 tdesc = &(tattr->tdescAlias);
4899 break;
4901 case TKIND_INTERFACE:
4902 FIXME("TKIND_INTERFACE unhandled.\n");
4903 break;
4904 case TKIND_DISPATCH:
4905 FIXME("TKIND_DISPATCH unhandled.\n");
4906 break;
4907 case TKIND_RECORD:
4908 FIXME("TKIND_RECORD unhandled.\n");
4909 break;
4910 default:
4911 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4912 break;
4914 ITypeInfo_Release(tinfo2);
4916 V_VT(pVarResult) = tdesc->vt;
4918 /* HACK: VB5 likes this.
4919 * I do not know why. There is 1 example in MSDN which uses
4920 * this which appears broken (mixes int vals and
4921 * IDispatch*.).
4923 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4924 V_VT(pVarResult) = VT_DISPATCH;
4925 TRACE("storing into variant:\n");
4926 dump_Variant(pVarResult);
4927 args2pos += arglen;
4930 func_fail:
4931 HeapFree(GetProcessHeap(), 0, rgvarg);
4932 HeapFree(GetProcessHeap(),0,args2);
4933 HeapFree(GetProcessHeap(),0,args);
4934 break;
4936 case FUNC_DISPATCH: {
4937 IDispatch *disp;
4939 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4940 if (SUCCEEDED(hres)) {
4941 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4942 hres = IDispatch_Invoke(
4943 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4944 pVarResult,pExcepInfo,pArgErr
4946 if (FAILED(hres))
4947 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
4948 IDispatch_Release(disp);
4949 } else
4950 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4951 break;
4953 default:
4954 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
4955 hres = E_FAIL;
4956 break;
4959 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
4960 return hres;
4962 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
4963 VARDESC *var_desc;
4965 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
4966 if(FAILED(hres)) return hres;
4968 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
4969 dump_VARDESC(var_desc);
4970 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
4971 return E_NOTIMPL;
4974 /* not found, look for it in inherited interfaces */
4975 ITypeInfo2_GetTypeKind(iface, &type_kind);
4976 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
4977 HREFTYPE ref_type;
4978 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
4979 /* recursive search */
4980 ITypeInfo *pTInfo;
4981 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
4982 if(SUCCEEDED(hres)){
4983 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4984 ITypeInfo_Release(pTInfo);
4985 return hres;
4987 WARN("Could not search inherited interface!\n");
4990 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
4991 return DISP_E_MEMBERNOTFOUND;
4994 /* ITypeInfo::GetDocumentation
4996 * Retrieves the documentation string, the complete Help file name and path,
4997 * and the context ID for the Help topic for a specified type description.
4999 * (Can be tested by the Visual Basic Editor in Word for instance.)
5001 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5002 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5003 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5005 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5006 TLBFuncDesc * pFDesc;
5007 TLBVarDesc * pVDesc;
5008 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5009 " HelpContext(%p) HelpFile(%p)\n",
5010 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5011 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5012 if(pBstrName)
5013 *pBstrName=SysAllocString(This->Name);
5014 if(pBstrDocString)
5015 *pBstrDocString=SysAllocString(This->DocString);
5016 if(pdwHelpContext)
5017 *pdwHelpContext=This->dwHelpContext;
5018 if(pBstrHelpFile)
5019 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5020 return S_OK;
5021 }else {/* for a member */
5022 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5023 if(pFDesc->funcdesc.memid==memid){
5024 if(pBstrName)
5025 *pBstrName = SysAllocString(pFDesc->Name);
5026 if(pBstrDocString)
5027 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5028 if(pdwHelpContext)
5029 *pdwHelpContext=pFDesc->helpcontext;
5030 return S_OK;
5032 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5033 if(pVDesc->vardesc.memid==memid){
5034 if(pBstrName)
5035 *pBstrName = SysAllocString(pVDesc->Name);
5036 if(pBstrDocString)
5037 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5038 if(pdwHelpContext)
5039 *pdwHelpContext=pVDesc->HelpContext;
5040 return S_OK;
5043 return TYPE_E_ELEMENTNOTFOUND;
5046 /* ITypeInfo::GetDllEntry
5048 * Retrieves a description or specification of an entry point for a function
5049 * in a DLL.
5051 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5052 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5053 WORD *pwOrdinal)
5055 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5056 TLBFuncDesc *pFDesc;
5058 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5060 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5061 if(pFDesc->funcdesc.memid==memid){
5062 dump_TypeInfo(This);
5063 dump_TLBFuncDescOne(pFDesc);
5065 /* FIXME: This is wrong, but how do you find that out? */
5066 if (pBstrDllName) {
5067 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5068 *pBstrDllName = SysAllocString(oleaut32W);
5071 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5072 if (pBstrName)
5073 *pBstrName = SysAllocString(pFDesc->Entry);
5074 if (pwOrdinal)
5075 *pwOrdinal = -1;
5076 return S_OK;
5078 if (pBstrName)
5079 *pBstrName = NULL;
5080 if (pwOrdinal)
5081 *pwOrdinal = (DWORD)pFDesc->Entry;
5082 return S_OK;
5084 return E_FAIL;
5087 /* ITypeInfo::GetRefTypeInfo
5089 * If a type description references other type descriptions, it retrieves
5090 * the referenced type descriptions.
5092 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5093 ITypeInfo2 *iface,
5094 HREFTYPE hRefType,
5095 ITypeInfo **ppTInfo)
5097 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5098 HRESULT result = E_FAIL;
5100 if (hRefType == -1 &&
5101 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5102 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5104 /* when we meet a DUAL dispinterface, we must create the interface
5105 * version of it.
5107 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5110 /* the interface version contains the same information as the dispinterface
5111 * copy the contents of the structs.
5113 *pTypeInfoImpl = *This;
5114 pTypeInfoImpl->ref = 1;
5116 /* change the type to interface */
5117 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5119 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5121 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5123 result = S_OK;
5125 } else {
5126 TLBRefType *pRefType;
5127 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5128 if(pRefType->reference == hRefType)
5129 break;
5131 if(!pRefType)
5132 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5133 if(pRefType && hRefType != -1) {
5134 ITypeLib *pTLib = NULL;
5136 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5137 int Index;
5138 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5139 } else {
5140 if(pRefType->pImpTLInfo->pImpTypeLib) {
5141 TRACE("typeinfo in imported typelib that is already loaded\n");
5142 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5143 ITypeLib2_AddRef((ITypeLib*) pTLib);
5144 result = S_OK;
5145 } else {
5146 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5147 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5148 pRefType->pImpTLInfo->wVersionMajor,
5149 pRefType->pImpTLInfo->wVersionMinor,
5150 pRefType->pImpTLInfo->lcid,
5151 &pTLib);
5153 if(!SUCCEEDED(result)) {
5154 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5155 result=LoadTypeLib(libnam, &pTLib);
5156 SysFreeString(libnam);
5158 if(SUCCEEDED(result)) {
5159 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5160 ITypeLib2_AddRef(pTLib);
5164 if(SUCCEEDED(result)) {
5165 if(pRefType->index == TLB_REF_USE_GUID)
5166 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5167 &pRefType->guid,
5168 ppTInfo);
5169 else
5170 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5171 ppTInfo);
5173 if (pTLib != NULL)
5174 ITypeLib2_Release(pTLib);
5178 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5179 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5180 return result;
5183 /* ITypeInfo::AddressOfMember
5185 * Retrieves the addresses of static functions or variables, such as those
5186 * defined in a DLL.
5188 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5189 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5191 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5192 FIXME("(%p) stub!\n", This);
5193 return S_OK;
5196 /* ITypeInfo::CreateInstance
5198 * Creates a new instance of a type that describes a component object class
5199 * (coclass).
5201 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5202 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5204 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5205 FIXME("(%p) stub!\n", This);
5206 return S_OK;
5209 /* ITypeInfo::GetMops
5211 * Retrieves marshalling information.
5213 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5214 BSTR *pBstrMops)
5216 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5217 FIXME("(%p) stub!\n", This);
5218 return S_OK;
5221 /* ITypeInfo::GetContainingTypeLib
5223 * Retrieves the containing type library and the index of the type description
5224 * within that type library.
5226 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5227 ITypeLib * *ppTLib, UINT *pIndex)
5229 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5231 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5232 if (pIndex) {
5233 *pIndex=This->index;
5234 TRACE("returning pIndex=%d\n", *pIndex);
5237 if (ppTLib) {
5238 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5239 ITypeLib2_AddRef(*ppTLib);
5240 TRACE("returning ppTLib=%p\n", *ppTLib);
5243 return S_OK;
5246 /* ITypeInfo::ReleaseTypeAttr
5248 * Releases a TYPEATTR previously returned by GetTypeAttr.
5251 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5252 TYPEATTR* pTypeAttr)
5254 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5255 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5256 if(This->TypeAttr.typekind == TKIND_ALIAS)
5257 free_deep_typedesc(&pTypeAttr->tdescAlias);
5258 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5261 /* ITypeInfo::ReleaseFuncDesc
5263 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5265 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5266 ITypeInfo2 *iface,
5267 FUNCDESC *pFuncDesc)
5269 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5270 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5273 /* ITypeInfo::ReleaseVarDesc
5275 * Releases a VARDESC previously returned by GetVarDesc.
5277 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5278 VARDESC *pVarDesc)
5280 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5281 TRACE("(%p)->(%p)\n", This, pVarDesc);
5284 /* ITypeInfo2::GetTypeKind
5286 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5289 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5290 TYPEKIND *pTypeKind)
5292 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5293 *pTypeKind=This->TypeAttr.typekind;
5294 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5295 return S_OK;
5298 /* ITypeInfo2::GetTypeFlags
5300 * Returns the type flags without any allocations. This returns a DWORD type
5301 * flag, which expands the type flags without growing the TYPEATTR (type
5302 * attribute).
5305 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5307 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5308 *pTypeFlags=This->TypeAttr.wTypeFlags;
5309 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5310 return S_OK;
5313 /* ITypeInfo2::GetFuncIndexOfMemId
5314 * Binds to a specific member based on a known DISPID, where the member name
5315 * is not known (for example, when binding to a default member).
5318 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5319 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5321 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5322 TLBFuncDesc *pFuncInfo;
5323 int i;
5324 HRESULT result;
5326 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5327 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5328 break;
5329 if(pFuncInfo) {
5330 *pFuncIndex = i;
5331 result = S_OK;
5332 } else
5333 result = TYPE_E_ELEMENTNOTFOUND;
5335 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5336 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5337 return result;
5340 /* TypeInfo2::GetVarIndexOfMemId
5342 * Binds to a specific member based on a known DISPID, where the member name
5343 * is not known (for example, when binding to a default member).
5346 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5347 MEMBERID memid, UINT *pVarIndex)
5349 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5350 TLBVarDesc *pVarInfo;
5351 int i;
5352 HRESULT result;
5353 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5354 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5356 if(pVarInfo) {
5357 *pVarIndex = i;
5358 result = S_OK;
5359 } else
5360 result = TYPE_E_ELEMENTNOTFOUND;
5362 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5363 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5364 return result;
5367 /* ITypeInfo2::GetCustData
5369 * Gets the custom data
5371 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5372 ITypeInfo2 * iface,
5373 REFGUID guid,
5374 VARIANT *pVarVal)
5376 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5377 TLBCustData *pCData;
5379 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5380 if( IsEqualIID(guid, &pCData->guid)) break;
5382 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5384 if(pCData)
5386 VariantInit( pVarVal);
5387 VariantCopy( pVarVal, &pCData->data);
5388 return S_OK;
5390 return E_INVALIDARG; /* FIXME: correct? */
5393 /* ITypeInfo2::GetFuncCustData
5395 * Gets the custom data
5397 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5398 ITypeInfo2 * iface,
5399 UINT index,
5400 REFGUID guid,
5401 VARIANT *pVarVal)
5403 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5404 TLBCustData *pCData=NULL;
5405 TLBFuncDesc * pFDesc;
5406 int i;
5407 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5408 pFDesc=pFDesc->next);
5410 if(pFDesc)
5411 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5412 if( IsEqualIID(guid, &pCData->guid)) break;
5414 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5416 if(pCData){
5417 VariantInit( pVarVal);
5418 VariantCopy( pVarVal, &pCData->data);
5419 return S_OK;
5421 return E_INVALIDARG; /* FIXME: correct? */
5424 /* ITypeInfo2::GetParamCustData
5426 * Gets the custom data
5428 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5429 ITypeInfo2 * iface,
5430 UINT indexFunc,
5431 UINT indexParam,
5432 REFGUID guid,
5433 VARIANT *pVarVal)
5435 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5436 TLBCustData *pCData=NULL;
5437 TLBFuncDesc * pFDesc;
5438 int i;
5440 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5442 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5443 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5444 pCData = pCData->next)
5445 if( IsEqualIID(guid, &pCData->guid)) break;
5447 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5449 if(pCData)
5451 VariantInit( pVarVal);
5452 VariantCopy( pVarVal, &pCData->data);
5453 return S_OK;
5455 return E_INVALIDARG; /* FIXME: correct? */
5458 /* ITypeInfo2::GetVarCustData
5460 * Gets the custom data
5462 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5463 ITypeInfo2 * iface,
5464 UINT index,
5465 REFGUID guid,
5466 VARIANT *pVarVal)
5468 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5469 TLBCustData *pCData=NULL;
5470 TLBVarDesc * pVDesc;
5471 int i;
5473 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5475 if(pVDesc)
5477 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5479 if( IsEqualIID(guid, &pCData->guid)) break;
5483 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5485 if(pCData)
5487 VariantInit( pVarVal);
5488 VariantCopy( pVarVal, &pCData->data);
5489 return S_OK;
5491 return E_INVALIDARG; /* FIXME: correct? */
5494 /* ITypeInfo2::GetImplCustData
5496 * Gets the custom data
5498 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5499 ITypeInfo2 * iface,
5500 UINT index,
5501 REFGUID guid,
5502 VARIANT *pVarVal)
5504 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5505 TLBCustData *pCData=NULL;
5506 TLBImplType * pRDesc;
5507 int i;
5509 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5511 if(pRDesc)
5513 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5515 if( IsEqualIID(guid, &pCData->guid)) break;
5519 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5521 if(pCData)
5523 VariantInit( pVarVal);
5524 VariantCopy( pVarVal, &pCData->data);
5525 return S_OK;
5527 return E_INVALIDARG; /* FIXME: correct? */
5530 /* ITypeInfo2::GetDocumentation2
5532 * Retrieves the documentation string, the complete Help file name and path,
5533 * the localization context to use, and the context ID for the library Help
5534 * topic in the Help file.
5537 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5538 ITypeInfo2 * iface,
5539 MEMBERID memid,
5540 LCID lcid,
5541 BSTR *pbstrHelpString,
5542 DWORD *pdwHelpStringContext,
5543 BSTR *pbstrHelpStringDll)
5545 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5546 TLBFuncDesc * pFDesc;
5547 TLBVarDesc * pVDesc;
5548 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5549 "HelpStringContext(%p) HelpStringDll(%p)\n",
5550 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5551 pbstrHelpStringDll );
5552 /* the help string should be obtained from the helpstringdll,
5553 * using the _DLLGetDocumentation function, based on the supplied
5554 * lcid. Nice to do sometime...
5556 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5557 if(pbstrHelpString)
5558 *pbstrHelpString=SysAllocString(This->Name);
5559 if(pdwHelpStringContext)
5560 *pdwHelpStringContext=This->dwHelpStringContext;
5561 if(pbstrHelpStringDll)
5562 *pbstrHelpStringDll=
5563 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5564 return S_OK;
5565 }else {/* for a member */
5566 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5567 if(pFDesc->funcdesc.memid==memid){
5568 if(pbstrHelpString)
5569 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5570 if(pdwHelpStringContext)
5571 *pdwHelpStringContext=pFDesc->HelpStringContext;
5572 if(pbstrHelpStringDll)
5573 *pbstrHelpStringDll=
5574 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5575 return S_OK;
5577 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5578 if(pVDesc->vardesc.memid==memid){
5579 if(pbstrHelpString)
5580 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5581 if(pdwHelpStringContext)
5582 *pdwHelpStringContext=pVDesc->HelpStringContext;
5583 if(pbstrHelpStringDll)
5584 *pbstrHelpStringDll=
5585 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5586 return S_OK;
5589 return TYPE_E_ELEMENTNOTFOUND;
5592 /* ITypeInfo2::GetAllCustData
5594 * Gets all custom data items for the Type info.
5597 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5598 ITypeInfo2 * iface,
5599 CUSTDATA *pCustData)
5601 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5602 TLBCustData *pCData;
5603 int i;
5605 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5607 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5608 if(pCustData->prgCustData ){
5609 pCustData->cCustData=This->ctCustData;
5610 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5611 pCustData->prgCustData[i].guid=pCData->guid;
5612 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5614 }else{
5615 ERR(" OUT OF MEMORY! \n");
5616 return E_OUTOFMEMORY;
5618 return S_OK;
5621 /* ITypeInfo2::GetAllFuncCustData
5623 * Gets all custom data items for the specified Function
5626 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5627 ITypeInfo2 * iface,
5628 UINT index,
5629 CUSTDATA *pCustData)
5631 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5632 TLBCustData *pCData;
5633 TLBFuncDesc * pFDesc;
5634 int i;
5635 TRACE("(%p) index %d\n", This, index);
5636 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5637 pFDesc=pFDesc->next)
5639 if(pFDesc){
5640 pCustData->prgCustData =
5641 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5642 if(pCustData->prgCustData ){
5643 pCustData->cCustData=pFDesc->ctCustData;
5644 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5645 pCData = pCData->next){
5646 pCustData->prgCustData[i].guid=pCData->guid;
5647 VariantCopy(& pCustData->prgCustData[i].varValue,
5648 & pCData->data);
5650 }else{
5651 ERR(" OUT OF MEMORY! \n");
5652 return E_OUTOFMEMORY;
5654 return S_OK;
5656 return TYPE_E_ELEMENTNOTFOUND;
5659 /* ITypeInfo2::GetAllParamCustData
5661 * Gets all custom data items for the Functions
5664 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5665 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5667 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5668 TLBCustData *pCData=NULL;
5669 TLBFuncDesc * pFDesc;
5670 int i;
5671 TRACE("(%p) index %d\n", This, indexFunc);
5672 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5673 pFDesc=pFDesc->next)
5675 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5676 pCustData->prgCustData =
5677 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5678 sizeof(CUSTDATAITEM));
5679 if(pCustData->prgCustData ){
5680 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5681 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5682 pCData; i++, pCData = pCData->next){
5683 pCustData->prgCustData[i].guid=pCData->guid;
5684 VariantCopy(& pCustData->prgCustData[i].varValue,
5685 & pCData->data);
5687 }else{
5688 ERR(" OUT OF MEMORY! \n");
5689 return E_OUTOFMEMORY;
5691 return S_OK;
5693 return TYPE_E_ELEMENTNOTFOUND;
5696 /* ITypeInfo2::GetAllVarCustData
5698 * Gets all custom data items for the specified Variable
5701 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5702 UINT index, CUSTDATA *pCustData)
5704 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5705 TLBCustData *pCData;
5706 TLBVarDesc * pVDesc;
5707 int i;
5708 TRACE("(%p) index %d\n", This, index);
5709 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5710 pVDesc=pVDesc->next)
5712 if(pVDesc){
5713 pCustData->prgCustData =
5714 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5715 if(pCustData->prgCustData ){
5716 pCustData->cCustData=pVDesc->ctCustData;
5717 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5718 pCData = pCData->next){
5719 pCustData->prgCustData[i].guid=pCData->guid;
5720 VariantCopy(& pCustData->prgCustData[i].varValue,
5721 & pCData->data);
5723 }else{
5724 ERR(" OUT OF MEMORY! \n");
5725 return E_OUTOFMEMORY;
5727 return S_OK;
5729 return TYPE_E_ELEMENTNOTFOUND;
5732 /* ITypeInfo2::GetAllImplCustData
5734 * Gets all custom data items for the specified implementation type
5737 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5738 ITypeInfo2 * iface,
5739 UINT index,
5740 CUSTDATA *pCustData)
5742 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5743 TLBCustData *pCData;
5744 TLBImplType * pRDesc;
5745 int i;
5746 TRACE("(%p) index %d\n", This, index);
5747 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5748 pRDesc=pRDesc->next)
5750 if(pRDesc){
5751 pCustData->prgCustData =
5752 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5753 if(pCustData->prgCustData ){
5754 pCustData->cCustData=pRDesc->ctCustData;
5755 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5756 pCData = pCData->next){
5757 pCustData->prgCustData[i].guid=pCData->guid;
5758 VariantCopy(& pCustData->prgCustData[i].varValue,
5759 & pCData->data);
5761 }else{
5762 ERR(" OUT OF MEMORY! \n");
5763 return E_OUTOFMEMORY;
5765 return S_OK;
5767 return TYPE_E_ELEMENTNOTFOUND;
5770 static const ITypeInfo2Vtbl tinfvt =
5773 ITypeInfo_fnQueryInterface,
5774 ITypeInfo_fnAddRef,
5775 ITypeInfo_fnRelease,
5777 ITypeInfo_fnGetTypeAttr,
5778 ITypeInfo_fnGetTypeComp,
5779 ITypeInfo_fnGetFuncDesc,
5780 ITypeInfo_fnGetVarDesc,
5781 ITypeInfo_fnGetNames,
5782 ITypeInfo_fnGetRefTypeOfImplType,
5783 ITypeInfo_fnGetImplTypeFlags,
5784 ITypeInfo_fnGetIDsOfNames,
5785 ITypeInfo_fnInvoke,
5786 ITypeInfo_fnGetDocumentation,
5787 ITypeInfo_fnGetDllEntry,
5788 ITypeInfo_fnGetRefTypeInfo,
5789 ITypeInfo_fnAddressOfMember,
5790 ITypeInfo_fnCreateInstance,
5791 ITypeInfo_fnGetMops,
5792 ITypeInfo_fnGetContainingTypeLib,
5793 ITypeInfo_fnReleaseTypeAttr,
5794 ITypeInfo_fnReleaseFuncDesc,
5795 ITypeInfo_fnReleaseVarDesc,
5797 ITypeInfo2_fnGetTypeKind,
5798 ITypeInfo2_fnGetTypeFlags,
5799 ITypeInfo2_fnGetFuncIndexOfMemId,
5800 ITypeInfo2_fnGetVarIndexOfMemId,
5801 ITypeInfo2_fnGetCustData,
5802 ITypeInfo2_fnGetFuncCustData,
5803 ITypeInfo2_fnGetParamCustData,
5804 ITypeInfo2_fnGetVarCustData,
5805 ITypeInfo2_fnGetImplTypeCustData,
5806 ITypeInfo2_fnGetDocumentation2,
5807 ITypeInfo2_fnGetAllCustData,
5808 ITypeInfo2_fnGetAllFuncCustData,
5809 ITypeInfo2_fnGetAllParamCustData,
5810 ITypeInfo2_fnGetAllVarCustData,
5811 ITypeInfo2_fnGetAllImplTypeCustData,
5814 /******************************************************************************
5815 * CreateDispTypeInfo [OLEAUT32.31]
5817 * Build type information for an object so it can be called through an
5818 * IDispatch interface.
5820 * RETURNS
5821 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5822 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5824 * NOTES
5825 * This call allows an objects methods to be accessed through IDispatch, by
5826 * building an ITypeInfo object that IDispatch can use to call through.
5828 HRESULT WINAPI CreateDispTypeInfo(
5829 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5830 LCID lcid, /* [I] Locale Id */
5831 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5833 ITypeInfoImpl *pTIImpl;
5834 int param, func;
5835 TLBFuncDesc **ppFuncDesc;
5837 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5838 pTIImpl->pTypeLib = NULL;
5839 pTIImpl->index = 0;
5840 pTIImpl->Name = NULL;
5841 pTIImpl->dwHelpContext = -1;
5842 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
5843 pTIImpl->TypeAttr.lcid = lcid;
5844 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
5845 pTIImpl->TypeAttr.wMajorVerNum = 0;
5846 pTIImpl->TypeAttr.wMinorVerNum = 0;
5847 pTIImpl->TypeAttr.cbAlignment = 2;
5848 pTIImpl->TypeAttr.cbSizeInstance = -1;
5849 pTIImpl->TypeAttr.cbSizeVft = -1;
5850 pTIImpl->TypeAttr.cFuncs = 0;
5851 pTIImpl->TypeAttr.cImplTypes = 1;
5852 pTIImpl->TypeAttr.cVars = 0;
5853 pTIImpl->TypeAttr.wTypeFlags = 0;
5855 ppFuncDesc = &pTIImpl->funclist;
5856 for(func = 0; func < pidata->cMembers; func++) {
5857 METHODDATA *md = pidata->pmethdata + func;
5858 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
5859 (*ppFuncDesc)->Name = SysAllocString(md->szName);
5860 (*ppFuncDesc)->funcdesc.memid = md->dispid;
5861 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
5862 (*ppFuncDesc)->funcdesc.callconv = md->cc;
5863 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
5864 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
5865 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
5866 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
5867 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
5868 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5869 md->cArgs * sizeof(ELEMDESC));
5870 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5871 md->cArgs * sizeof(TLBParDesc));
5872 for(param = 0; param < md->cArgs; param++) {
5873 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
5874 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
5876 ppFuncDesc = &(*ppFuncDesc)->next;
5878 *pptinfo = (ITypeInfo*)pTIImpl;
5879 return S_OK;
5883 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5885 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5887 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5890 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5892 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5894 return ITypeInfo_AddRef((ITypeInfo *)This);
5897 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5899 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5901 return ITypeInfo_Release((ITypeInfo *)This);
5904 static HRESULT WINAPI ITypeComp_fnBind(
5905 ITypeComp * iface,
5906 OLECHAR * szName,
5907 ULONG lHash,
5908 WORD wFlags,
5909 ITypeInfo ** ppTInfo,
5910 DESCKIND * pDescKind,
5911 BINDPTR * pBindPtr)
5913 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5914 TLBFuncDesc * pFDesc;
5915 TLBVarDesc * pVDesc;
5917 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5919 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5920 if (pFDesc->funcdesc.invkind & wFlags)
5921 if (!strcmpW(pFDesc->Name, szName)) {
5922 break;
5925 if (pFDesc)
5927 *pDescKind = DESCKIND_FUNCDESC;
5928 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5929 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5930 return S_OK;
5931 } else {
5932 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5934 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5935 if (!strcmpW(pVDesc->Name, szName)) {
5936 *pDescKind = DESCKIND_VARDESC;
5937 pBindPtr->lpvardesc = &pVDesc->vardesc;
5938 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5939 return S_OK;
5944 /* not found, look for it in inherited interfaces */
5945 if (This->TypeAttr.cImplTypes &&
5946 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
5947 /* recursive search */
5948 ITypeInfo *pTInfo;
5949 ITypeComp *pTComp;
5950 HRESULT hr;
5951 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5952 if (SUCCEEDED(hr))
5954 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5955 ITypeInfo_Release(pTInfo);
5957 if (SUCCEEDED(hr))
5959 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5960 ITypeComp_Release(pTComp);
5961 return hr;
5963 WARN("Could not search inherited interface!\n");
5965 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5966 *pDescKind = DESCKIND_NONE;
5967 pBindPtr->lpfuncdesc = NULL;
5968 *ppTInfo = NULL;
5969 return DISP_E_MEMBERNOTFOUND;
5972 static HRESULT WINAPI ITypeComp_fnBindType(
5973 ITypeComp * iface,
5974 OLECHAR * szName,
5975 ULONG lHash,
5976 ITypeInfo ** ppTInfo,
5977 ITypeComp ** ppTComp)
5979 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5981 /* strange behaviour (does nothing) but like the
5982 * original */
5984 if (!ppTInfo || !ppTComp)
5985 return E_POINTER;
5987 *ppTInfo = NULL;
5988 *ppTComp = NULL;
5990 return S_OK;
5993 static const ITypeCompVtbl tcompvt =
5996 ITypeComp_fnQueryInterface,
5997 ITypeComp_fnAddRef,
5998 ITypeComp_fnRelease,
6000 ITypeComp_fnBind,
6001 ITypeComp_fnBindType