Yet another useful hint for missing stdole32.tlb.
[wine/testsucceed.git] / dlls / oleaut32 / typelib.c
blob64b058bc7eaa9123587b35a19b899ad8d4279c19
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 NONAMELESSUNION
65 #define NONAMELESSSTRUCT
66 #include "winerror.h"
67 #include "windef.h"
68 #include "winbase.h"
69 #include "winnls.h"
70 #include "winreg.h"
71 #include "winuser.h"
73 #include "wine/unicode.h"
74 #include "objbase.h"
75 #include "heap.h"
76 #include "ole2disp.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
152 /****************************************************************************
153 * QueryPathOfRegTypeLib [OLEAUT32.164]
154 * RETURNS
155 * path of typelib
157 HRESULT WINAPI
158 QueryPathOfRegTypeLib(
159 REFGUID guid, /* [in] referenced guid */
160 WORD wMaj, /* [in] major version */
161 WORD wMin, /* [in] minor version */
162 LCID lcid, /* [in] locale id */
163 LPBSTR path ) /* [out] path of typelib */
165 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
166 string termination character on output strings */
168 HRESULT hr = E_FAIL;
170 LCID myLCID = lcid;
172 char szXGUID[80];
173 char szTypeLibKey[100];
174 char szPath[MAX_PATH];
175 DWORD dwPathLen = sizeof(szPath);
177 if ( !HIWORD(guid) )
179 sprintf(szXGUID,
180 "<guid 0x%08lx>",
181 (DWORD) guid);
183 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
184 return E_FAIL;
187 while (hr != S_OK)
189 sprintf(szTypeLibKey,
190 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
191 guid->Data1, guid->Data2, guid->Data3,
192 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
193 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
194 wMaj,
195 wMin,
196 myLCID);
198 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
200 if (!lcid)
201 break;
202 else if (myLCID == lcid)
204 /* try with sub-langid */
205 myLCID = SUBLANGID(lcid);
207 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
209 /* try with system langid */
210 myLCID = 0;
212 else
214 break;
217 else
219 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
220 BSTR bstrPath = SysAllocStringLen(NULL,len);
222 MultiByteToWideChar(CP_ACP,
223 MB_PRECOMPOSED,
224 szPath,
225 dwPathLen,
226 bstrPath,
227 len);
228 *path = bstrPath;
229 hr = S_OK;
233 if (hr != S_OK)
234 TRACE_(typelib)("%s not found\n", szTypeLibKey);
236 return hr;
239 /******************************************************************************
240 * CreateTypeLib [OLEAUT32.160] creates a typelib
242 * RETURNS
243 * Success: S_OK
244 * Failure: Status
246 HRESULT WINAPI CreateTypeLib(
247 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
249 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
250 return E_FAIL;
252 /******************************************************************************
253 * LoadTypeLib [OLEAUT32.161]
254 * Loads and registers a type library
255 * NOTES
256 * Docs: OLECHAR FAR* szFile
257 * Docs: iTypeLib FAR* FAR* pptLib
259 * RETURNS
260 * Success: S_OK
261 * Failure: Status
263 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
265 HRESULT WINAPI LoadTypeLib(
266 const OLECHAR *szFile,/* [in] Name of file to load from */
267 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
269 TRACE("\n");
270 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
273 /******************************************************************************
274 * LoadTypeLibEx [OLEAUT32.183]
275 * Loads and optionally registers a type library
277 * RETURNS
278 * Success: S_OK
279 * Failure: Status
281 HRESULT WINAPI LoadTypeLibEx(
282 LPCOLESTR szFile, /* [in] Name of file to load from */
283 REGKIND regkind, /* [in] Specify kind of registration */
284 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
286 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
287 WCHAR *pIndexStr;
288 HRESULT res;
289 INT index = 1;
291 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
293 *pptLib = NULL;
294 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
295 NULL)) {
297 /* Look for a trailing '\\' followed by an index */
298 pIndexStr = strrchrW(szFile, '\\');
299 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
300 index = atoiW(pIndexStr);
301 memcpy(szFileCopy, szFile,
302 (pIndexStr - szFile - 1) * sizeof(WCHAR));
303 szFileCopy[pIndexStr - szFile - 1] = '\0';
304 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
305 szPath,NULL))
306 return TYPE_E_CANTLOADLIBRARY;
307 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
308 return TYPE_E_CANTLOADLIBRARY;
309 } else {
310 WCHAR tstpath[260];
311 WCHAR stdole32tlb[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
312 int i;
314 lstrcpyW(tstpath,szFile);
315 CharLowerW(tstpath);
316 for (i=0;i<strlenW(tstpath);i++) {
317 if (tstpath[i] == 's') {
318 if (!strcmpW(tstpath+i,stdole32tlb)) {
319 MESSAGE("\n");
320 MESSAGE("**************************************************************************\n");
321 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
322 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
323 MESSAGE("on the Microsoft Download Pages.\n");
324 MESSAGE("A free download link is on http://sourceforge.net/projects/wine/, look for dcom95.exe.\n");
325 MESSAGE("**************************************************************************\n");
326 break;
330 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile));
331 return TYPE_E_CANTLOADLIBRARY;
335 TRACE("File %s index %d\n", debugstr_w(szPath), index);
337 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
339 if (SUCCEEDED(res))
340 switch(regkind)
342 case REGKIND_DEFAULT:
343 /* don't register typelibs supplied with full path. Experimentation confirms the following */
344 if ((!szFile) ||
345 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
346 (szFile[0] && (szFile[1] == ':'))) break;
347 /* else fall-through */
349 case REGKIND_REGISTER:
350 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
352 IUnknown_Release(*pptLib);
353 *pptLib = 0;
355 break;
356 case REGKIND_NONE:
357 break;
360 TRACE(" returns %08lx\n",res);
361 return res;
364 /******************************************************************************
365 * LoadRegTypeLib [OLEAUT32.162]
367 HRESULT WINAPI LoadRegTypeLib(
368 REFGUID rguid, /* [in] referenced guid */
369 WORD wVerMajor, /* [in] major version */
370 WORD wVerMinor, /* [in] minor version */
371 LCID lcid, /* [in] locale id */
372 ITypeLib **ppTLib) /* [out] path of typelib */
374 BSTR bstr=NULL;
375 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
377 if(SUCCEEDED(res))
379 res= LoadTypeLib(bstr, ppTLib);
380 SysFreeString(bstr);
383 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
385 return res;
389 /******************************************************************************
390 * RegisterTypeLib [OLEAUT32.163]
391 * Adds information about a type library to the System Registry
392 * NOTES
393 * Docs: ITypeLib FAR * ptlib
394 * Docs: OLECHAR FAR* szFullPath
395 * Docs: OLECHAR FAR* szHelpDir
397 * RETURNS
398 * Success: S_OK
399 * Failure: Status
401 HRESULT WINAPI RegisterTypeLib(
402 ITypeLib * ptlib, /* [in] Pointer to the library*/
403 OLECHAR * szFullPath, /* [in] full Path of the library*/
404 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
405 may be NULL*/
407 HRESULT res;
408 TLIBATTR *attr;
409 OLECHAR guid[80];
410 LPSTR guidA;
411 CHAR keyName[120];
412 CHAR tmp[MAX_PATH];
413 HKEY key, subKey;
414 UINT types, tidx;
415 TYPEKIND kind;
416 DWORD disposition;
417 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
419 if (ptlib == NULL || szFullPath == NULL)
420 return E_INVALIDARG;
422 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
423 return E_FAIL;
425 StringFromGUID2(&attr->guid, guid, 80);
426 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
427 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
428 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
429 HeapFree(GetProcessHeap(), 0, guidA);
431 res = S_OK;
432 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
433 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
435 LPOLESTR doc;
437 /* Set the human-readable name of the typelib */
438 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
440 if (RegSetValueExW(key, NULL, 0, REG_SZ,
441 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
442 res = E_FAIL;
444 SysFreeString(doc);
446 else
447 res = E_FAIL;
449 /* Make up the name of the typelib path subkey */
450 sprintf(tmp, "%lu\\", attr->lcid);
451 switch(attr->syskind) {
452 case SYS_WIN16:
453 strcat(tmp, "win16");
454 break;
456 case SYS_WIN32:
457 strcat(tmp, "win32");
458 break;
460 default:
461 TRACE("Typelib is for unsupported syskind %i\n", attr->syskind);
462 res = E_FAIL;
463 break;
466 /* Create the typelib path subkey */
467 if (res == S_OK && RegCreateKeyExA(key, tmp, 0, NULL, 0,
468 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
470 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
471 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
472 res = E_FAIL;
474 RegCloseKey(subKey);
476 else
477 res = E_FAIL;
479 /* Create the flags subkey */
480 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
481 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
483 CHAR buf[20];
484 /* FIXME: is %u correct? */
485 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
486 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
487 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
488 res = E_FAIL;
490 RegCloseKey(subKey);
492 else
493 res = E_FAIL;
495 /* create the helpdir subkey */
496 if (res == S_OK && RegCreateKeyExA(key, "HELPDIR", 0, NULL, 0,
497 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
499 BOOL freeHelpDir = FALSE;
500 OLECHAR* pIndexStr;
502 /* if we created a new key, and helpDir was null, set the helpdir
503 to the directory which contains the typelib. However,
504 if we just opened an existing key, we leave the helpdir alone */
505 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
506 szHelpDir = SysAllocString(szFullPath);
507 pIndexStr = strrchrW(szHelpDir, '\\');
508 if (pIndexStr) {
509 *pIndexStr = 0;
511 freeHelpDir = TRUE;
514 /* if we have an szHelpDir, set it! */
515 if (szHelpDir != NULL) {
516 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
517 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
518 res = E_FAIL;
522 /* tidy up */
523 if (freeHelpDir) SysFreeString(szHelpDir);
524 RegCloseKey(subKey);
526 } else {
527 res = E_FAIL;
530 RegCloseKey(key);
532 else
533 res = E_FAIL;
535 /* register OLE Automation-compatible interfaces for this typelib */
536 types = ITypeLib_GetTypeInfoCount(ptlib);
537 for (tidx=0; tidx<types; tidx++) {
538 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
539 LPOLESTR name = NULL;
540 ITypeInfo *tinfo = NULL;
542 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
544 switch (kind) {
545 case TKIND_INTERFACE:
546 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
547 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
548 break;
550 case TKIND_DISPATCH:
551 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
552 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
553 break;
555 default:
556 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
557 break;
560 if (tinfo) {
561 TYPEATTR *tattr = NULL;
562 ITypeInfo_GetTypeAttr(tinfo, &tattr);
564 if (tattr) {
565 TRACE_(typelib)("guid=%s, flags=%04x (",
566 debugstr_guid(&tattr->guid),
567 tattr->wTypeFlags);
569 if (TRACE_ON(typelib)) {
570 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
571 XX(FAPPOBJECT);
572 XX(FCANCREATE);
573 XX(FLICENSED);
574 XX(FPREDECLID);
575 XX(FHIDDEN);
576 XX(FCONTROL);
577 XX(FDUAL);
578 XX(FNONEXTENSIBLE);
579 XX(FOLEAUTOMATION);
580 XX(FRESTRICTED);
581 XX(FAGGREGATABLE);
582 XX(FREPLACEABLE);
583 XX(FDISPATCHABLE);
584 XX(FREVERSEBIND);
585 XX(FPROXY);
586 #undef XX
587 MESSAGE("\n");
591 * FIXME: The 1 is just here until we implement rpcrt4
592 * stub/proxy handling. Until then it helps IShield
593 * v6 to work.
595 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
597 if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {
598 FIXME("Registering non-oleautomation interface!\n");
601 /* register interface<->typelib coupling */
602 StringFromGUID2(&tattr->guid, guid, 80);
603 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
604 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
605 HeapFree(GetProcessHeap(), 0, guidA);
607 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
608 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
609 if (name)
610 RegSetValueExW(key, NULL, 0, REG_SZ,
611 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
613 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
614 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
615 RegSetValueExA(subKey, NULL, 0, REG_SZ,
616 PSOA, strlen(PSOA));
617 RegCloseKey(subKey);
620 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
621 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
622 RegSetValueExA(subKey, NULL, 0, REG_SZ,
623 PSOA, strlen(PSOA));
624 RegCloseKey(subKey);
627 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
628 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
629 CHAR ver[32];
630 StringFromGUID2(&attr->guid, guid, 80);
631 snprintf(ver, sizeof(ver), "%x.%x",
632 attr->wMajorVerNum, attr->wMinorVerNum);
633 RegSetValueExW(subKey, NULL, 0, REG_SZ,
634 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
635 RegSetValueExA(subKey, "Version", 0, REG_SZ,
636 ver, lstrlenA(ver));
637 RegCloseKey(subKey);
640 RegCloseKey(key);
644 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
647 ITypeInfo_Release(tinfo);
650 SysFreeString(name);
654 ITypeLib_ReleaseTLibAttr(ptlib, attr);
656 return res;
660 /******************************************************************************
661 * UnRegisterTypeLib [OLEAUT32.186]
662 * Removes information about a type library from the System Registry
663 * NOTES
665 * RETURNS
666 * Success: S_OK
667 * Failure: Status
669 HRESULT WINAPI UnRegisterTypeLib(
670 REFGUID libid, /* [in] Guid of the library */
671 WORD wVerMajor, /* [in] major version */
672 WORD wVerMinor, /* [in] minor version */
673 LCID lcid, /* [in] locale id */
674 SYSKIND syskind)
676 BSTR tlibPath = NULL;
677 DWORD tmpLength;
678 CHAR keyName[MAX_PATH];
679 CHAR* syskindName;
680 CHAR subKeyName[MAX_PATH];
681 LPSTR guidA;
682 int result = S_OK;
683 DWORD i = 0;
684 OLECHAR guid[80];
685 BOOL deleteOtherStuff;
686 HKEY key = NULL;
687 HKEY subKey = NULL;
688 TYPEATTR* typeAttr = NULL;
689 TYPEKIND kind;
690 ITypeInfo* typeInfo = NULL;
691 ITypeLib* typeLib = NULL;
692 int numTypes;
694 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
696 /* Create the path to the key */
697 StringFromGUID2(libid, guid, 80);
698 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
699 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
700 guidA, wVerMajor, wVerMinor);
701 HeapFree(GetProcessHeap(), 0, guidA);
703 /* Work out the syskind name */
704 switch(syskind) {
705 case SYS_WIN16:
706 syskindName = "win16";
707 break;
709 case SYS_WIN32:
710 syskindName = "win32";
711 break;
713 default:
714 TRACE("Unsupported syskind %i\n", syskind);
715 result = E_INVALIDARG;
716 goto end;
719 /* get the path to the typelib on disk */
720 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
721 result = E_INVALIDARG;
722 goto end;
725 /* Try and open the key to the type library. */
726 if (RegOpenKeyExA(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
727 result = E_INVALIDARG;
728 goto end;
731 /* Try and load the type library */
732 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
733 result = TYPE_E_INVALIDSTATE;
734 goto end;
737 /* remove any types registered with this typelib */
738 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
739 for (i=0; i<numTypes; i++) {
740 /* get the kind of type */
741 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
742 goto enddeleteloop;
745 /* skip non-interfaces, and get type info for the type */
746 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
747 goto enddeleteloop;
749 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
750 goto enddeleteloop;
752 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
753 goto enddeleteloop;
756 /* the path to the type */
757 StringFromGUID2(&typeAttr->guid, guid, 80);
758 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
759 snprintf(subKeyName, sizeof(subKeyName), "Interface\\%s", guidA);
760 HeapFree(GetProcessHeap(), 0, guidA);
762 /* Delete its bits */
763 if (RegOpenKeyExA(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
764 goto enddeleteloop;
766 RegDeleteKeyA(subKey, "ProxyStubClsid");
767 RegDeleteKeyA(subKey, "ProxyStubClsid32");
768 RegDeleteKeyA(subKey, "TypeLib");
769 RegCloseKey(subKey);
770 subKey = NULL;
771 RegDeleteKeyA(HKEY_CLASSES_ROOT, subKeyName);
773 enddeleteloop:
774 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
775 typeAttr = NULL;
776 if (typeInfo) ITypeInfo_Release(typeInfo);
777 typeInfo = NULL;
780 /* Now, delete the type library path subkey */
781 sprintf(subKeyName, "%lu\\%s", lcid, syskindName);
782 RegDeleteKeyA(key, subKeyName);
783 sprintf(subKeyName, "%lu", lcid);
784 RegDeleteKeyA(key, subKeyName);
786 /* check if there is anything besides the FLAGS/HELPDIR keys.
787 If there is, we don't delete them */
788 tmpLength = sizeof(subKeyName);
789 deleteOtherStuff = TRUE;
790 i = 0;
791 while(RegEnumKeyExA(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
792 tmpLength = sizeof(subKeyName);
794 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
795 if (!strcmp(subKeyName, "FLAGS")) continue;
796 if (!strcmp(subKeyName, "HELPDIR")) continue;
797 deleteOtherStuff = FALSE;
798 break;
801 /* only delete the other parts of the key if we're absolutely sure */
802 if (deleteOtherStuff) {
803 RegDeleteKeyA(key, "FLAGS");
804 RegDeleteKeyA(key, "HELPDIR");
805 RegCloseKey(key);
806 key = NULL;
808 StringFromGUID2(libid, guid, 80);
809 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
810 sprintf(keyName, "TypeLib\\%s\\%x.%x", guidA, wVerMajor, wVerMinor);
811 RegDeleteKeyA(HKEY_CLASSES_ROOT, keyName);
812 sprintf(keyName, "TypeLib\\%s", guidA);
813 RegDeleteKeyA(HKEY_CLASSES_ROOT, keyName);
814 HeapFree(GetProcessHeap(), 0, guidA);
817 end:
818 if (tlibPath) SysFreeString(tlibPath);
819 if (typeLib) ITypeLib_Release(typeLib);
820 if (subKey) RegCloseKey(subKey);
821 if (key) RegCloseKey(key);
822 return result;
825 /*======================= ITypeLib implementation =======================*/
827 typedef struct tagTLBCustData
829 GUID guid;
830 VARIANT data;
831 struct tagTLBCustData* next;
832 } TLBCustData;
834 /* data structure for import typelibs */
835 typedef struct tagTLBImpLib
837 int offset; /* offset in the file (MSFT)
838 offset in nametable (SLTG)
839 just used to identify library while reading
840 data from file */
841 GUID guid; /* libid */
842 BSTR name; /* name */
844 LCID lcid; /* lcid of imported typelib */
846 WORD wVersionMajor; /* major version number */
847 WORD wVersionMinor; /* minor version number */
849 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
850 NULL if not yet loaded */
851 struct tagTLBImpLib * next;
852 } TLBImpLib;
854 /* internal ITypeLib data */
855 typedef struct tagITypeLibImpl
857 ICOM_VFIELD(ITypeLib2);
858 ICOM_VTABLE(ITypeComp) * lpVtblTypeComp;
859 UINT ref;
860 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
862 /* strings can be stored in tlb as multibyte strings BUT they are *always*
863 * exported to the application as a UNICODE string.
865 BSTR Name;
866 BSTR DocString;
867 BSTR HelpFile;
868 BSTR HelpStringDll;
869 unsigned long dwHelpContext;
870 int TypeInfoCount; /* nr of typeinfo's in librarry */
871 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
872 int ctCustData; /* number of items in cust data list */
873 TLBCustData * pCustData; /* linked list to cust data */
874 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
875 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
876 libary. Only used while read MSFT
877 typelibs */
879 /* typelibs are cached, keyed by path, so store the linked list info within them */
880 struct tagITypeLibImpl *next, *prev;
881 WCHAR *path;
882 } ITypeLibImpl;
884 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
885 static struct ICOM_VTABLE(ITypeComp) tlbtcvt;
887 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
888 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
890 /* ITypeLib methods */
891 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
892 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
894 /*======================= ITypeInfo implementation =======================*/
896 /* data for refernced types */
897 typedef struct tagTLBRefType
899 INT index; /* Type index for internal ref or for external ref
900 it the format is SLTG. -2 indicates to
901 use guid */
903 GUID guid; /* guid of the referenced type */
904 /* if index == TLB_REF_USE_GUID */
906 HREFTYPE reference; /* The href of this ref */
907 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
908 TLB_REF_INTERNAL for internal refs
909 TLB_REF_NOT_FOUND for broken refs */
911 struct tagTLBRefType * next;
912 } TLBRefType;
914 #define TLB_REF_USE_GUID -2
916 #define TLB_REF_INTERNAL (void*)-2
917 #define TLB_REF_NOT_FOUND (void*)-1
919 /* internal Parameter data */
920 typedef struct tagTLBParDesc
922 BSTR Name;
923 int ctCustData;
924 TLBCustData * pCustData; /* linked list to cust data */
925 } TLBParDesc;
927 /* internal Function data */
928 typedef struct tagTLBFuncDesc
930 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
931 BSTR Name; /* the name of this function */
932 TLBParDesc *pParamDesc; /* array with param names and custom data */
933 int helpcontext;
934 int HelpStringContext;
935 BSTR HelpString;
936 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
937 int ctCustData;
938 TLBCustData * pCustData; /* linked list to cust data; */
939 struct tagTLBFuncDesc * next;
940 } TLBFuncDesc;
942 /* internal Variable data */
943 typedef struct tagTLBVarDesc
945 VARDESC vardesc; /* lots of info on the variable and its attributes. */
946 BSTR Name; /* the name of this variable */
947 int HelpContext;
948 int HelpStringContext; /* FIXME: where? */
949 BSTR HelpString;
950 int ctCustData;
951 TLBCustData * pCustData;/* linked list to cust data; */
952 struct tagTLBVarDesc * next;
953 } TLBVarDesc;
955 /* internal implemented interface data */
956 typedef struct tagTLBImplType
958 HREFTYPE hRef; /* hRef of interface */
959 int implflags; /* IMPLFLAG_*s */
960 int ctCustData;
961 TLBCustData * pCustData;/* linked list to custom data; */
962 struct tagTLBImplType *next;
963 } TLBImplType;
965 /* internal TypeInfo data */
966 typedef struct tagITypeInfoImpl
968 ICOM_VFIELD(ITypeInfo2);
969 ICOM_VTABLE(ITypeComp) * lpVtblTypeComp;
970 UINT ref;
971 TYPEATTR TypeAttr ; /* _lots_ of type information. */
972 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
973 int index; /* index in this typelib; */
974 /* type libs seem to store the doc strings in ascii
975 * so why should we do it in unicode?
977 BSTR Name;
978 BSTR DocString;
979 unsigned long dwHelpContext;
980 unsigned long dwHelpStringContext;
982 /* functions */
983 TLBFuncDesc * funclist; /* linked list with function descriptions */
985 /* variables */
986 TLBVarDesc * varlist; /* linked list with variable descriptions */
988 /* Implemented Interfaces */
989 TLBImplType * impltypelist;
991 TLBRefType * reflist;
992 int ctCustData;
993 TLBCustData * pCustData; /* linked list to cust data; */
994 struct tagITypeInfoImpl * next;
995 } ITypeInfoImpl;
997 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
998 static struct ICOM_VTABLE(ITypeComp) tcompvt;
1000 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
1002 typedef struct tagTLBContext
1004 unsigned int oStart; /* start of TLB in file */
1005 unsigned int pos; /* current pos */
1006 unsigned int length; /* total length */
1007 void *mapping; /* memory mapping */
1008 MSFT_SegDir * pTblDir;
1009 ITypeLibImpl* pLibInfo;
1010 } TLBContext;
1013 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1016 debug
1018 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1019 if (pTD->vt & VT_RESERVED)
1020 szVarType += strlen(strcpy(szVarType, "reserved | "));
1021 if (pTD->vt & VT_BYREF)
1022 szVarType += strlen(strcpy(szVarType, "ref to "));
1023 if (pTD->vt & VT_ARRAY)
1024 szVarType += strlen(strcpy(szVarType, "array of "));
1025 if (pTD->vt & VT_VECTOR)
1026 szVarType += strlen(strcpy(szVarType, "vector of "));
1027 switch(pTD->vt & VT_TYPEMASK) {
1028 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1029 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1030 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1031 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1032 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1033 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1034 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1035 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1036 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1037 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1038 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1039 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1040 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1041 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1042 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1043 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1044 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1045 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1046 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1047 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1048 pTD->u.hreftype); break;
1049 case VT_PTR: sprintf(szVarType, "ptr to ");
1050 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1051 break;
1052 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1053 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1054 break;
1055 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1056 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1057 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1058 break;
1060 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1064 void dump_ELEMDESC(ELEMDESC *edesc) {
1065 char buf[200];
1066 dump_TypeDesc(&edesc->tdesc,buf);
1067 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1068 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
1069 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1071 void dump_FUNCDESC(FUNCDESC *funcdesc) {
1072 int i;
1073 MESSAGE("memid is %08lx\n",funcdesc->memid);
1074 for (i=0;i<funcdesc->cParams;i++) {
1075 MESSAGE("Param %d:\n",i);
1076 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1078 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1079 switch (funcdesc->funckind) {
1080 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1081 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1082 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1083 case FUNC_STATIC: MESSAGE("static");break;
1084 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1085 default: MESSAGE("unknown");break;
1087 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1088 switch (funcdesc->invkind) {
1089 case INVOKE_FUNC: MESSAGE("func");break;
1090 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1091 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1092 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1094 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1095 switch (funcdesc->callconv) {
1096 case CC_CDECL: MESSAGE("cdecl");break;
1097 case CC_PASCAL: MESSAGE("pascal");break;
1098 case CC_STDCALL: MESSAGE("stdcall");break;
1099 case CC_SYSCALL: MESSAGE("syscall");break;
1100 default:break;
1102 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1103 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1104 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1107 void dump_IDLDESC(IDLDESC *idl) {
1108 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
1111 static const char * typekind_desc[] =
1113 "TKIND_ENUM",
1114 "TKIND_RECORD",
1115 "TKIND_MODULE",
1116 "TKIND_INTERFACE",
1117 "TKIND_DISPATCH",
1118 "TKIND_COCLASS",
1119 "TKIND_ALIAS",
1120 "TKIND_UNION",
1121 "TKIND_MAX"
1124 void dump_TYPEATTR(TYPEATTR *tattr) {
1125 char buf[200];
1126 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
1127 MESSAGE("\tlcid: %ld\n",tattr->lcid);
1128 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
1129 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
1130 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
1131 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
1132 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
1133 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
1134 MESSAGE("\tcVars: %d\n", tattr->cVars);
1135 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
1136 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
1137 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
1138 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
1139 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
1140 dump_TypeDesc(&tattr->tdescAlias,buf);
1141 MESSAGE("\ttypedesc: %s\n", buf);
1142 dump_IDLDESC(&tattr->idldescType);
1145 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1147 int i;
1148 if (!TRACE_ON(typelib))
1149 return;
1150 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1151 for (i=0;i<pfd->funcdesc.cParams;i++)
1152 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1155 dump_FUNCDESC(&(pfd->funcdesc));
1157 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1158 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1160 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1162 while (pfd)
1164 dump_TLBFuncDescOne(pfd);
1165 pfd = pfd->next;
1168 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1170 while (pvd)
1172 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1173 pvd = pvd->next;
1177 static void dump_TLBImpLib(TLBImpLib *import)
1179 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1180 debugstr_w(import->name));
1181 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1182 import->wVersionMinor, import->lcid, import->offset);
1185 static void dump_TLBRefType(TLBRefType * prt)
1187 while (prt)
1189 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1190 if(prt->index == -1)
1191 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1192 else
1193 TRACE_(typelib)("type no: %d\n", prt->index);
1195 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1196 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1197 TRACE_(typelib)("in lib\n");
1198 dump_TLBImpLib(prt->pImpTLInfo);
1200 prt = prt->next;
1204 static void dump_TLBImplType(TLBImplType * impl)
1206 while (impl) {
1207 TRACE_(typelib)(
1208 "implementing/inheriting interface hRef = %lx implflags %x\n",
1209 impl->hRef, impl->implflags);
1210 impl = impl->next;
1214 void dump_Variant(VARIANT * pvar)
1216 SYSTEMTIME st;
1218 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1220 if (pvar)
1222 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1223 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1225 TRACE(",%p", V_BYREF(pvar));
1227 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1229 TRACE(",FIXME");
1231 else switch (V_TYPE(pvar))
1233 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1234 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1235 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1236 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1237 case VT_INT:
1238 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1239 case VT_UINT:
1240 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1241 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1242 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1243 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1244 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1245 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1246 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1247 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1248 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1249 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1250 V_CY(pvar).s.Lo); break;
1251 case VT_DATE:
1252 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1253 TRACE(",<invalid>");
1254 else
1255 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1256 st.wHour, st.wMinute, st.wSecond);
1257 break;
1258 case VT_ERROR:
1259 case VT_VOID:
1260 case VT_USERDEFINED:
1261 case VT_EMPTY:
1262 case VT_NULL: break;
1263 default: TRACE(",?"); break;
1266 TRACE("}\n");
1269 static void dump_DispParms(DISPPARAMS * pdp)
1271 int index = 0;
1273 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1275 while (index < pdp->cArgs)
1277 dump_Variant( &pdp->rgvarg[index] );
1278 ++index;
1282 static void dump_TypeInfo(ITypeInfoImpl * pty)
1284 TRACE("%p ref=%u\n", pty, pty->ref);
1285 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1286 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1287 TRACE("fct:%u var:%u impl:%u\n",
1288 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1289 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1290 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1291 dump_TLBFuncDesc(pty->funclist);
1292 dump_TLBVarDesc(pty->varlist);
1293 dump_TLBImplType(pty->impltypelist);
1296 void dump_VARDESC(VARDESC *v)
1298 MESSAGE("memid %ld\n",v->memid);
1299 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1300 MESSAGE("oInst %ld\n",v->u.oInst);
1301 dump_ELEMDESC(&(v->elemdescVar));
1302 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1303 MESSAGE("varkind %d\n",v->varkind);
1306 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1308 /* VT_LPWSTR is largest type that */
1309 /* may appear in type description*/
1310 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1311 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1312 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1313 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1314 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1315 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1316 {{0},30},{{0},31}
1319 static void TLB_abort()
1321 DebugBreak();
1323 static void * TLB_Alloc(unsigned size)
1325 void * ret;
1326 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1327 /* FIXME */
1328 ERR("cannot allocate memory\n");
1330 return ret;
1333 static void TLB_Free(void * ptr)
1335 HeapFree(GetProcessHeap(), 0, ptr);
1339 /**********************************************************************
1341 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1343 /* read function */
1344 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1346 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1347 pcx->pos, count, pcx->oStart, pcx->length, where);
1349 if (where != DO_NOT_SEEK)
1351 where += pcx->oStart;
1352 if (where > pcx->length)
1354 /* FIXME */
1355 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1356 TLB_abort();
1358 pcx->pos = where;
1360 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1361 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1362 pcx->pos += count;
1363 return count;
1366 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1367 long where )
1369 DWORD ret;
1371 ret = MSFT_Read(buffer, count, pcx, where);
1372 FromLEDWords(buffer, ret);
1374 return ret;
1377 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1378 long where )
1380 DWORD ret;
1382 ret = MSFT_Read(buffer, count, pcx, where);
1383 FromLEWords(buffer, ret);
1385 return ret;
1388 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1390 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1391 memset(pGuid,0, sizeof(GUID));
1392 return;
1394 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1395 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1396 pGuid->Data2 = FromLEWord(pGuid->Data2);
1397 pGuid->Data3 = FromLEWord(pGuid->Data3);
1398 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1401 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1403 char * name;
1404 MSFT_NameIntro niName;
1405 int lengthInChars;
1406 WCHAR* pwstring = NULL;
1407 BSTR bstrName = NULL;
1409 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1410 pcx->pTblDir->pNametab.offset+offset);
1411 niName.namelen &= 0xFF; /* FIXME: correct ? */
1412 name=TLB_Alloc((niName.namelen & 0xff) +1);
1413 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1414 name[niName.namelen & 0xff]='\0';
1416 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1417 name, -1, NULL, 0);
1419 /* no invalid characters in string */
1420 if (lengthInChars)
1422 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1424 /* don't check for invalid character since this has been done previously */
1425 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1427 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1428 lengthInChars = SysStringLen(bstrName);
1429 HeapFree(GetProcessHeap(), 0, pwstring);
1432 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1433 return bstrName;
1436 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1438 char * string;
1439 INT16 length;
1440 int lengthInChars;
1441 BSTR bstr = NULL;
1443 if(offset<0) return NULL;
1444 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1445 if(length <= 0) return 0;
1446 string=TLB_Alloc(length +1);
1447 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1448 string[length]='\0';
1450 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1451 string, -1, NULL, 0);
1453 /* no invalid characters in string */
1454 if (lengthInChars)
1456 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1458 /* don't check for invalid character since this has been done previously */
1459 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1461 bstr = SysAllocStringLen(pwstring, lengthInChars);
1462 lengthInChars = SysStringLen(bstr);
1463 HeapFree(GetProcessHeap(), 0, pwstring);
1466 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1467 return bstr;
1470 * read a value and fill a VARIANT structure
1472 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1474 int size;
1476 TRACE_(typelib)("\n");
1478 if(offset <0) { /* data are packed in here */
1479 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1480 V_UNION(pVar, iVal) = offset & 0xffff;
1481 return;
1483 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1484 pcx->pTblDir->pCustData.offset + offset );
1485 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1486 switch (V_VT(pVar)){
1487 case VT_EMPTY: /* FIXME: is this right? */
1488 case VT_NULL: /* FIXME: is this right? */
1489 case VT_I2 : /* this should not happen */
1490 case VT_I4 :
1491 case VT_R4 :
1492 case VT_ERROR :
1493 case VT_BOOL :
1494 case VT_I1 :
1495 case VT_UI1 :
1496 case VT_UI2 :
1497 case VT_UI4 :
1498 case VT_INT :
1499 case VT_UINT :
1500 case VT_VOID : /* FIXME: is this right? */
1501 case VT_HRESULT :
1502 size=4; break;
1503 case VT_R8 :
1504 case VT_CY :
1505 case VT_DATE :
1506 case VT_I8 :
1507 case VT_UI8 :
1508 case VT_DECIMAL : /* FIXME: is this right? */
1509 case VT_FILETIME :
1510 size=8;break;
1511 /* pointer types with known behaviour */
1512 case VT_BSTR :{
1513 char * ptr;
1514 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1515 if(size <= 0) {
1516 FIXME("BSTR length = %d?\n", size);
1517 } else {
1518 ptr=TLB_Alloc(size);/* allocate temp buffer */
1519 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1520 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1521 /* FIXME: do we need a AtoW conversion here? */
1522 V_UNION(pVar, bstrVal[size])=L'\0';
1523 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1524 TLB_Free(ptr);
1527 size=-4; break;
1528 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1529 case VT_DISPATCH :
1530 case VT_VARIANT :
1531 case VT_UNKNOWN :
1532 case VT_PTR :
1533 case VT_SAFEARRAY :
1534 case VT_CARRAY :
1535 case VT_USERDEFINED :
1536 case VT_LPSTR :
1537 case VT_LPWSTR :
1538 case VT_BLOB :
1539 case VT_STREAM :
1540 case VT_STORAGE :
1541 case VT_STREAMED_OBJECT :
1542 case VT_STORED_OBJECT :
1543 case VT_BLOB_OBJECT :
1544 case VT_CF :
1545 case VT_CLSID :
1546 default:
1547 size=0;
1548 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1549 V_VT(pVar));
1552 if(size>0) /* (big|small) endian correct? */
1553 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1554 return;
1557 * create a linked list with custom data
1559 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1561 MSFT_CDGuid entry;
1562 TLBCustData* pNew;
1563 int count=0;
1565 TRACE_(typelib)("\n");
1567 while(offset >=0){
1568 count++;
1569 pNew=TLB_Alloc(sizeof(TLBCustData));
1570 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1571 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1572 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1573 /* add new custom data at head of the list */
1574 pNew->next=*ppCustData;
1575 *ppCustData=pNew;
1576 offset = entry.next;
1578 return count;
1581 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1582 ITypeInfoImpl *pTI)
1584 if(type <0)
1585 pTd->vt=type & VT_TYPEMASK;
1586 else
1587 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1589 if(pTd->vt == VT_USERDEFINED)
1590 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1592 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1595 static void
1596 MSFT_DoFuncs(TLBContext* pcx,
1597 ITypeInfoImpl* pTI,
1598 int cFuncs,
1599 int cVars,
1600 int offset,
1601 TLBFuncDesc** pptfd)
1604 * member information is stored in a data structure at offset
1605 * indicated by the memoffset field of the typeinfo structure
1606 * There are several distinctive parts.
1607 * the first part starts with a field that holds the total length
1608 * of this (first) part excluding this field. Then follow the records,
1609 * for each member there is one record.
1611 * First entry is always the length of the record (excluding this
1612 * length word).
1613 * Rest of the record depends on the type of the member. If there is
1614 * a field indicating the member type (function variable intereface etc)
1615 * I have not found it yet. At this time we depend on the information
1616 * in the type info and the usual order how things are stored.
1618 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1619 * for each member;
1621 * Third is a equal sized array with file offsets to the name entry
1622 * of each member.
1624 * Forth and last (?) part is an array with offsets to the records in the
1625 * first part of this file segment.
1628 int infolen, nameoffset, reclength, nrattributes, i;
1629 int recoffset = offset + sizeof(INT);
1631 char recbuf[512];
1632 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1634 TRACE_(typelib)("\n");
1636 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1638 for ( i = 0; i < cFuncs ; i++ )
1640 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1642 /* name, eventually add to a hash table */
1643 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1644 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1646 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1648 /* read the function information record */
1649 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1651 reclength &= 0x1ff;
1653 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1655 /* do the attributes */
1656 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1657 / sizeof(int);
1659 if ( nrattributes > 0 )
1661 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1663 if ( nrattributes > 1 )
1665 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1666 pFuncRec->OptAttr[1]) ;
1668 if ( nrattributes > 2 )
1670 if ( pFuncRec->FKCCIC & 0x2000 )
1672 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1674 else
1676 (*pptfd)->Entry = MSFT_ReadString(pcx,
1677 pFuncRec->OptAttr[2]);
1679 if( nrattributes > 5 )
1681 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1683 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1685 MSFT_CustData(pcx,
1686 pFuncRec->OptAttr[6],
1687 &(*pptfd)->pCustData);
1694 /* fill the FuncDesc Structure */
1695 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1696 offset + infolen + ( i + 1) * sizeof(INT));
1698 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1699 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1700 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1701 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1702 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1703 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1704 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1706 MSFT_GetTdesc(pcx,
1707 pFuncRec->DataType,
1708 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1709 pTI);
1711 /* do the parameters/arguments */
1712 if(pFuncRec->nrargs)
1714 int j = 0;
1715 MSFT_ParameterInfo paraminfo;
1717 (*pptfd)->funcdesc.lprgelemdescParam =
1718 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1720 (*pptfd)->pParamDesc =
1721 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1723 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1724 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1726 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1728 TYPEDESC* lpArgTypeDesc = 0;
1730 MSFT_GetTdesc(pcx,
1731 paraminfo.DataType,
1732 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1733 pTI);
1735 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1737 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1739 /* SEEK value = jump to offset,
1740 * from there jump to the end of record,
1741 * go back by (j-1) arguments
1743 MSFT_ReadLEDWords( &paraminfo ,
1744 sizeof(MSFT_ParameterInfo), pcx,
1745 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1746 * sizeof(MSFT_ParameterInfo)));
1747 lpArgTypeDesc =
1748 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1750 while ( lpArgTypeDesc != NULL )
1752 switch ( lpArgTypeDesc->vt )
1754 case VT_PTR:
1755 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1756 break;
1758 case VT_CARRAY:
1759 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1760 break;
1762 case VT_USERDEFINED:
1763 MSFT_DoRefType(pcx, pTI,
1764 lpArgTypeDesc->u.hreftype);
1766 lpArgTypeDesc = NULL;
1767 break;
1769 default:
1770 lpArgTypeDesc = NULL;
1776 /* parameter is the return value! */
1777 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1779 TYPEDESC* lpArgTypeDesc;
1781 (*pptfd)->funcdesc.elemdescFunc =
1782 (*pptfd)->funcdesc.lprgelemdescParam[j];
1784 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1786 while ( lpArgTypeDesc != NULL )
1788 switch ( lpArgTypeDesc->vt )
1790 case VT_PTR:
1791 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1792 break;
1793 case VT_CARRAY:
1794 lpArgTypeDesc =
1795 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1797 break;
1799 case VT_USERDEFINED:
1800 MSFT_DoRefType(pcx,
1801 pTI,
1802 lpArgTypeDesc->u.hreftype);
1804 lpArgTypeDesc = NULL;
1805 break;
1807 default:
1808 lpArgTypeDesc = NULL;
1813 /* second time around */
1814 for(j=0;j<pFuncRec->nrargs;j++)
1816 /* name */
1817 (*pptfd)->pParamDesc[j].Name =
1818 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1820 /* default value */
1821 if ( (PARAMFLAG_FHASDEFAULT &
1822 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1823 ((pFuncRec->FKCCIC) & 0x1000) )
1825 INT* pInt = (INT *)((char *)pFuncRec +
1826 reclength -
1827 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1829 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1831 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1832 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1834 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1835 pInt[j], pcx);
1837 /* custom info */
1838 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1840 MSFT_CustData(pcx,
1841 pFuncRec->OptAttr[7+j],
1842 &(*pptfd)->pParamDesc[j].pCustData);
1847 /* scode is not used: archaic win16 stuff FIXME: right? */
1848 (*pptfd)->funcdesc.cScodes = 0 ;
1849 (*pptfd)->funcdesc.lprgscode = NULL ;
1851 pptfd = & ((*pptfd)->next);
1852 recoffset += reclength;
1856 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1857 int cVars, int offset, TLBVarDesc ** pptvd)
1859 int infolen, nameoffset, reclength;
1860 char recbuf[256];
1861 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1862 int i;
1863 int recoffset;
1865 TRACE_(typelib)("\n");
1867 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1868 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1869 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1870 recoffset += offset+sizeof(INT);
1871 for(i=0;i<cVars;i++){
1872 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1873 /* name, eventually add to a hash table */
1874 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1875 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1876 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1877 /* read the variable information record */
1878 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1879 reclength &=0xff;
1880 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1881 /* Optional data */
1882 if(reclength >(6*sizeof(INT)) )
1883 (*pptvd)->HelpContext=pVarRec->HelpContext;
1884 if(reclength >(7*sizeof(INT)) )
1885 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1886 if(reclength >(8*sizeof(INT)) )
1887 if(reclength >(9*sizeof(INT)) )
1888 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1889 /* fill the VarDesc Structure */
1890 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1891 offset + infolen + ( i + 1) * sizeof(INT));
1892 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1893 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1894 MSFT_GetTdesc(pcx, pVarRec->DataType,
1895 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1896 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1897 if(pVarRec->VarKind == VAR_CONST ){
1898 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1899 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1900 pVarRec->OffsValue, pcx);
1901 } else
1902 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1903 pptvd=&((*pptvd)->next);
1904 recoffset += reclength;
1907 /* fill in data for a hreftype (offset). When the refernced type is contained
1908 * in the typelib, it's just an (file) offset in the type info base dir.
1909 * If comes from import, it's an offset+1 in the ImpInfo table
1910 * */
1911 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1912 int offset)
1914 int j;
1915 TLBRefType **ppRefType = &pTI->reflist;
1917 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1919 while(*ppRefType) {
1920 if((*ppRefType)->reference == offset)
1921 return;
1922 ppRefType = &(*ppRefType)->next;
1925 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1926 sizeof(**ppRefType));
1928 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1929 /* external typelib */
1930 MSFT_ImpInfo impinfo;
1931 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1933 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1935 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1936 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1937 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1938 if(pImpLib->offset==impinfo.oImpFile) break;
1939 pImpLib=pImpLib->next;
1941 if(pImpLib){
1942 (*ppRefType)->reference=offset;
1943 (*ppRefType)->pImpTLInfo = pImpLib;
1944 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1945 (*ppRefType)->index = TLB_REF_USE_GUID;
1946 }else{
1947 ERR("Cannot find a reference\n");
1948 (*ppRefType)->reference=-1;
1949 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1951 }else{
1952 /* in this typelib */
1953 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1954 (*ppRefType)->reference=offset;
1955 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1959 /* process Implemented Interfaces of a com class */
1960 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1961 int offset)
1963 int i;
1964 MSFT_RefRecord refrec;
1965 TLBImplType **ppImpl = &pTI->impltypelist;
1967 TRACE_(typelib)("\n");
1969 for(i=0;i<count;i++){
1970 if(offset<0) break; /* paranoia */
1971 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1972 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1973 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1974 (*ppImpl)->hRef = refrec.reftype;
1975 (*ppImpl)->implflags=refrec.flags;
1976 (*ppImpl)->ctCustData=
1977 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1978 offset=refrec.onext;
1979 ppImpl=&((*ppImpl)->next);
1983 * process a typeinfo record
1985 ITypeInfoImpl * MSFT_DoTypeInfo(
1986 TLBContext *pcx,
1987 int count,
1988 ITypeLibImpl * pLibInfo)
1990 MSFT_TypeInfoBase tiBase;
1991 ITypeInfoImpl *ptiRet;
1993 TRACE_(typelib)("count=%u\n", count);
1995 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1996 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
1997 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1998 /* this is where we are coming from */
1999 ptiRet->pTypeLib = pLibInfo;
2000 ptiRet->index=count;
2001 /* fill in the typeattr fields */
2002 WARN("Assign constructor/destructor memid\n");
2004 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2005 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2006 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2007 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2008 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2009 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2010 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2011 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2012 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2013 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2014 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2015 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2016 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2017 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2018 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2019 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2020 MSFT_GetTdesc(pcx, tiBase.datatype1,
2021 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2023 /* FIXME: */
2024 /* IDLDESC idldescType; *//* never saw this one != zero */
2026 /* name, eventually add to a hash table */
2027 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2028 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2029 /* help info */
2030 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2031 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2032 ptiRet->dwHelpContext=tiBase.helpcontext;
2033 /* note: InfoType's Help file and HelpStringDll come from the containing
2034 * library. Further HelpString and Docstring appear to be the same thing :(
2036 /* functions */
2037 if(ptiRet->TypeAttr.cFuncs >0 )
2038 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2039 ptiRet->TypeAttr.cVars,
2040 tiBase.memoffset, & ptiRet->funclist);
2041 /* variables */
2042 if(ptiRet->TypeAttr.cVars >0 )
2043 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2044 ptiRet->TypeAttr.cVars,
2045 tiBase.memoffset, & ptiRet->varlist);
2046 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2047 switch(ptiRet->TypeAttr.typekind)
2049 case TKIND_COCLASS:
2050 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2051 tiBase.datatype1);
2052 break;
2053 case TKIND_DISPATCH:
2054 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2056 if (tiBase.datatype1 != -1)
2058 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2059 ptiRet->impltypelist->hRef = tiBase.datatype1;
2061 else
2062 { /* FIXME: This is a really bad hack to add IDispatch */
2063 const char* szStdOle = "stdole2.tlb\0";
2064 int nStdOleLen = strlen(szStdOle);
2065 TLBRefType **ppRef = &ptiRet->reflist;
2067 while(*ppRef) {
2068 if((*ppRef)->reference == -1)
2069 break;
2070 ppRef = &(*ppRef)->next;
2072 if(!*ppRef) {
2073 *ppRef = TLB_Alloc(sizeof(**ppRef));
2074 (*ppRef)->guid = IID_IDispatch;
2075 (*ppRef)->reference = -1;
2076 (*ppRef)->index = TLB_REF_USE_GUID;
2077 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2078 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2079 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2080 nStdOleLen + 1);
2082 MultiByteToWideChar(CP_ACP,
2083 MB_PRECOMPOSED,
2084 szStdOle,
2086 (*ppRef)->pImpTLInfo->name,
2087 SysStringLen((*ppRef)->pImpTLInfo->name));
2089 (*ppRef)->pImpTLInfo->lcid = 0;
2090 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2091 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2094 break;
2095 default:
2096 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2097 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2098 ptiRet->impltypelist->hRef = tiBase.datatype1;
2099 break;
2102 ptiRet->ctCustData=
2103 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2105 TRACE_(typelib)("%s guid: %s kind:%s\n",
2106 debugstr_w(ptiRet->Name),
2107 debugstr_guid(&ptiRet->TypeAttr.guid),
2108 typekind_desc[ptiRet->TypeAttr.typekind]);
2110 return ptiRet;
2113 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2114 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2115 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2116 * tradeoff here.
2118 static ITypeLibImpl *tlb_cache_first;
2119 static CRITICAL_SECTION cache_section;
2120 static CRITICAL_SECTION_DEBUG cache_section_debug =
2122 0, 0, &cache_section,
2123 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2124 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
2126 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2129 /****************************************************************************
2130 * TLB_ReadTypeLib
2132 * find the type of the typelib file and map the typelib resource into
2133 * the memory
2135 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2136 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2137 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2139 ITypeLibImpl *entry;
2140 int ret = TYPE_E_CANTLOADLIBRARY;
2141 DWORD dwSignature = 0;
2142 HANDLE hFile;
2144 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2146 *ppTypeLib = NULL;
2148 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2149 EnterCriticalSection(&cache_section);
2150 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2152 if (!strcmpiW(entry->path, pszFileName))
2154 TRACE("cache hit\n");
2155 *ppTypeLib = (ITypeLib2*)entry;
2156 ITypeLib_AddRef(*ppTypeLib);
2157 LeaveCriticalSection(&cache_section);
2158 return S_OK;
2161 LeaveCriticalSection(&cache_section);
2163 /* check the signature of the file */
2164 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2165 if (INVALID_HANDLE_VALUE != hFile)
2167 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2168 if (hMapping)
2170 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2171 if(pBase)
2173 /* retrieve file size */
2174 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2176 /* first try to load as *.tlb */
2177 dwSignature = FromLEDWord(*((DWORD*) pBase));
2178 if ( dwSignature == MSFT_SIGNATURE)
2180 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2182 else if ( dwSignature == SLTG_SIGNATURE)
2184 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2186 UnmapViewOfFile(pBase);
2188 CloseHandle(hMapping);
2190 CloseHandle(hFile);
2193 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2195 /* find the typelibrary resource*/
2196 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2197 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2198 if (hinstDLL)
2200 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2201 "TYPELIB");
2202 if (hrsrc)
2204 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2205 if (hGlobal)
2207 LPVOID pBase = LockResource(hGlobal);
2208 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2210 if (pBase)
2212 /* try to load as incore resource */
2213 dwSignature = FromLEDWord(*((DWORD*) pBase));
2214 if ( dwSignature == MSFT_SIGNATURE)
2216 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2218 else if ( dwSignature == SLTG_SIGNATURE)
2220 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2222 else
2224 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2227 FreeResource( hGlobal );
2230 FreeLibrary(hinstDLL);
2234 if(*ppTypeLib) {
2235 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2237 TRACE("adding to cache\n");
2238 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2239 lstrcpyW(impl->path, pszFileName);
2240 /* We should really canonicalise the path here. */
2242 /* FIXME: check if it has added already in the meantime */
2243 EnterCriticalSection(&cache_section);
2244 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2245 impl->prev = NULL;
2246 tlb_cache_first = impl;
2247 LeaveCriticalSection(&cache_section);
2248 ret = S_OK;
2249 } else
2250 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2252 return ret;
2255 /*================== ITypeLib(2) Methods ===================================*/
2257 /****************************************************************************
2258 * ITypeLib2_Constructor_MSFT
2260 * loading an MSFT typelib from an in-memory image
2262 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2264 TLBContext cx;
2265 long lPSegDir;
2266 MSFT_Header tlbHeader;
2267 MSFT_SegDir tlbSegDir;
2268 ITypeLibImpl * pTypeLibImpl;
2270 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2272 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2273 if (!pTypeLibImpl) return NULL;
2275 pTypeLibImpl->lpVtbl = &tlbvt;
2276 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2277 pTypeLibImpl->ref = 1;
2279 /* get pointer to beginning of typelib data */
2280 cx.pos = 0;
2281 cx.oStart=0;
2282 cx.mapping = pLib;
2283 cx.pLibInfo = pTypeLibImpl;
2284 cx.length = dwTLBLength;
2286 /* read header */
2287 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2288 TRACE("header:\n");
2289 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2290 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2291 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2292 return NULL;
2294 /* there is a small amount of information here until the next important
2295 * part:
2296 * the segment directory . Try to calculate the amount of data */
2297 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2299 /* now read the segment directory */
2300 TRACE("read segment directory (at %ld)\n",lPSegDir);
2301 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2302 cx.pTblDir = &tlbSegDir;
2304 /* just check two entries */
2305 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2307 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2308 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2309 return NULL;
2312 /* now fill our internal data */
2313 /* TLIBATTR fields */
2314 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2316 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2317 /* Windows seems to have zero here, is this correct? */
2318 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2319 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2320 else
2321 pTypeLibImpl->LibAttr.lcid = 0;
2323 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2324 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2325 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2326 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2328 /* name, eventually add to a hash table */
2329 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2331 /* help info */
2332 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2333 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2335 if( tlbHeader.varflags & HELPDLLFLAG)
2337 int offset;
2338 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2339 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2342 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2344 /* custom data */
2345 if(tlbHeader.CustomDataOffset >= 0)
2347 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2350 /* fill in typedescriptions */
2351 if(tlbSegDir.pTypdescTab.length > 0)
2353 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2354 INT16 td[4];
2355 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2356 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2357 for(i=0; i<cTD; )
2359 /* FIXME: add several sanity checks here */
2360 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2361 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2363 /* FIXME: check safearray */
2364 if(td[3] < 0)
2365 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2366 else
2367 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2369 else if(td[0] == VT_CARRAY)
2371 /* array descr table here */
2372 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2374 else if(td[0] == VT_USERDEFINED)
2376 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2378 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2381 /* second time around to fill the array subscript info */
2382 for(i=0;i<cTD;i++)
2384 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2385 if(tlbSegDir.pArrayDescriptions.offset>0)
2387 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2388 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2390 if(td[1]<0)
2391 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2392 else
2393 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2395 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2397 for(j = 0; j<td[2]; j++)
2399 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2400 sizeof(INT), &cx, DO_NOT_SEEK);
2401 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2402 sizeof(INT), &cx, DO_NOT_SEEK);
2405 else
2407 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2408 ERR("didn't find array description data\n");
2413 /* imported type libs */
2414 if(tlbSegDir.pImpFiles.offset>0)
2416 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2417 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2418 UINT16 size;
2420 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2422 char *name;
2423 DWORD len;
2425 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2426 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2427 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2429 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2430 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2431 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2432 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2434 size >>= 2;
2435 name = TLB_Alloc(size+1);
2436 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2437 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2438 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2439 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2440 TLB_Free(name);
2442 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2443 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2445 ppImpLib = &(*ppImpLib)->next;
2449 /* type info's */
2450 if(tlbHeader.nrtypeinfos >= 0 )
2452 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2453 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2454 int i;
2456 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2458 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2460 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2461 ppTI = &((*ppTI)->next);
2462 (pTypeLibImpl->TypeInfoCount)++;
2466 TRACE("(%p)\n", pTypeLibImpl);
2467 return (ITypeLib2*) pTypeLibImpl;
2471 static BSTR TLB_MultiByteToBSTR(char *ptr)
2473 DWORD len;
2474 WCHAR *nameW;
2475 BSTR ret;
2477 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2478 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2479 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2480 ret = SysAllocString(nameW);
2481 HeapFree(GetProcessHeap(), 0, nameW);
2482 return ret;
2485 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2487 char b[3];
2488 int i;
2489 short s;
2491 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2492 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2493 return FALSE;
2496 guid->Data4[0] = s >> 8;
2497 guid->Data4[1] = s & 0xff;
2499 b[2] = '\0';
2500 for(i = 0; i < 6; i++) {
2501 memcpy(b, str + 24 + 2 * i, 2);
2502 guid->Data4[i + 2] = strtol(b, NULL, 16);
2504 return TRUE;
2507 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2509 WORD bytelen;
2510 DWORD len;
2511 WCHAR *nameW;
2513 *pBstr = NULL;
2514 bytelen = *(WORD*)ptr;
2515 if(bytelen == 0xffff) return 2;
2516 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2517 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2518 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2519 *pBstr = SysAllocStringLen(nameW, len);
2520 HeapFree(GetProcessHeap(), 0, nameW);
2521 return bytelen + 2;
2524 static WORD SLTG_ReadStringA(char *ptr, char **str)
2526 WORD bytelen;
2528 *str = NULL;
2529 bytelen = *(WORD*)ptr;
2530 if(bytelen == 0xffff) return 2;
2531 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2532 memcpy(*str, ptr + 2, bytelen);
2533 (*str)[bytelen] = '\0';
2534 return bytelen + 2;
2537 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2539 char *ptr = pLibBlk;
2540 WORD w;
2542 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2543 FIXME("libblk magic = %04x\n", w);
2544 return 0;
2547 ptr += 6;
2548 if((w = *(WORD*)ptr) != 0xffff) {
2549 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2550 ptr += w;
2552 ptr += 2;
2554 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2556 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2558 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2559 ptr += 4;
2561 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2562 ptr += 2;
2564 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2565 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2566 else
2567 pTypeLibImpl->LibAttr.lcid = 0;
2568 ptr += 2;
2570 ptr += 4; /* skip res12 */
2572 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2573 ptr += 2;
2575 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2576 ptr += 2;
2578 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2579 ptr += 2;
2581 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2582 ptr += sizeof(GUID);
2584 return ptr - (char*)pLibBlk;
2587 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2589 BOOL done = FALSE;
2590 TYPEDESC *pTD = &pElem->tdesc;
2592 /* Handle [in/out] first */
2593 if((*pType & 0xc000) == 0xc000)
2594 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2595 else if(*pType & 0x8000)
2596 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2597 else if(*pType & 0x4000)
2598 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2599 else
2600 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2602 if(*pType & 0x2000)
2603 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2605 if(*pType & 0x80)
2606 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2608 while(!done) {
2609 if((*pType & 0xe00) == 0xe00) {
2610 pTD->vt = VT_PTR;
2611 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2612 sizeof(TYPEDESC));
2613 pTD = pTD->u.lptdesc;
2615 switch(*pType & 0x7f) {
2616 case VT_PTR:
2617 pTD->vt = VT_PTR;
2618 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2619 sizeof(TYPEDESC));
2620 pTD = pTD->u.lptdesc;
2621 break;
2623 case VT_USERDEFINED:
2624 pTD->vt = VT_USERDEFINED;
2625 pTD->u.hreftype = *(++pType) / 4;
2626 done = TRUE;
2627 break;
2629 case VT_CARRAY:
2631 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2632 array */
2634 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2636 pTD->vt = VT_CARRAY;
2637 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2638 sizeof(ARRAYDESC) +
2639 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2640 pTD->u.lpadesc->cDims = pSA->cDims;
2641 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2642 pSA->cDims * sizeof(SAFEARRAYBOUND));
2644 pTD = &pTD->u.lpadesc->tdescElem;
2645 break;
2648 case VT_SAFEARRAY:
2650 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2651 useful? */
2653 pType++;
2654 pTD->vt = VT_SAFEARRAY;
2655 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2656 sizeof(TYPEDESC));
2657 pTD = pTD->u.lptdesc;
2658 break;
2660 default:
2661 pTD->vt = *pType & 0x7f;
2662 done = TRUE;
2663 break;
2665 pType++;
2667 return pType;
2671 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2672 char *pNameTable)
2674 int ref;
2675 char *name;
2676 TLBRefType **ppRefType;
2678 if(pRef->magic != SLTG_REF_MAGIC) {
2679 FIXME("Ref magic = %x\n", pRef->magic);
2680 return;
2682 name = ( (char*)(&pRef->names) + pRef->number);
2684 ppRefType = &pTI->reflist;
2685 for(ref = 0; ref < pRef->number >> 3; ref++) {
2686 char *refname;
2687 unsigned int lib_offs, type_num;
2689 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2690 sizeof(**ppRefType));
2692 name += SLTG_ReadStringA(name, &refname);
2693 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2694 FIXME("Can't sscanf ref\n");
2695 if(lib_offs != 0xffff) {
2696 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2698 while(*import) {
2699 if((*import)->offset == lib_offs)
2700 break;
2701 import = &(*import)->next;
2703 if(!*import) {
2704 char fname[MAX_PATH+1];
2705 int len;
2707 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2708 sizeof(**import));
2709 (*import)->offset = lib_offs;
2710 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2711 &(*import)->guid);
2712 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2713 &(*import)->wVersionMajor,
2714 &(*import)->wVersionMinor,
2715 &(*import)->lcid, fname) != 4) {
2716 FIXME("can't sscanf ref %s\n",
2717 pNameTable + lib_offs + 40);
2719 len = strlen(fname);
2720 if(fname[len-1] != '#')
2721 FIXME("fname = %s\n", fname);
2722 fname[len-1] = '\0';
2723 (*import)->name = TLB_MultiByteToBSTR(fname);
2725 (*ppRefType)->pImpTLInfo = *import;
2726 } else { /* internal ref */
2727 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2729 (*ppRefType)->reference = ref;
2730 (*ppRefType)->index = type_num;
2732 HeapFree(GetProcessHeap(), 0, refname);
2733 ppRefType = &(*ppRefType)->next;
2735 if((BYTE)*name != SLTG_REF_MAGIC)
2736 FIXME("End of ref block magic = %x\n", *name);
2737 dump_TLBRefType(pTI->reflist);
2740 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2741 BOOL OneOnly)
2743 SLTG_ImplInfo *info;
2744 TLBImplType **ppImplType = &pTI->impltypelist;
2745 /* I don't really get this structure, usually it's 0x16 bytes
2746 long, but iuser.tlb contains some that are 0x18 bytes long.
2747 That's ok because we can use the next ptr to jump to the next
2748 one. But how do we know the length of the last one? The WORD
2749 at offs 0x8 might be the clue. For now I'm just assuming that
2750 the last one is the regular 0x16 bytes. */
2752 info = (SLTG_ImplInfo*)pBlk;
2753 while(1) {
2754 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2755 sizeof(**ppImplType));
2756 (*ppImplType)->hRef = info->ref;
2757 (*ppImplType)->implflags = info->impltypeflags;
2758 pTI->TypeAttr.cImplTypes++;
2759 ppImplType = &(*ppImplType)->next;
2761 if(info->next == 0xffff)
2762 break;
2763 if(OneOnly)
2764 FIXME("Interface inheriting more than one interface\n");
2765 info = (SLTG_ImplInfo*)(pBlk + info->next);
2767 info++; /* see comment at top of function */
2768 return (char*)info;
2771 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2772 char *pNameTable)
2774 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2775 SLTG_MemberHeader *pMemHeader;
2776 char *pFirstItem, *pNextItem;
2778 if(pTIHeader->href_table != 0xffffffff) {
2779 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2780 pNameTable);
2784 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2786 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2788 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2789 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2792 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2796 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2797 char *pNameTable)
2799 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2800 SLTG_MemberHeader *pMemHeader;
2801 SLTG_Function *pFunc;
2802 char *pFirstItem, *pNextItem;
2803 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2804 int num = 0;
2806 if(pTIHeader->href_table != 0xffffffff) {
2807 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2808 pNameTable);
2811 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2813 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2815 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2816 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2819 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2820 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2822 int param;
2823 WORD *pType, *pArg;
2825 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2826 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2827 FIXME("func magic = %02x\n", pFunc->magic);
2828 return NULL;
2830 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2831 sizeof(**ppFuncDesc));
2832 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2834 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2835 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2836 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2837 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2838 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2839 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2841 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2842 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2844 if(pFunc->retnextopt & 0x80)
2845 pType = &pFunc->rettype;
2846 else
2847 pType = (WORD*)(pFirstItem + pFunc->rettype);
2850 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2852 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2853 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2854 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2855 (*ppFuncDesc)->pParamDesc =
2856 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2857 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2859 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2861 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2862 char *paramName = pNameTable + *pArg;
2863 BOOL HaveOffs;
2864 /* If arg type follows then paramName points to the 2nd
2865 letter of the name, else the next WORD is an offset to
2866 the arg type and paramName points to the first letter.
2867 So let's take one char off paramName and see if we're
2868 pointing at an alpha-numeric char. However if *pArg is
2869 0xffff or 0xfffe then the param has no name, the former
2870 meaning that the next WORD is the type, the latter
2871 meaning the the next WORD is an offset to the type. */
2873 HaveOffs = FALSE;
2874 if(*pArg == 0xffff)
2875 paramName = NULL;
2876 else if(*pArg == 0xfffe) {
2877 paramName = NULL;
2878 HaveOffs = TRUE;
2880 else if(!isalnum(*(paramName-1)))
2881 HaveOffs = TRUE;
2883 pArg++;
2885 if(HaveOffs) { /* the next word is an offset to type */
2886 pType = (WORD*)(pFirstItem + *pArg);
2887 SLTG_DoType(pType, pFirstItem,
2888 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2889 pArg++;
2890 } else {
2891 if(paramName)
2892 paramName--;
2893 pArg = SLTG_DoType(pArg, pFirstItem,
2894 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2897 /* Are we an optional param ? */
2898 if((*ppFuncDesc)->funcdesc.cParams - param <=
2899 (*ppFuncDesc)->funcdesc.cParamsOpt)
2900 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2902 if(paramName) {
2903 (*ppFuncDesc)->pParamDesc[param].Name =
2904 TLB_MultiByteToBSTR(paramName);
2908 ppFuncDesc = &((*ppFuncDesc)->next);
2909 if(pFunc->next == 0xffff) break;
2911 pTI->TypeAttr.cFuncs = num;
2912 dump_TLBFuncDesc(pTI->funclist);
2913 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2916 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2917 char *pNameTable)
2919 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2920 SLTG_MemberHeader *pMemHeader;
2921 SLTG_RecordItem *pItem;
2922 char *pFirstItem;
2923 TLBVarDesc **ppVarDesc = &pTI->varlist;
2924 int num = 0;
2925 WORD *pType;
2926 char buf[300];
2928 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2930 pFirstItem = (char*)(pMemHeader + 1);
2931 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2932 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2933 if(pItem->magic != SLTG_RECORD_MAGIC) {
2934 FIXME("record magic = %02x\n", pItem->magic);
2935 return NULL;
2937 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2938 sizeof(**ppVarDesc));
2939 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2940 (*ppVarDesc)->vardesc.memid = pItem->memid;
2941 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2942 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2944 if(pItem->typepos == 0x02)
2945 pType = &pItem->type;
2946 else if(pItem->typepos == 0x00)
2947 pType = (WORD*)(pFirstItem + pItem->type);
2948 else {
2949 FIXME("typepos = %02x\n", pItem->typepos);
2950 break;
2953 SLTG_DoType(pType, pFirstItem,
2954 &(*ppVarDesc)->vardesc.elemdescVar);
2956 /* FIXME("helpcontext, helpstring\n"); */
2958 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2960 ppVarDesc = &((*ppVarDesc)->next);
2961 if(pItem->next == 0xffff) break;
2963 pTI->TypeAttr.cVars = num;
2964 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2967 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2968 char *pNameTable)
2970 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2971 SLTG_MemberHeader *pMemHeader;
2972 SLTG_AliasItem *pItem;
2973 int i, mustbelast;
2975 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2976 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2978 mustbelast = 0;
2979 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2980 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2981 if (pItem->vt == 0xffff) {
2982 if (i<(pMemHeader->cbExtra/4-1))
2983 FIXME("Endmarker too early in process alias data!\n");
2984 break;
2986 if (mustbelast) {
2987 FIXME("Chain extends over last entry?\n");
2988 break;
2990 if (pItem->vt == VT_USERDEFINED) {
2991 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2992 /* guessing here ... */
2993 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2994 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2995 mustbelast = 1;
2996 } else {
2997 FIXME("alias %d: 0x%x\n",i,pItem->vt);
2998 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3000 pItem++;
3002 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3005 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3006 char *pNameTable)
3008 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3009 SLTG_MemberHeader *pMemHeader;
3010 SLTG_AliasItem *pItem;
3012 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3013 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3014 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3015 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3016 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3019 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3020 char *pNameTable)
3022 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3023 SLTG_MemberHeader *pMemHeader;
3024 SLTG_EnumItem *pItem;
3025 char *pFirstItem;
3026 TLBVarDesc **ppVarDesc = &pTI->varlist;
3027 int num = 0;
3029 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3031 pFirstItem = (char*)(pMemHeader + 1);
3032 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3033 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3034 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3035 FIXME("enumitem magic = %04x\n", pItem->magic);
3036 return NULL;
3038 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3039 sizeof(**ppVarDesc));
3040 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3041 (*ppVarDesc)->vardesc.memid = pItem->memid;
3042 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3043 sizeof(VARIANT));
3044 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3045 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3046 *(INT*)(pItem->value + pFirstItem);
3047 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3048 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3049 /* FIXME("helpcontext, helpstring\n"); */
3051 ppVarDesc = &((*ppVarDesc)->next);
3052 if(pItem->next == 0xffff) break;
3054 pTI->TypeAttr.cVars = num;
3055 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3058 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
3059 managable copy of it into this */
3060 typedef struct {
3061 WORD small_no;
3062 char *index_name;
3063 char *other_name;
3064 WORD res1a;
3065 WORD name_offs;
3066 WORD more_bytes;
3067 char *extra;
3068 WORD res20;
3069 DWORD helpcontext;
3070 WORD res26;
3071 GUID uuid;
3072 } SLTG_InternalOtherTypeInfo;
3074 /****************************************************************************
3075 * ITypeLib2_Constructor_SLTG
3077 * loading a SLTG typelib from an in-memory image
3079 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3081 ITypeLibImpl *pTypeLibImpl;
3082 SLTG_Header *pHeader;
3083 SLTG_BlkEntry *pBlkEntry;
3084 SLTG_Magic *pMagic;
3085 SLTG_Index *pIndex;
3086 SLTG_Pad9 *pPad9;
3087 LPVOID pBlk, pFirstBlk;
3088 SLTG_LibBlk *pLibBlk;
3089 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3090 char *pAfterOTIBlks = NULL;
3091 char *pNameTable, *ptr;
3092 int i;
3093 DWORD len, order;
3094 ITypeInfoImpl **ppTypeInfoImpl;
3096 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3098 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3099 if (!pTypeLibImpl) return NULL;
3101 pTypeLibImpl->lpVtbl = &tlbvt;
3102 pTypeLibImpl->ref = 1;
3104 pHeader = pLib;
3106 TRACE("header:\n");
3107 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3108 pHeader->nrOfFileBlks );
3109 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3110 FIXME("Header type magic 0x%08lx not supported.\n",
3111 pHeader->SLTG_magic);
3112 return NULL;
3115 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3116 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3118 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3119 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3121 /* Next we have a magic block */
3122 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3124 /* Let's see if we're still in sync */
3125 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3126 sizeof(SLTG_COMPOBJ_MAGIC))) {
3127 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3128 return NULL;
3130 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3131 sizeof(SLTG_DIR_MAGIC))) {
3132 FIXME("dir magic = %s\n", pMagic->dir_magic);
3133 return NULL;
3136 pIndex = (SLTG_Index*)(pMagic+1);
3138 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3140 pFirstBlk = (LPVOID)(pPad9 + 1);
3142 /* We'll set up a ptr to the main library block, which is the last one. */
3144 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3145 pBlkEntry[order].next != 0;
3146 order = pBlkEntry[order].next - 1, i++) {
3147 pBlk = (char*)pBlk + pBlkEntry[order].len;
3149 pLibBlk = pBlk;
3151 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3153 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3154 interspersed */
3156 len += 0x40;
3158 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3160 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3161 sizeof(*pOtherTypeInfoBlks) *
3162 pTypeLibImpl->TypeInfoCount);
3165 ptr = (char*)pLibBlk + len;
3167 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3168 WORD w, extra;
3169 len = 0;
3171 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3173 w = *(WORD*)(ptr + 2);
3174 if(w != 0xffff) {
3175 len += w;
3176 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3177 w+1);
3178 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3179 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3181 w = *(WORD*)(ptr + 4 + len);
3182 if(w != 0xffff) {
3183 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3184 len += w;
3185 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3186 w+1);
3187 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3188 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3190 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3191 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3192 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3193 if(extra) {
3194 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3195 extra);
3196 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3197 len += extra;
3199 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3200 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3201 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3202 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3203 len += sizeof(SLTG_OtherTypeInfo);
3204 ptr += len;
3207 pAfterOTIBlks = ptr;
3209 /* Skip this WORD and get the next DWORD */
3210 len = *(DWORD*)(pAfterOTIBlks + 2);
3212 /* Now add this to pLibBLk look at what we're pointing at and
3213 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3214 dust and we should be pointing at the beginning of the name
3215 table */
3217 pNameTable = (char*)pLibBlk + len;
3219 switch(*(WORD*)pNameTable) {
3220 case 0xffff:
3221 break;
3222 case 0x0200:
3223 pNameTable += 0x20;
3224 break;
3225 default:
3226 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3227 break;
3230 pNameTable += 0x216;
3232 pNameTable += 2;
3234 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3236 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3239 /* Hopefully we now have enough ptrs set up to actually read in
3240 some TypeInfos. It's not clear which order to do them in, so
3241 I'll just follow the links along the BlkEntry chain and read
3242 them in in the order in which they're in the file */
3244 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3246 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3247 pBlkEntry[order].next != 0;
3248 order = pBlkEntry[order].next - 1, i++) {
3250 SLTG_TypeInfoHeader *pTIHeader;
3251 SLTG_TypeInfoTail *pTITail;
3253 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3254 pOtherTypeInfoBlks[i].index_name)) {
3255 FIXME("Index strings don't match\n");
3256 return NULL;
3259 pTIHeader = pBlk;
3260 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3261 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3262 return NULL;
3264 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3265 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3266 (*ppTypeInfoImpl)->index = i;
3267 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3268 pOtherTypeInfoBlks[i].name_offs +
3269 pNameTable);
3270 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3271 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3272 sizeof(GUID));
3273 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3274 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3275 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3276 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3277 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3279 if((pTIHeader->typeflags1 & 7) != 2)
3280 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3281 if(pTIHeader->typeflags3 != 2)
3282 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3284 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3285 debugstr_w((*ppTypeInfoImpl)->Name),
3286 typekind_desc[pTIHeader->typekind],
3287 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3288 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3290 switch(pTIHeader->typekind) {
3291 case TKIND_ENUM:
3292 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3293 break;
3295 case TKIND_RECORD:
3296 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3297 break;
3299 case TKIND_INTERFACE:
3300 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3301 break;
3303 case TKIND_COCLASS:
3304 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3305 break;
3307 case TKIND_ALIAS:
3308 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3309 if (pTITail->tdescalias_vt)
3310 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3311 break;
3313 case TKIND_DISPATCH:
3314 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3315 break;
3317 default:
3318 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3319 pTITail = NULL;
3320 break;
3324 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3325 but we've already set those */
3326 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3327 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3328 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3330 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3331 X(06);
3332 X(08);
3333 X(0a);
3334 X(0c);
3335 X(0e);
3336 X(10);
3337 X(12);
3338 X(16);
3339 X(18);
3340 X(1a);
3341 X(1c);
3342 X(1e);
3343 X(24);
3344 X(26);
3345 X(2a);
3346 X(2c);
3347 X(2e);
3348 X(30);
3349 X(32);
3350 X(34);
3352 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3353 pBlk = (char*)pBlk + pBlkEntry[order].len;
3356 if(i != pTypeLibImpl->TypeInfoCount) {
3357 FIXME("Somehow processed %d TypeInfos\n", i);
3358 return NULL;
3361 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3362 return (ITypeLib2*)pTypeLibImpl;
3365 /* ITypeLib::QueryInterface
3367 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3368 ITypeLib2 * iface,
3369 REFIID riid,
3370 VOID **ppvObject)
3372 ICOM_THIS( ITypeLibImpl, iface);
3374 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3376 *ppvObject=NULL;
3377 if(IsEqualIID(riid, &IID_IUnknown) ||
3378 IsEqualIID(riid,&IID_ITypeLib)||
3379 IsEqualIID(riid,&IID_ITypeLib2))
3381 *ppvObject = This;
3384 if(*ppvObject)
3386 ITypeLib2_AddRef(iface);
3387 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3388 return S_OK;
3390 TRACE("-- Interface: E_NOINTERFACE\n");
3391 return E_NOINTERFACE;
3394 /* ITypeLib::AddRef
3396 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3398 ICOM_THIS( ITypeLibImpl, iface);
3400 TRACE("(%p)->ref was %u\n",This, This->ref);
3402 return ++(This->ref);
3405 /* ITypeLib::Release
3407 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3409 ICOM_THIS( ITypeLibImpl, iface);
3411 --(This->ref);
3413 TRACE("(%p)->(%u)\n",This, This->ref);
3415 if (!This->ref)
3417 /* remove cache entry */
3418 TRACE("removing from cache list\n");
3419 EnterCriticalSection(&cache_section);
3420 if (This->next) This->next->prev = This->prev;
3421 if (This->prev) This->prev->next = This->next;
3422 else tlb_cache_first = This->next;
3423 LeaveCriticalSection(&cache_section);
3425 /* FIXME destroy child objects */
3426 TRACE(" destroying ITypeLib(%p)\n",This);
3428 if (This->Name)
3430 SysFreeString(This->Name);
3431 This->Name = NULL;
3434 if (This->DocString)
3436 SysFreeString(This->DocString);
3437 This->DocString = NULL;
3440 if (This->HelpFile)
3442 SysFreeString(This->HelpFile);
3443 This->HelpFile = NULL;
3446 if (This->HelpStringDll)
3448 SysFreeString(This->HelpStringDll);
3449 This->HelpStringDll = NULL;
3452 if (This->pTypeInfo) /* can be NULL */
3453 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3454 HeapFree(GetProcessHeap(),0,This);
3455 return 0;
3458 return This->ref;
3461 /* ITypeLib::GetTypeInfoCount
3463 * Returns the number of type descriptions in the type library
3465 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3467 ICOM_THIS( ITypeLibImpl, iface);
3468 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3469 return This->TypeInfoCount;
3472 /* ITypeLib::GetTypeInfo
3474 * retrieves the specified type description in the library.
3476 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3477 ITypeLib2 *iface,
3478 UINT index,
3479 ITypeInfo **ppTInfo)
3481 int i;
3483 ICOM_THIS( ITypeLibImpl, iface);
3484 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3486 TRACE("(%p)->(index=%d) \n", This, index);
3488 if (!ppTInfo) return E_INVALIDARG;
3490 /* search element n in list */
3491 for(i=0; i < index; i++)
3493 pTypeInfo = pTypeInfo->next;
3494 if (!pTypeInfo)
3496 TRACE("-- element not found\n");
3497 return TYPE_E_ELEMENTNOTFOUND;
3501 *ppTInfo = (ITypeInfo *) pTypeInfo;
3503 ITypeInfo_AddRef(*ppTInfo);
3504 TRACE("-- found (%p)\n",*ppTInfo);
3505 return S_OK;
3509 /* ITypeLibs::GetTypeInfoType
3511 * Retrieves the type of a type description.
3513 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3514 ITypeLib2 *iface,
3515 UINT index,
3516 TYPEKIND *pTKind)
3518 ICOM_THIS( ITypeLibImpl, iface);
3519 int i;
3520 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3522 TRACE("(%p) index %d \n",This, index);
3524 if(!pTKind) return E_INVALIDARG;
3526 /* search element n in list */
3527 for(i=0; i < index; i++)
3529 if(!pTInfo)
3531 TRACE("-- element not found\n");
3532 return TYPE_E_ELEMENTNOTFOUND;
3534 pTInfo = pTInfo->next;
3537 *pTKind = pTInfo->TypeAttr.typekind;
3538 TRACE("-- found Type (%d)\n", *pTKind);
3539 return S_OK;
3542 /* ITypeLib::GetTypeInfoOfGuid
3544 * Retrieves the type description that corresponds to the specified GUID.
3547 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3548 ITypeLib2 *iface,
3549 REFGUID guid,
3550 ITypeInfo **ppTInfo)
3552 ICOM_THIS( ITypeLibImpl, iface);
3553 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3555 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3557 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3559 /* search linked list for guid */
3560 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3562 pTypeInfo = pTypeInfo->next;
3564 if (!pTypeInfo)
3566 /* end of list reached */
3567 TRACE("-- element not found\n");
3568 return TYPE_E_ELEMENTNOTFOUND;
3572 TRACE("-- found (%p, %s)\n",
3573 pTypeInfo,
3574 debugstr_w(pTypeInfo->Name));
3576 *ppTInfo = (ITypeInfo*)pTypeInfo;
3577 ITypeInfo_AddRef(*ppTInfo);
3578 return S_OK;
3581 /* ITypeLib::GetLibAttr
3583 * Retrieves the structure that contains the library's attributes.
3586 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3587 ITypeLib2 *iface,
3588 LPTLIBATTR *ppTLibAttr)
3590 ICOM_THIS( ITypeLibImpl, iface);
3591 TRACE("(%p)\n",This);
3592 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3593 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3594 return S_OK;
3597 /* ITypeLib::GetTypeComp
3599 * Enables a client compiler to bind to a library's types, variables,
3600 * constants, and global functions.
3603 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3604 ITypeLib2 *iface,
3605 ITypeComp **ppTComp)
3607 ICOM_THIS( ITypeLibImpl, iface);
3609 TRACE("(%p)->(%p)\n",This,ppTComp);
3610 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3611 ITypeComp_AddRef(*ppTComp);
3613 return S_OK;
3616 /* ITypeLib::GetDocumentation
3618 * Retrieves the library's documentation string, the complete Help file name
3619 * and path, and the context identifier for the library Help topic in the Help
3620 * file.
3622 * On a successful return all non-null BSTR pointers will have been set,
3623 * possibly to NULL.
3625 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3626 ITypeLib2 *iface,
3627 INT index,
3628 BSTR *pBstrName,
3629 BSTR *pBstrDocString,
3630 DWORD *pdwHelpContext,
3631 BSTR *pBstrHelpFile)
3633 ICOM_THIS( ITypeLibImpl, iface);
3635 HRESULT result = E_INVALIDARG;
3637 ITypeInfo *pTInfo;
3640 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3641 This, index,
3642 pBstrName, pBstrDocString,
3643 pdwHelpContext, pBstrHelpFile);
3645 if(index<0)
3647 /* documentation for the typelib */
3648 if(pBstrName)
3650 if (This->Name)
3651 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3652 else
3653 *pBstrName = NULL;
3655 if(pBstrDocString)
3657 if (This->DocString)
3658 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3659 else if (This->Name)
3660 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3661 else
3662 *pBstrDocString = NULL;
3664 if(pdwHelpContext)
3666 *pdwHelpContext = This->dwHelpContext;
3668 if(pBstrHelpFile)
3670 if (This->HelpFile)
3671 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3672 else
3673 *pBstrHelpFile = NULL;
3676 result = S_OK;
3678 else
3680 /* for a typeinfo */
3681 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3683 if(SUCCEEDED(result))
3685 result = ITypeInfo_GetDocumentation(pTInfo,
3686 MEMBERID_NIL,
3687 pBstrName,
3688 pBstrDocString,
3689 pdwHelpContext, pBstrHelpFile);
3691 ITypeInfo_Release(pTInfo);
3694 return result;
3695 memerr3:
3696 if (pBstrDocString) SysFreeString (*pBstrDocString);
3697 memerr2:
3698 if (pBstrName) SysFreeString (*pBstrName);
3699 memerr1:
3700 return STG_E_INSUFFICIENTMEMORY;
3703 /* ITypeLib::IsName
3705 * Indicates whether a passed-in string contains the name of a type or member
3706 * described in the library.
3709 static HRESULT WINAPI ITypeLib2_fnIsName(
3710 ITypeLib2 *iface,
3711 LPOLESTR szNameBuf,
3712 ULONG lHashVal,
3713 BOOL *pfName)
3715 ICOM_THIS( ITypeLibImpl, iface);
3716 ITypeInfoImpl *pTInfo;
3717 TLBFuncDesc *pFInfo;
3718 TLBVarDesc *pVInfo;
3719 int i;
3720 UINT nNameBufLen = SysStringLen(szNameBuf);
3722 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3723 pfName);
3725 *pfName=TRUE;
3726 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3727 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3728 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3729 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3730 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3731 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3732 goto ITypeLib2_fnIsName_exit;
3734 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3735 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3738 *pfName=FALSE;
3740 ITypeLib2_fnIsName_exit:
3741 TRACE("(%p)slow! search for %s: %s found!\n", This,
3742 debugstr_w(szNameBuf), *pfName?"NOT":"");
3744 return S_OK;
3747 /* ITypeLib::FindName
3749 * Finds occurrences of a type description in a type library. This may be used
3750 * to quickly verify that a name exists in a type library.
3753 static HRESULT WINAPI ITypeLib2_fnFindName(
3754 ITypeLib2 *iface,
3755 LPOLESTR szNameBuf,
3756 ULONG lHashVal,
3757 ITypeInfo **ppTInfo,
3758 MEMBERID *rgMemId,
3759 UINT16 *pcFound)
3761 ICOM_THIS( ITypeLibImpl, iface);
3762 ITypeInfoImpl *pTInfo;
3763 TLBFuncDesc *pFInfo;
3764 TLBVarDesc *pVInfo;
3765 int i,j = 0;
3767 UINT nNameBufLen = SysStringLen(szNameBuf);
3769 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3770 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3771 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3772 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3773 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3774 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3775 goto ITypeLib2_fnFindName_exit;
3777 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3778 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3779 continue;
3780 ITypeLib2_fnFindName_exit:
3781 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3782 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3783 j++;
3785 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3786 This, *pcFound, debugstr_w(szNameBuf), j);
3788 *pcFound=j;
3790 return S_OK;
3793 /* ITypeLib::ReleaseTLibAttr
3795 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3798 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3799 ITypeLib2 *iface,
3800 TLIBATTR *pTLibAttr)
3802 ICOM_THIS( ITypeLibImpl, iface);
3803 TRACE("freeing (%p)\n",This);
3804 HeapFree(GetProcessHeap(),0,pTLibAttr);
3808 /* ITypeLib2::GetCustData
3810 * gets the custom data
3812 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3813 ITypeLib2 * iface,
3814 REFGUID guid,
3815 VARIANT *pVarVal)
3817 ICOM_THIS( ITypeLibImpl, iface);
3818 TLBCustData *pCData;
3820 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3822 if( IsEqualIID(guid, &pCData->guid)) break;
3825 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3827 if(pCData)
3829 VariantInit( pVarVal);
3830 VariantCopy( pVarVal, &pCData->data);
3831 return S_OK;
3833 return E_INVALIDARG; /* FIXME: correct? */
3836 /* ITypeLib2::GetLibStatistics
3838 * Returns statistics about a type library that are required for efficient
3839 * sizing of hash tables.
3842 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3843 ITypeLib2 * iface,
3844 ULONG *pcUniqueNames,
3845 ULONG *pcchUniqueNames)
3847 ICOM_THIS( ITypeLibImpl, iface);
3849 FIXME("(%p): stub!\n", This);
3851 if(pcUniqueNames) *pcUniqueNames=1;
3852 if(pcchUniqueNames) *pcchUniqueNames=1;
3853 return S_OK;
3856 /* ITypeLib2::GetDocumentation2
3858 * Retrieves the library's documentation string, the complete Help file name
3859 * and path, the localization context to use, and the context ID for the
3860 * library Help topic in the Help file.
3863 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3864 ITypeLib2 * iface,
3865 INT index,
3866 LCID lcid,
3867 BSTR *pbstrHelpString,
3868 DWORD *pdwHelpStringContext,
3869 BSTR *pbstrHelpStringDll)
3871 ICOM_THIS( ITypeLibImpl, iface);
3872 HRESULT result;
3873 ITypeInfo *pTInfo;
3875 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3877 /* the help string should be obtained from the helpstringdll,
3878 * using the _DLLGetDocumentation function, based on the supplied
3879 * lcid. Nice to do sometime...
3881 if(index<0)
3883 /* documentation for the typelib */
3884 if(pbstrHelpString)
3885 *pbstrHelpString=SysAllocString(This->DocString);
3886 if(pdwHelpStringContext)
3887 *pdwHelpStringContext=This->dwHelpContext;
3888 if(pbstrHelpStringDll)
3889 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3891 result = S_OK;
3893 else
3895 /* for a typeinfo */
3896 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3898 if(SUCCEEDED(result))
3900 ITypeInfo2 * pTInfo2;
3901 result = ITypeInfo_QueryInterface(pTInfo,
3902 &IID_ITypeInfo2,
3903 (LPVOID*) &pTInfo2);
3905 if(SUCCEEDED(result))
3907 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3908 MEMBERID_NIL,
3909 lcid,
3910 pbstrHelpString,
3911 pdwHelpStringContext,
3912 pbstrHelpStringDll);
3914 ITypeInfo2_Release(pTInfo2);
3917 ITypeInfo_Release(pTInfo);
3920 return result;
3923 /* ITypeLib2::GetAllCustData
3925 * Gets all custom data items for the library.
3928 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3929 ITypeLib2 * iface,
3930 CUSTDATA *pCustData)
3932 ICOM_THIS( ITypeLibImpl, iface);
3933 TLBCustData *pCData;
3934 int i;
3935 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3936 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3937 if(pCustData->prgCustData ){
3938 pCustData->cCustData=This->ctCustData;
3939 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3940 pCustData->prgCustData[i].guid=pCData->guid;
3941 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3943 }else{
3944 ERR(" OUT OF MEMORY! \n");
3945 return E_OUTOFMEMORY;
3947 return S_OK;
3950 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3951 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3952 ITypeLib2_fnQueryInterface,
3953 ITypeLib2_fnAddRef,
3954 ITypeLib2_fnRelease,
3955 ITypeLib2_fnGetTypeInfoCount,
3956 ITypeLib2_fnGetTypeInfo,
3957 ITypeLib2_fnGetTypeInfoType,
3958 ITypeLib2_fnGetTypeInfoOfGuid,
3959 ITypeLib2_fnGetLibAttr,
3960 ITypeLib2_fnGetTypeComp,
3961 ITypeLib2_fnGetDocumentation,
3962 ITypeLib2_fnIsName,
3963 ITypeLib2_fnFindName,
3964 ITypeLib2_fnReleaseTLibAttr,
3966 ITypeLib2_fnGetCustData,
3967 ITypeLib2_fnGetLibStatistics,
3968 ITypeLib2_fnGetDocumentation2,
3969 ITypeLib2_fnGetAllCustData
3973 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
3975 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3977 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
3980 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
3982 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3984 return ITypeInfo_AddRef((ITypeInfo *)This);
3987 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
3989 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3991 return ITypeInfo_Release((ITypeInfo *)This);
3994 static HRESULT WINAPI ITypeLibComp_fnBind(
3995 ITypeComp * iface,
3996 OLECHAR * szName,
3997 unsigned long lHash,
3998 unsigned short wFlags,
3999 ITypeInfo ** ppTInfo,
4000 DESCKIND * pDescKind,
4001 BINDPTR * pBindPtr)
4003 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4004 return E_NOTIMPL;
4007 static HRESULT WINAPI ITypeLibComp_fnBindType(
4008 ITypeComp * iface,
4009 OLECHAR * szName,
4010 unsigned long lHash,
4011 ITypeInfo ** ppTInfo,
4012 ITypeComp ** ppTComp)
4014 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4015 return E_NOTIMPL;
4018 static ICOM_VTABLE(ITypeComp) tlbtcvt =
4020 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4022 ITypeLibComp_fnQueryInterface,
4023 ITypeLibComp_fnAddRef,
4024 ITypeLibComp_fnRelease,
4026 ITypeLibComp_fnBind,
4027 ITypeLibComp_fnBindType
4030 /*================== ITypeInfo(2) Methods ===================================*/
4031 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4033 ITypeInfoImpl * pTypeInfoImpl;
4035 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4036 if (pTypeInfoImpl)
4038 pTypeInfoImpl->lpVtbl = &tinfvt;
4039 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4040 pTypeInfoImpl->ref=1;
4042 TRACE("(%p)\n", pTypeInfoImpl);
4043 return (ITypeInfo2*) pTypeInfoImpl;
4046 /* ITypeInfo::QueryInterface
4048 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4049 ITypeInfo2 *iface,
4050 REFIID riid,
4051 VOID **ppvObject)
4053 ICOM_THIS( ITypeLibImpl, iface);
4055 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4057 *ppvObject=NULL;
4058 if(IsEqualIID(riid, &IID_IUnknown) ||
4059 IsEqualIID(riid,&IID_ITypeInfo)||
4060 IsEqualIID(riid,&IID_ITypeInfo2))
4061 *ppvObject = This;
4063 if(*ppvObject){
4064 ITypeInfo_AddRef(iface);
4065 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4066 return S_OK;
4068 TRACE("-- Interface: E_NOINTERFACE\n");
4069 return E_NOINTERFACE;
4072 /* ITypeInfo::AddRef
4074 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4076 ICOM_THIS( ITypeInfoImpl, iface);
4078 ++(This->ref);
4080 TRACE("(%p)->ref is %u\n",This, This->ref);
4081 return This->ref;
4084 /* ITypeInfo::Release
4086 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
4088 ICOM_THIS( ITypeInfoImpl, iface);
4090 --(This->ref);
4092 TRACE("(%p)->(%u)\n",This, This->ref);
4094 if (!This->ref)
4096 FIXME("destroy child objects\n");
4098 TRACE("destroying ITypeInfo(%p)\n",This);
4099 if (This->Name)
4101 SysFreeString(This->Name);
4102 This->Name = 0;
4105 if (This->DocString)
4107 SysFreeString(This->DocString);
4108 This->DocString = 0;
4111 if (This->next)
4113 ITypeInfo_Release((ITypeInfo*)This->next);
4116 HeapFree(GetProcessHeap(),0,This);
4117 return 0;
4119 return This->ref;
4122 /* ITypeInfo::GetTypeAttr
4124 * Retrieves a TYPEATTR structure that contains the attributes of the type
4125 * description.
4128 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4129 LPTYPEATTR *ppTypeAttr)
4131 ICOM_THIS( ITypeInfoImpl, iface);
4132 TRACE("(%p)\n",This);
4133 /* FIXME: must do a copy here */
4134 *ppTypeAttr=&This->TypeAttr;
4135 return S_OK;
4138 /* ITypeInfo::GetTypeComp
4140 * Retrieves the ITypeComp interface for the type description, which enables a
4141 * client compiler to bind to the type description's members.
4144 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4145 ITypeComp * *ppTComp)
4147 ICOM_THIS( ITypeInfoImpl, iface);
4149 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4151 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4152 ITypeComp_AddRef(*ppTComp);
4153 return S_OK;
4156 /* ITypeInfo::GetFuncDesc
4158 * Retrieves the FUNCDESC structure that contains information about a
4159 * specified function.
4162 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4163 LPFUNCDESC *ppFuncDesc)
4165 ICOM_THIS( ITypeInfoImpl, iface);
4166 int i;
4167 TLBFuncDesc * pFDesc;
4168 TRACE("(%p) index %d\n", This, index);
4169 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4171 if(pFDesc){
4172 /* FIXME: must do a copy here */
4173 *ppFuncDesc=&pFDesc->funcdesc;
4174 return S_OK;
4176 return E_INVALIDARG;
4179 /* ITypeInfo::GetVarDesc
4181 * Retrieves a VARDESC structure that describes the specified variable.
4184 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4185 LPVARDESC *ppVarDesc)
4187 ICOM_THIS( ITypeInfoImpl, iface);
4188 int i;
4189 TLBVarDesc * pVDesc;
4190 TRACE("(%p) index %d\n", This, index);
4191 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4193 if(pVDesc){
4194 /* FIXME: must do a copy here */
4195 *ppVarDesc=&pVDesc->vardesc;
4196 return S_OK;
4198 return E_INVALIDARG;
4201 /* ITypeInfo_GetNames
4203 * Retrieves the variable with the specified member ID (or the name of the
4204 * property or method and its parameters) that correspond to the specified
4205 * function ID.
4207 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4208 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4210 ICOM_THIS( ITypeInfoImpl, iface);
4211 TLBFuncDesc * pFDesc;
4212 TLBVarDesc * pVDesc;
4213 int i;
4214 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4215 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4216 if(pFDesc)
4218 /* function found, now return function and parameter names */
4219 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4221 if(!i)
4222 *rgBstrNames=SysAllocString(pFDesc->Name);
4223 else
4224 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4226 *pcNames=i;
4228 else
4230 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4231 if(pVDesc)
4233 *rgBstrNames=SysAllocString(pVDesc->Name);
4234 *pcNames=1;
4236 else
4238 if(This->TypeAttr.cImplTypes &&
4239 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4240 /* recursive search */
4241 ITypeInfo *pTInfo;
4242 HRESULT result;
4243 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4244 &pTInfo);
4245 if(SUCCEEDED(result))
4247 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4248 ITypeInfo_Release(pTInfo);
4249 return result;
4251 WARN("Could not search inherited interface!\n");
4253 else
4255 WARN("no names found\n");
4257 *pcNames=0;
4258 return TYPE_E_ELEMENTNOTFOUND;
4261 return S_OK;
4265 /* ITypeInfo::GetRefTypeOfImplType
4267 * If a type description describes a COM class, it retrieves the type
4268 * description of the implemented interface types. For an interface,
4269 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4270 * if any exist.
4273 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4274 ITypeInfo2 *iface,
4275 UINT index,
4276 HREFTYPE *pRefType)
4278 ICOM_THIS( ITypeInfoImpl, iface);
4279 int(i);
4280 TLBImplType *pImpl = This->impltypelist;
4282 TRACE("(%p) index %d\n", This, index);
4283 if (TRACE_ON(ole)) dump_TypeInfo(This);
4285 if(index==(UINT)-1)
4287 /* only valid on dual interfaces;
4288 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4290 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4292 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4293 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4295 *pRefType = -1;
4297 else
4299 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4300 *pRefType = pImpl->hRef;
4303 else
4305 /* get element n from linked list */
4306 for(i=0; pImpl && i<index; i++)
4308 pImpl = pImpl->next;
4311 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4313 *pRefType = pImpl->hRef;
4315 TRACE("-- 0x%08lx\n", pImpl->hRef );
4318 return S_OK;
4322 /* ITypeInfo::GetImplTypeFlags
4324 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4325 * or base interface in a type description.
4327 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4328 UINT index, INT *pImplTypeFlags)
4330 ICOM_THIS( ITypeInfoImpl, iface);
4331 int i;
4332 TLBImplType *pImpl;
4334 TRACE("(%p) index %d\n", This, index);
4335 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4336 i++, pImpl=pImpl->next)
4338 if(i==index && pImpl){
4339 *pImplTypeFlags=pImpl->implflags;
4340 return S_OK;
4342 *pImplTypeFlags=0;
4343 return TYPE_E_ELEMENTNOTFOUND;
4346 /* GetIDsOfNames
4347 * Maps between member names and member IDs, and parameter names and
4348 * parameter IDs.
4350 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4351 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4353 ICOM_THIS( ITypeInfoImpl, iface);
4354 TLBFuncDesc * pFDesc;
4355 TLBVarDesc * pVDesc;
4356 HRESULT ret=S_OK;
4358 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4359 cNames);
4360 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4361 int i, j;
4362 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4363 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4364 for(i=1; i < cNames; i++){
4365 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4366 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4367 break;
4368 if( j<pFDesc->funcdesc.cParams)
4369 pMemId[i]=j;
4370 else
4371 ret=DISP_E_UNKNOWNNAME;
4373 return ret;
4376 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4377 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4378 if(cNames) *pMemId=pVDesc->vardesc.memid;
4379 return ret;
4382 /* not found, see if this is and interface with an inheritance */
4383 if(This->TypeAttr.cImplTypes &&
4384 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4385 /* recursive search */
4386 ITypeInfo *pTInfo;
4387 ret=ITypeInfo_GetRefTypeInfo(iface,
4388 This->impltypelist->hRef, &pTInfo);
4389 if(SUCCEEDED(ret)){
4390 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4391 ITypeInfo_Release(pTInfo);
4392 return ret;
4394 WARN("Could not search inherited interface!\n");
4395 } else
4396 WARN("no names found\n");
4397 return DISP_E_UNKNOWNNAME;
4400 /* ITypeInfo::Invoke
4402 * Invokes a method, or accesses a property of an object, that implements the
4403 * interface described by the type description.
4405 DWORD
4406 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4407 DWORD res;
4409 if (TRACE_ON(ole)) {
4410 int i;
4411 TRACE("Calling %p(",func);
4412 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4413 TRACE(")\n");
4416 switch (callconv) {
4417 case CC_STDCALL:
4419 switch (nrargs) {
4420 case 0:
4421 res = func();
4422 break;
4423 case 1:
4424 res = func(args[0]);
4425 break;
4426 case 2:
4427 res = func(args[0],args[1]);
4428 break;
4429 case 3:
4430 res = func(args[0],args[1],args[2]);
4431 break;
4432 case 4:
4433 res = func(args[0],args[1],args[2],args[3]);
4434 break;
4435 case 5:
4436 res = func(args[0],args[1],args[2],args[3],args[4]);
4437 break;
4438 case 6:
4439 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4440 break;
4441 case 7:
4442 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4443 break;
4444 case 8:
4445 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4446 break;
4447 case 9:
4448 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4449 break;
4450 default:
4451 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4452 res = -1;
4453 break;
4455 break;
4456 default:
4457 FIXME("unsupported calling convention %d\n",callconv);
4458 res = -1;
4459 break;
4461 TRACE("returns %08lx\n",res);
4462 return res;
4465 extern int const _argsize(DWORD vt);
4467 /****************************************************************************
4468 * Helper functions for Dispcall / Invoke, which copies one variant
4469 * with target type onto the argument stack.
4471 static HRESULT
4472 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4473 DWORD *argpos, VARIANT *arg, VARTYPE vt
4475 UINT arglen = _argsize(vt)*sizeof(DWORD);
4476 VARTYPE oldvt;
4477 VARIANT va;
4479 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4480 memcpy(argpos,&arg,sizeof(void*));
4481 return S_OK;
4484 if (V_VT(arg) == vt) {
4485 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4486 return S_OK;
4489 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4490 memcpy(argpos, &V_UNION(arg,parray), sizeof(SAFEARRAY*));
4491 return S_OK;
4494 if (vt == VT_VARIANT) {
4495 memcpy(argpos, arg, arglen);
4496 return S_OK;
4498 /* Deref BYREF vars if there is need */
4499 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4500 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4501 return S_OK;
4503 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4504 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4505 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4506 return S_OK;
4508 if ((vt == VT_PTR) && tdesc)
4509 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4511 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4512 ITypeInfo *tinfo2;
4513 TYPEATTR *tattr;
4514 HRESULT hres;
4516 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4517 if (hres) {
4518 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing from vt 0x%x. Copying 4 byte.\n",tdesc->u.hreftype,V_VT(arg));
4519 memcpy(argpos, &V_UNION(arg,lVal), 4);
4520 return S_OK;
4522 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4523 switch (tattr->typekind) {
4524 case TKIND_ENUM:
4525 switch ( V_VT( arg ) ) {
4526 case VT_I2:
4527 *argpos = V_UNION(arg,iVal);
4528 return S_OK;
4529 case VT_I4:
4530 memcpy(argpos, &V_UNION(arg,lVal), 4);
4531 return S_OK;
4532 default:
4533 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4534 break;
4537 case TKIND_ALIAS:
4538 tdesc = &(tattr->tdescAlias);
4539 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4540 ITypeInfo_Release(tinfo2);
4541 return hres;
4543 case TKIND_INTERFACE:
4544 if (V_VT(arg) == VT_DISPATCH) {
4545 IDispatch *disp;
4546 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4547 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4548 return S_OK;
4550 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),&IID_IDispatch,(LPVOID*)&disp);
4551 if (SUCCEEDED(hres)) {
4552 memcpy(argpos,&disp,4);
4553 IUnknown_Release(V_UNION(arg,pdispVal));
4554 return S_OK;
4556 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4557 return E_FAIL;
4559 if (V_VT(arg) == VT_UNKNOWN) {
4560 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4561 return S_OK;
4563 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg),debugstr_guid(&(tattr->guid)));
4564 break;
4565 case TKIND_DISPATCH:
4566 if (V_VT(arg) == VT_DISPATCH) {
4567 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4568 return S_OK;
4570 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4571 break;
4572 case TKIND_RECORD:
4573 FIXME("TKIND_RECORD unhandled.\n");
4574 break;
4575 default:
4576 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4577 break;
4579 return E_FAIL;
4582 oldvt = V_VT(arg);
4583 VariantInit(&va);
4584 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4585 memcpy(argpos,&V_UNION(&va,lVal), arglen);
4586 FIXME("Should not use VariantChangeType here. (conversion from 0x%x -> 0x%x)\n",
4587 V_VT(arg), vt
4589 return S_OK;
4591 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4592 return E_FAIL;
4595 /***********************************************************************
4596 * DispCallFunc (OLEAUT32.@)
4598 HRESULT WINAPI
4599 DispCallFunc(
4600 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4601 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4603 int i, argsize, argspos;
4604 DWORD *args;
4605 HRESULT hres;
4607 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4608 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4610 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4611 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4612 argsize = 1;
4613 for (i=0;i<cActuals;i++) {
4614 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4615 dump_Variant(prgpvarg[i]);
4616 argsize += _argsize(prgvt[i]);
4618 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4619 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4620 argspos = 1;
4621 for (i=0;i<cActuals;i++) {
4622 VARIANT *arg = prgpvarg[i];
4623 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4624 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4625 argspos += _argsize(prgvt[i]);
4628 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4630 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4631 hres=S_OK;
4633 else
4635 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4636 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4637 FIXME("Method returned %lx\n",hres);
4639 HeapFree(GetProcessHeap(),0,args);
4640 return hres;
4643 static HRESULT WINAPI ITypeInfo_fnInvoke(
4644 ITypeInfo2 *iface,
4645 VOID *pIUnk,
4646 MEMBERID memid,
4647 UINT16 dwFlags,
4648 DISPPARAMS *pDispParams,
4649 VARIANT *pVarResult,
4650 EXCEPINFO *pExcepInfo,
4651 UINT *pArgErr)
4653 ICOM_THIS( ITypeInfoImpl, iface);
4654 TLBFuncDesc * pFDesc;
4655 TLBVarDesc * pVDesc;
4656 int i;
4657 HRESULT hres;
4659 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4660 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4662 dump_DispParms(pDispParams);
4664 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4665 if (pFDesc->funcdesc.memid == memid) {
4666 if (pFDesc->funcdesc.invkind & dwFlags)
4667 break;
4670 if (pFDesc) {
4671 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4672 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4673 switch (pFDesc->funcdesc.funckind) {
4674 case FUNC_PUREVIRTUAL:
4675 case FUNC_VIRTUAL: {
4676 DWORD res;
4677 int numargs, numargs2, argspos, args2pos;
4678 DWORD *args , *args2;
4681 numargs = 1; numargs2 = 0;
4682 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4683 if (i<pDispParams->cArgs)
4684 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4685 else {
4686 numargs += 1; /* sizeof(lpvoid) */
4687 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4691 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4692 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4694 args[0] = (DWORD)pIUnk;
4695 argspos = 1; args2pos = 0;
4696 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4697 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4698 if (i<pDispParams->cArgs) {
4699 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4700 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4701 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4702 if (FAILED(hres)) return hres;
4703 argspos += arglen;
4704 } else {
4705 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4706 if (tdesc->vt != VT_PTR)
4707 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4708 /*FIXME: give pointers for the rest, so propertyget works*/
4709 args[argspos] = (DWORD)&args2[args2pos];
4711 /* If pointer to variant, pass reference it. */
4712 if ((tdesc->vt == VT_PTR) &&
4713 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4714 pVarResult
4716 args[argspos]= (DWORD)pVarResult;
4717 argspos += 1;
4718 args2pos += arglen;
4721 if (pFDesc->funcdesc.cParamsOpt)
4722 FIXME("Does not support optional parameters (%d)\n",
4723 pFDesc->funcdesc.cParamsOpt
4726 res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4],
4727 pFDesc->funcdesc.callconv,
4728 numargs,
4729 args
4731 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4732 args2pos = 0;
4733 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4734 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4735 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4736 TYPEDESC i4_tdesc;
4737 i4_tdesc.vt = VT_I4;
4739 /* If we are a pointer to a variant, we are done already */
4740 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4741 continue;
4743 VariantInit(pVarResult);
4744 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4746 if (tdesc->vt == VT_PTR)
4747 tdesc = tdesc->u.lptdesc;
4748 if (tdesc->vt == VT_USERDEFINED) {
4749 ITypeInfo *tinfo2;
4750 TYPEATTR *tattr;
4752 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4753 if (hres) {
4754 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4755 return E_FAIL;
4757 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4758 switch (tattr->typekind) {
4759 case TKIND_ENUM:
4760 /* force the return type to be VT_I4 */
4761 tdesc = &i4_tdesc;
4762 break;
4763 case TKIND_ALIAS:
4764 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4765 tdesc = &(tattr->tdescAlias);
4766 break;
4768 case TKIND_INTERFACE:
4769 FIXME("TKIND_INTERFACE unhandled.\n");
4770 break;
4771 case TKIND_DISPATCH:
4772 FIXME("TKIND_DISPATCH unhandled.\n");
4773 break;
4774 case TKIND_RECORD:
4775 FIXME("TKIND_RECORD unhandled.\n");
4776 break;
4777 default:
4778 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4779 break;
4781 ITypeInfo_Release(tinfo2);
4783 V_VT(pVarResult) = tdesc->vt;
4785 /* HACK: VB5 likes this.
4786 * I do not know why. There is 1 example in MSDN which uses
4787 * this which appears broken (mixes int vals and
4788 * IDispatch*.).
4790 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4791 V_VT(pVarResult) = VT_DISPATCH;
4792 TRACE("storing into variant:\n");
4793 dump_Variant(pVarResult);
4794 args2pos += arglen;
4797 HeapFree(GetProcessHeap(),0,args2);
4798 HeapFree(GetProcessHeap(),0,args);
4799 return S_OK;
4801 case FUNC_DISPATCH: {
4802 IDispatch *disp;
4803 HRESULT hr;
4805 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4806 if (hr) {
4807 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4808 return hr;
4810 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4811 hr = IDispatch_Invoke(
4812 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4813 pVarResult,pExcepInfo,pArgErr
4815 if (hr)
4816 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4817 IDispatch_Release(disp);
4818 return hr;
4820 default:
4821 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4822 return E_FAIL;
4824 } else {
4825 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4826 if (pVDesc->vardesc.memid == memid) {
4827 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4828 dump_TLBVarDesc(pVDesc);
4829 break;
4833 /* not found, look for it in inherited interfaces */
4834 if (This->TypeAttr.cImplTypes &&
4835 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4836 /* recursive search */
4837 ITypeInfo *pTInfo;
4838 HRESULT hr;
4839 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4840 if(SUCCEEDED(hr)){
4841 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4842 ITypeInfo_Release(pTInfo);
4843 return hr;
4845 WARN("Could not search inherited interface!\n");
4847 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4848 return DISP_E_MEMBERNOTFOUND;
4851 /* ITypeInfo::GetDocumentation
4853 * Retrieves the documentation string, the complete Help file name and path,
4854 * and the context ID for the Help topic for a specified type description.
4856 * (Can be tested by the Visual Basic Editor in Word for instance.)
4858 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4859 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4860 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4862 ICOM_THIS( ITypeInfoImpl, iface);
4863 TLBFuncDesc * pFDesc;
4864 TLBVarDesc * pVDesc;
4865 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4866 " HelpContext(%p) HelpFile(%p)\n",
4867 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4868 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4869 if(pBstrName)
4870 *pBstrName=SysAllocString(This->Name);
4871 if(pBstrDocString)
4872 *pBstrDocString=SysAllocString(This->DocString);
4873 if(pdwHelpContext)
4874 *pdwHelpContext=This->dwHelpContext;
4875 if(pBstrHelpFile)
4876 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4877 return S_OK;
4878 }else {/* for a member */
4879 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4880 if(pFDesc->funcdesc.memid==memid){
4881 if(pBstrName)
4882 *pBstrName = SysAllocString(pFDesc->Name);
4883 if(pBstrDocString)
4884 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4885 if(pdwHelpContext)
4886 *pdwHelpContext=pFDesc->helpcontext;
4887 return S_OK;
4889 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4890 if(pVDesc->vardesc.memid==memid){
4891 if(pBstrName)
4892 *pBstrName = SysAllocString(pVDesc->Name);
4893 if(pBstrDocString)
4894 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4895 if(pdwHelpContext)
4896 *pdwHelpContext=pVDesc->HelpContext;
4897 return S_OK;
4900 return TYPE_E_ELEMENTNOTFOUND;
4903 /* ITypeInfo::GetDllEntry
4905 * Retrieves a description or specification of an entry point for a function
4906 * in a DLL.
4908 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4909 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4910 WORD *pwOrdinal)
4912 ICOM_THIS( ITypeInfoImpl, iface);
4913 TLBFuncDesc *pFDesc;
4915 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4917 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4918 if(pFDesc->funcdesc.memid==memid){
4919 dump_TypeInfo(This);
4920 dump_TLBFuncDescOne(pFDesc);
4922 /* FIXME: This is wrong, but how do you find that out? */
4923 if (pBstrDllName) {
4924 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4925 *pBstrDllName = SysAllocString(oleaut32W);
4928 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4929 if (pBstrName)
4930 *pBstrName = SysAllocString(pFDesc->Entry);
4931 if (pwOrdinal)
4932 *pwOrdinal = -1;
4933 return S_OK;
4935 if (pBstrName)
4936 *pBstrName = NULL;
4937 if (pwOrdinal)
4938 *pwOrdinal = (DWORD)pFDesc->Entry;
4939 return S_OK;
4941 return E_FAIL;
4944 /* ITypeInfo::GetRefTypeInfo
4946 * If a type description references other type descriptions, it retrieves
4947 * the referenced type descriptions.
4949 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4950 ITypeInfo2 *iface,
4951 HREFTYPE hRefType,
4952 ITypeInfo **ppTInfo)
4954 ICOM_THIS( ITypeInfoImpl, iface);
4955 HRESULT result = E_FAIL;
4958 if (hRefType == -1 &&
4959 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4960 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4962 /* when we meet a DUAL dispinterface, we must create the interface
4963 * version of it.
4965 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4968 /* the interface version contains the same information as the dispinterface
4969 * copy the contents of the structs.
4971 *pTypeInfoImpl = *This;
4972 pTypeInfoImpl->ref = 1;
4974 /* change the type to interface */
4975 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4977 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4979 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4981 result = S_OK;
4983 } else {
4984 TLBRefType *pRefType;
4985 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4986 if(pRefType->reference == hRefType)
4987 break;
4989 if(!pRefType)
4990 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4991 if(pRefType && hRefType != -1) {
4992 ITypeLib *pTLib = NULL;
4994 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4995 int Index;
4996 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4997 } else {
4998 if(pRefType->pImpTLInfo->pImpTypeLib) {
4999 TRACE("typeinfo in imported typelib that is already loaded\n");
5000 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5001 ITypeLib2_AddRef((ITypeLib*) pTLib);
5002 result = S_OK;
5003 } else {
5004 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5005 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5006 pRefType->pImpTLInfo->wVersionMajor,
5007 pRefType->pImpTLInfo->wVersionMinor,
5008 pRefType->pImpTLInfo->lcid,
5009 &pTLib);
5011 if(!SUCCEEDED(result)) {
5012 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5013 result=LoadTypeLib(libnam, &pTLib);
5014 SysFreeString(libnam);
5016 if(SUCCEEDED(result)) {
5017 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5018 ITypeLib2_AddRef(pTLib);
5022 if(SUCCEEDED(result)) {
5023 if(pRefType->index == TLB_REF_USE_GUID)
5024 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5025 &pRefType->guid,
5026 ppTInfo);
5027 else
5028 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5029 ppTInfo);
5031 if (pTLib != NULL)
5032 ITypeLib2_Release(pTLib);
5036 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5037 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5038 return result;
5041 /* ITypeInfo::AddressOfMember
5043 * Retrieves the addresses of static functions or variables, such as those
5044 * defined in a DLL.
5046 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5047 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5049 ICOM_THIS( ITypeInfoImpl, iface);
5050 FIXME("(%p) stub!\n", This);
5051 return S_OK;
5054 /* ITypeInfo::CreateInstance
5056 * Creates a new instance of a type that describes a component object class
5057 * (coclass).
5059 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5060 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5062 ICOM_THIS( ITypeInfoImpl, iface);
5063 FIXME("(%p) stub!\n", This);
5064 return S_OK;
5067 /* ITypeInfo::GetMops
5069 * Retrieves marshalling information.
5071 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5072 BSTR *pBstrMops)
5074 ICOM_THIS( ITypeInfoImpl, iface);
5075 FIXME("(%p) stub!\n", This);
5076 return S_OK;
5079 /* ITypeInfo::GetContainingTypeLib
5081 * Retrieves the containing type library and the index of the type description
5082 * within that type library.
5084 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5085 ITypeLib * *ppTLib, UINT *pIndex)
5087 ICOM_THIS( ITypeInfoImpl, iface);
5089 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5090 if (pIndex) {
5091 *pIndex=This->index;
5092 TRACE("returning pIndex=%d\n", *pIndex);
5095 if (ppTLib) {
5096 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5097 ITypeLib2_AddRef(*ppTLib);
5098 TRACE("returning ppTLib=%p\n", *ppTLib);
5101 return S_OK;
5104 /* ITypeInfo::ReleaseTypeAttr
5106 * Releases a TYPEATTR previously returned by GetTypeAttr.
5109 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5110 TYPEATTR* pTypeAttr)
5112 ICOM_THIS( ITypeInfoImpl, iface);
5113 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5116 /* ITypeInfo::ReleaseFuncDesc
5118 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5120 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5121 ITypeInfo2 *iface,
5122 FUNCDESC *pFuncDesc)
5124 ICOM_THIS( ITypeInfoImpl, iface);
5125 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5128 /* ITypeInfo::ReleaseVarDesc
5130 * Releases a VARDESC previously returned by GetVarDesc.
5132 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5133 VARDESC *pVarDesc)
5135 ICOM_THIS( ITypeInfoImpl, iface);
5136 TRACE("(%p)->(%p)\n", This, pVarDesc);
5139 /* ITypeInfo2::GetTypeKind
5141 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5144 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5145 TYPEKIND *pTypeKind)
5147 ICOM_THIS( ITypeInfoImpl, iface);
5148 *pTypeKind=This->TypeAttr.typekind;
5149 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5150 return S_OK;
5153 /* ITypeInfo2::GetTypeFlags
5155 * Returns the type flags without any allocations. This returns a DWORD type
5156 * flag, which expands the type flags without growing the TYPEATTR (type
5157 * attribute).
5160 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5162 ICOM_THIS( ITypeInfoImpl, iface);
5163 *pTypeFlags=This->TypeAttr.wTypeFlags;
5164 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5165 return S_OK;
5168 /* ITypeInfo2::GetFuncIndexOfMemId
5169 * Binds to a specific member based on a known DISPID, where the member name
5170 * is not known (for example, when binding to a default member).
5173 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5174 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5176 ICOM_THIS( ITypeInfoImpl, iface);
5177 TLBFuncDesc *pFuncInfo;
5178 int i;
5179 HRESULT result;
5180 /* FIXME: should check for invKind??? */
5181 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
5182 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
5183 if(pFuncInfo){
5184 *pFuncIndex=i;
5185 result= S_OK;
5186 }else{
5187 *pFuncIndex=0;
5188 result=E_INVALIDARG;
5190 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5191 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
5192 return result;
5195 /* TypeInfo2::GetVarIndexOfMemId
5197 * Binds to a specific member based on a known DISPID, where the member name
5198 * is not known (for example, when binding to a default member).
5201 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5202 MEMBERID memid, UINT *pVarIndex)
5204 ICOM_THIS( ITypeInfoImpl, iface);
5205 TLBVarDesc *pVarInfo;
5206 int i;
5207 HRESULT result;
5208 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5209 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5211 if(pVarInfo){
5212 *pVarIndex=i;
5213 result= S_OK;
5214 }else{
5215 *pVarIndex=0;
5216 result=E_INVALIDARG;
5218 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5219 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
5220 return result;
5223 /* ITypeInfo2::GetCustData
5225 * Gets the custom data
5227 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5228 ITypeInfo2 * iface,
5229 REFGUID guid,
5230 VARIANT *pVarVal)
5232 ICOM_THIS( ITypeInfoImpl, iface);
5233 TLBCustData *pCData;
5235 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5236 if( IsEqualIID(guid, &pCData->guid)) break;
5238 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5240 if(pCData)
5242 VariantInit( pVarVal);
5243 VariantCopy( pVarVal, &pCData->data);
5244 return S_OK;
5246 return E_INVALIDARG; /* FIXME: correct? */
5249 /* ITypeInfo2::GetFuncCustData
5251 * Gets the custom data
5253 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5254 ITypeInfo2 * iface,
5255 UINT index,
5256 REFGUID guid,
5257 VARIANT *pVarVal)
5259 ICOM_THIS( ITypeInfoImpl, iface);
5260 TLBCustData *pCData=NULL;
5261 TLBFuncDesc * pFDesc;
5262 int i;
5263 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5264 pFDesc=pFDesc->next);
5266 if(pFDesc)
5267 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5268 if( IsEqualIID(guid, &pCData->guid)) break;
5270 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5272 if(pCData){
5273 VariantInit( pVarVal);
5274 VariantCopy( pVarVal, &pCData->data);
5275 return S_OK;
5277 return E_INVALIDARG; /* FIXME: correct? */
5280 /* ITypeInfo2::GetParamCustData
5282 * Gets the custom data
5284 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5285 ITypeInfo2 * iface,
5286 UINT indexFunc,
5287 UINT indexParam,
5288 REFGUID guid,
5289 VARIANT *pVarVal)
5291 ICOM_THIS( ITypeInfoImpl, iface);
5292 TLBCustData *pCData=NULL;
5293 TLBFuncDesc * pFDesc;
5294 int i;
5296 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5298 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5299 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5300 pCData = pCData->next)
5301 if( IsEqualIID(guid, &pCData->guid)) break;
5303 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5305 if(pCData)
5307 VariantInit( pVarVal);
5308 VariantCopy( pVarVal, &pCData->data);
5309 return S_OK;
5311 return E_INVALIDARG; /* FIXME: correct? */
5314 /* ITypeInfo2::GetVarCustData
5316 * Gets the custom data
5318 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5319 ITypeInfo2 * iface,
5320 UINT index,
5321 REFGUID guid,
5322 VARIANT *pVarVal)
5324 ICOM_THIS( ITypeInfoImpl, iface);
5325 TLBCustData *pCData=NULL;
5326 TLBVarDesc * pVDesc;
5327 int i;
5329 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5331 if(pVDesc)
5333 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5335 if( IsEqualIID(guid, &pCData->guid)) break;
5339 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5341 if(pCData)
5343 VariantInit( pVarVal);
5344 VariantCopy( pVarVal, &pCData->data);
5345 return S_OK;
5347 return E_INVALIDARG; /* FIXME: correct? */
5350 /* ITypeInfo2::GetImplCustData
5352 * Gets the custom data
5354 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5355 ITypeInfo2 * iface,
5356 UINT index,
5357 REFGUID guid,
5358 VARIANT *pVarVal)
5360 ICOM_THIS( ITypeInfoImpl, iface);
5361 TLBCustData *pCData=NULL;
5362 TLBImplType * pRDesc;
5363 int i;
5365 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5367 if(pRDesc)
5369 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5371 if( IsEqualIID(guid, &pCData->guid)) break;
5375 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5377 if(pCData)
5379 VariantInit( pVarVal);
5380 VariantCopy( pVarVal, &pCData->data);
5381 return S_OK;
5383 return E_INVALIDARG; /* FIXME: correct? */
5386 /* ITypeInfo2::GetDocumentation2
5388 * Retrieves the documentation string, the complete Help file name and path,
5389 * the localization context to use, and the context ID for the library Help
5390 * topic in the Help file.
5393 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5394 ITypeInfo2 * iface,
5395 MEMBERID memid,
5396 LCID lcid,
5397 BSTR *pbstrHelpString,
5398 DWORD *pdwHelpStringContext,
5399 BSTR *pbstrHelpStringDll)
5401 ICOM_THIS( ITypeInfoImpl, iface);
5402 TLBFuncDesc * pFDesc;
5403 TLBVarDesc * pVDesc;
5404 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5405 "HelpStringContext(%p) HelpStringDll(%p)\n",
5406 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5407 pbstrHelpStringDll );
5408 /* the help string should be obtained from the helpstringdll,
5409 * using the _DLLGetDocumentation function, based on the supplied
5410 * lcid. Nice to do sometime...
5412 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5413 if(pbstrHelpString)
5414 *pbstrHelpString=SysAllocString(This->Name);
5415 if(pdwHelpStringContext)
5416 *pdwHelpStringContext=This->dwHelpStringContext;
5417 if(pbstrHelpStringDll)
5418 *pbstrHelpStringDll=
5419 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5420 return S_OK;
5421 }else {/* for a member */
5422 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5423 if(pFDesc->funcdesc.memid==memid){
5424 if(pbstrHelpString)
5425 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5426 if(pdwHelpStringContext)
5427 *pdwHelpStringContext=pFDesc->HelpStringContext;
5428 if(pbstrHelpStringDll)
5429 *pbstrHelpStringDll=
5430 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5431 return S_OK;
5433 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5434 if(pVDesc->vardesc.memid==memid){
5435 if(pbstrHelpString)
5436 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5437 if(pdwHelpStringContext)
5438 *pdwHelpStringContext=pVDesc->HelpStringContext;
5439 if(pbstrHelpStringDll)
5440 *pbstrHelpStringDll=
5441 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5442 return S_OK;
5445 return TYPE_E_ELEMENTNOTFOUND;
5448 /* ITypeInfo2::GetAllCustData
5450 * Gets all custom data items for the Type info.
5453 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5454 ITypeInfo2 * iface,
5455 CUSTDATA *pCustData)
5457 ICOM_THIS( ITypeInfoImpl, iface);
5458 TLBCustData *pCData;
5459 int i;
5461 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5463 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5464 if(pCustData->prgCustData ){
5465 pCustData->cCustData=This->ctCustData;
5466 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5467 pCustData->prgCustData[i].guid=pCData->guid;
5468 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5470 }else{
5471 ERR(" OUT OF MEMORY! \n");
5472 return E_OUTOFMEMORY;
5474 return S_OK;
5477 /* ITypeInfo2::GetAllFuncCustData
5479 * Gets all custom data items for the specified Function
5482 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5483 ITypeInfo2 * iface,
5484 UINT index,
5485 CUSTDATA *pCustData)
5487 ICOM_THIS( ITypeInfoImpl, iface);
5488 TLBCustData *pCData;
5489 TLBFuncDesc * pFDesc;
5490 int i;
5491 TRACE("(%p) index %d\n", This, index);
5492 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5493 pFDesc=pFDesc->next)
5495 if(pFDesc){
5496 pCustData->prgCustData =
5497 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5498 if(pCustData->prgCustData ){
5499 pCustData->cCustData=pFDesc->ctCustData;
5500 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5501 pCData = pCData->next){
5502 pCustData->prgCustData[i].guid=pCData->guid;
5503 VariantCopy(& pCustData->prgCustData[i].varValue,
5504 & pCData->data);
5506 }else{
5507 ERR(" OUT OF MEMORY! \n");
5508 return E_OUTOFMEMORY;
5510 return S_OK;
5512 return TYPE_E_ELEMENTNOTFOUND;
5515 /* ITypeInfo2::GetAllParamCustData
5517 * Gets all custom data items for the Functions
5520 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5521 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5523 ICOM_THIS( ITypeInfoImpl, iface);
5524 TLBCustData *pCData=NULL;
5525 TLBFuncDesc * pFDesc;
5526 int i;
5527 TRACE("(%p) index %d\n", This, indexFunc);
5528 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5529 pFDesc=pFDesc->next)
5531 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5532 pCustData->prgCustData =
5533 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5534 sizeof(CUSTDATAITEM));
5535 if(pCustData->prgCustData ){
5536 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5537 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5538 pCData; i++, pCData = pCData->next){
5539 pCustData->prgCustData[i].guid=pCData->guid;
5540 VariantCopy(& pCustData->prgCustData[i].varValue,
5541 & pCData->data);
5543 }else{
5544 ERR(" OUT OF MEMORY! \n");
5545 return E_OUTOFMEMORY;
5547 return S_OK;
5549 return TYPE_E_ELEMENTNOTFOUND;
5552 /* ITypeInfo2::GetAllVarCustData
5554 * Gets all custom data items for the specified Variable
5557 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5558 UINT index, CUSTDATA *pCustData)
5560 ICOM_THIS( ITypeInfoImpl, iface);
5561 TLBCustData *pCData;
5562 TLBVarDesc * pVDesc;
5563 int i;
5564 TRACE("(%p) index %d\n", This, index);
5565 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5566 pVDesc=pVDesc->next)
5568 if(pVDesc){
5569 pCustData->prgCustData =
5570 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5571 if(pCustData->prgCustData ){
5572 pCustData->cCustData=pVDesc->ctCustData;
5573 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5574 pCData = pCData->next){
5575 pCustData->prgCustData[i].guid=pCData->guid;
5576 VariantCopy(& pCustData->prgCustData[i].varValue,
5577 & pCData->data);
5579 }else{
5580 ERR(" OUT OF MEMORY! \n");
5581 return E_OUTOFMEMORY;
5583 return S_OK;
5585 return TYPE_E_ELEMENTNOTFOUND;
5588 /* ITypeInfo2::GetAllImplCustData
5590 * Gets all custom data items for the specified implementation type
5593 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5594 ITypeInfo2 * iface,
5595 UINT index,
5596 CUSTDATA *pCustData)
5598 ICOM_THIS( ITypeInfoImpl, iface);
5599 TLBCustData *pCData;
5600 TLBImplType * pRDesc;
5601 int i;
5602 TRACE("(%p) index %d\n", This, index);
5603 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5604 pRDesc=pRDesc->next)
5606 if(pRDesc){
5607 pCustData->prgCustData =
5608 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5609 if(pCustData->prgCustData ){
5610 pCustData->cCustData=pRDesc->ctCustData;
5611 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5612 pCData = pCData->next){
5613 pCustData->prgCustData[i].guid=pCData->guid;
5614 VariantCopy(& pCustData->prgCustData[i].varValue,
5615 & pCData->data);
5617 }else{
5618 ERR(" OUT OF MEMORY! \n");
5619 return E_OUTOFMEMORY;
5621 return S_OK;
5623 return TYPE_E_ELEMENTNOTFOUND;
5626 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5628 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5630 ITypeInfo_fnQueryInterface,
5631 ITypeInfo_fnAddRef,
5632 ITypeInfo_fnRelease,
5634 ITypeInfo_fnGetTypeAttr,
5635 ITypeInfo_fnGetTypeComp,
5636 ITypeInfo_fnGetFuncDesc,
5637 ITypeInfo_fnGetVarDesc,
5638 ITypeInfo_fnGetNames,
5639 ITypeInfo_fnGetRefTypeOfImplType,
5640 ITypeInfo_fnGetImplTypeFlags,
5641 ITypeInfo_fnGetIDsOfNames,
5642 ITypeInfo_fnInvoke,
5643 ITypeInfo_fnGetDocumentation,
5644 ITypeInfo_fnGetDllEntry,
5645 ITypeInfo_fnGetRefTypeInfo,
5646 ITypeInfo_fnAddressOfMember,
5647 ITypeInfo_fnCreateInstance,
5648 ITypeInfo_fnGetMops,
5649 ITypeInfo_fnGetContainingTypeLib,
5650 ITypeInfo_fnReleaseTypeAttr,
5651 ITypeInfo_fnReleaseFuncDesc,
5652 ITypeInfo_fnReleaseVarDesc,
5654 ITypeInfo2_fnGetTypeKind,
5655 ITypeInfo2_fnGetTypeFlags,
5656 ITypeInfo2_fnGetFuncIndexOfMemId,
5657 ITypeInfo2_fnGetVarIndexOfMemId,
5658 ITypeInfo2_fnGetCustData,
5659 ITypeInfo2_fnGetFuncCustData,
5660 ITypeInfo2_fnGetParamCustData,
5661 ITypeInfo2_fnGetVarCustData,
5662 ITypeInfo2_fnGetImplTypeCustData,
5663 ITypeInfo2_fnGetDocumentation2,
5664 ITypeInfo2_fnGetAllCustData,
5665 ITypeInfo2_fnGetAllFuncCustData,
5666 ITypeInfo2_fnGetAllParamCustData,
5667 ITypeInfo2_fnGetAllVarCustData,
5668 ITypeInfo2_fnGetAllImplTypeCustData,
5671 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5673 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5675 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5678 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5680 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5682 return ITypeInfo_AddRef((ITypeInfo *)This);
5685 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5687 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5689 return ITypeInfo_Release((ITypeInfo *)This);
5692 static HRESULT WINAPI ITypeComp_fnBind(
5693 ITypeComp * iface,
5694 OLECHAR * szName,
5695 unsigned long lHash,
5696 unsigned short wFlags,
5697 ITypeInfo ** ppTInfo,
5698 DESCKIND * pDescKind,
5699 BINDPTR * pBindPtr)
5701 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5702 TLBFuncDesc * pFDesc;
5703 TLBVarDesc * pVDesc;
5705 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5707 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5708 if (pFDesc->funcdesc.invkind & wFlags)
5709 if (!strcmpW(pFDesc->Name, szName)) {
5710 break;
5713 if (pFDesc)
5715 *pDescKind = DESCKIND_FUNCDESC;
5716 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5717 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5718 return S_OK;
5719 } else {
5720 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5722 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5723 if (!strcmpW(pVDesc->Name, szName)) {
5724 *pDescKind = DESCKIND_VARDESC;
5725 pBindPtr->lpvardesc = &pVDesc->vardesc;
5726 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5727 return S_OK;
5732 /* not found, look for it in inherited interfaces */
5733 if (This->TypeAttr.cImplTypes &&
5734 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
5735 /* recursive search */
5736 ITypeInfo *pTInfo;
5737 ITypeComp *pTComp;
5738 HRESULT hr;
5739 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5740 if (SUCCEEDED(hr))
5742 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5743 ITypeInfo_Release(pTInfo);
5745 if (SUCCEEDED(hr))
5747 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5748 ITypeComp_Release(pTComp);
5749 return hr;
5751 WARN("Could not search inherited interface!\n");
5753 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5754 *pDescKind = DESCKIND_NONE;
5755 pBindPtr->lpfuncdesc = NULL;
5756 *ppTInfo = NULL;
5757 return DISP_E_MEMBERNOTFOUND;
5760 static HRESULT WINAPI ITypeComp_fnBindType(
5761 ITypeComp * iface,
5762 OLECHAR * szName,
5763 unsigned long lHash,
5764 ITypeInfo ** ppTInfo,
5765 ITypeComp ** ppTComp)
5767 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5769 /* strange behaviour (does nothing) but like the
5770 * original */
5772 if (!ppTInfo || !ppTComp)
5773 return E_POINTER;
5775 *ppTInfo = NULL;
5776 *ppTComp = NULL;
5778 return S_OK;
5781 static ICOM_VTABLE(ITypeComp) tcompvt =
5783 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5785 ITypeComp_fnQueryInterface,
5786 ITypeComp_fnAddRef,
5787 ITypeComp_fnRelease,
5789 ITypeComp_fnBind,
5790 ITypeComp_fnBindType