Ref counting fixes.
[wine/hacks.git] / dlls / oleaut32 / typelib.c
blob41659dba0fdf50ac76758d28e96dbaff326327a5
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 static const 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("**************************************************************************\n");
325 break;
329 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile));
330 return TYPE_E_CANTLOADLIBRARY;
334 TRACE("File %s index %d\n", debugstr_w(szPath), index);
336 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
338 if (SUCCEEDED(res))
339 switch(regkind)
341 case REGKIND_DEFAULT:
342 /* don't register typelibs supplied with full path. Experimentation confirms the following */
343 if ((!szFile) ||
344 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
345 (szFile[0] && (szFile[1] == ':'))) break;
346 /* else fall-through */
348 case REGKIND_REGISTER:
349 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
351 IUnknown_Release(*pptLib);
352 *pptLib = 0;
354 break;
355 case REGKIND_NONE:
356 break;
359 TRACE(" returns %08lx\n",res);
360 return res;
363 /******************************************************************************
364 * LoadRegTypeLib [OLEAUT32.162]
366 HRESULT WINAPI LoadRegTypeLib(
367 REFGUID rguid, /* [in] referenced guid */
368 WORD wVerMajor, /* [in] major version */
369 WORD wVerMinor, /* [in] minor version */
370 LCID lcid, /* [in] locale id */
371 ITypeLib **ppTLib) /* [out] path of typelib */
373 BSTR bstr=NULL;
374 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
376 if(SUCCEEDED(res))
378 res= LoadTypeLib(bstr, ppTLib);
379 SysFreeString(bstr);
382 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
384 return res;
388 /******************************************************************************
389 * RegisterTypeLib [OLEAUT32.163]
390 * Adds information about a type library to the System Registry
391 * NOTES
392 * Docs: ITypeLib FAR * ptlib
393 * Docs: OLECHAR FAR* szFullPath
394 * Docs: OLECHAR FAR* szHelpDir
396 * RETURNS
397 * Success: S_OK
398 * Failure: Status
400 HRESULT WINAPI RegisterTypeLib(
401 ITypeLib * ptlib, /* [in] Pointer to the library*/
402 OLECHAR * szFullPath, /* [in] full Path of the library*/
403 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
404 may be NULL*/
406 HRESULT res;
407 TLIBATTR *attr;
408 OLECHAR guid[80];
409 LPSTR guidA;
410 CHAR keyName[120];
411 CHAR tmp[MAX_PATH];
412 HKEY key, subKey;
413 UINT types, tidx;
414 TYPEKIND kind;
415 DWORD disposition;
416 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
418 if (ptlib == NULL || szFullPath == NULL)
419 return E_INVALIDARG;
421 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
422 return E_FAIL;
424 StringFromGUID2(&attr->guid, guid, 80);
425 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
426 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
427 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
428 HeapFree(GetProcessHeap(), 0, guidA);
430 res = S_OK;
431 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
432 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
434 LPOLESTR doc;
436 /* Set the human-readable name of the typelib */
437 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
439 if (RegSetValueExW(key, NULL, 0, REG_SZ,
440 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
441 res = E_FAIL;
443 SysFreeString(doc);
445 else
446 res = E_FAIL;
448 /* Make up the name of the typelib path subkey */
449 sprintf(tmp, "%lu\\", attr->lcid);
450 switch(attr->syskind) {
451 case SYS_WIN16:
452 strcat(tmp, "win16");
453 break;
455 case SYS_WIN32:
456 strcat(tmp, "win32");
457 break;
459 default:
460 TRACE("Typelib is for unsupported syskind %i\n", attr->syskind);
461 res = E_FAIL;
462 break;
465 /* Create the typelib path subkey */
466 if (res == S_OK && RegCreateKeyExA(key, tmp, 0, NULL, 0,
467 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
469 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
470 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
471 res = E_FAIL;
473 RegCloseKey(subKey);
475 else
476 res = E_FAIL;
478 /* Create the flags subkey */
479 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
480 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
482 CHAR buf[20];
483 /* FIXME: is %u correct? */
484 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
485 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
486 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
487 res = E_FAIL;
489 RegCloseKey(subKey);
491 else
492 res = E_FAIL;
494 /* create the helpdir subkey */
495 if (res == S_OK && RegCreateKeyExA(key, "HELPDIR", 0, NULL, 0,
496 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
498 BOOL freeHelpDir = FALSE;
499 OLECHAR* pIndexStr;
501 /* if we created a new key, and helpDir was null, set the helpdir
502 to the directory which contains the typelib. However,
503 if we just opened an existing key, we leave the helpdir alone */
504 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
505 szHelpDir = SysAllocString(szFullPath);
506 pIndexStr = strrchrW(szHelpDir, '\\');
507 if (pIndexStr) {
508 *pIndexStr = 0;
510 freeHelpDir = TRUE;
513 /* if we have an szHelpDir, set it! */
514 if (szHelpDir != NULL) {
515 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
516 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
517 res = E_FAIL;
521 /* tidy up */
522 if (freeHelpDir) SysFreeString(szHelpDir);
523 RegCloseKey(subKey);
525 } else {
526 res = E_FAIL;
529 RegCloseKey(key);
531 else
532 res = E_FAIL;
534 /* register OLE Automation-compatible interfaces for this typelib */
535 types = ITypeLib_GetTypeInfoCount(ptlib);
536 for (tidx=0; tidx<types; tidx++) {
537 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
538 LPOLESTR name = NULL;
539 ITypeInfo *tinfo = NULL;
541 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
543 switch (kind) {
544 case TKIND_INTERFACE:
545 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
546 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
547 break;
549 case TKIND_DISPATCH:
550 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
551 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
552 break;
554 default:
555 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
556 break;
559 if (tinfo) {
560 TYPEATTR *tattr = NULL;
561 ITypeInfo_GetTypeAttr(tinfo, &tattr);
563 if (tattr) {
564 TRACE_(typelib)("guid=%s, flags=%04x (",
565 debugstr_guid(&tattr->guid),
566 tattr->wTypeFlags);
568 if (TRACE_ON(typelib)) {
569 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
570 XX(FAPPOBJECT);
571 XX(FCANCREATE);
572 XX(FLICENSED);
573 XX(FPREDECLID);
574 XX(FHIDDEN);
575 XX(FCONTROL);
576 XX(FDUAL);
577 XX(FNONEXTENSIBLE);
578 XX(FOLEAUTOMATION);
579 XX(FRESTRICTED);
580 XX(FAGGREGATABLE);
581 XX(FREPLACEABLE);
582 XX(FDISPATCHABLE);
583 XX(FREVERSEBIND);
584 XX(FPROXY);
585 #undef XX
586 MESSAGE("\n");
590 * FIXME: The 1 is just here until we implement rpcrt4
591 * stub/proxy handling. Until then it helps IShield
592 * v6 to work.
594 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
596 if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {
597 FIXME("Registering non-oleautomation interface!\n");
600 /* register interface<->typelib coupling */
601 StringFromGUID2(&tattr->guid, guid, 80);
602 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
603 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
604 HeapFree(GetProcessHeap(), 0, guidA);
606 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
607 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
608 if (name)
609 RegSetValueExW(key, NULL, 0, REG_SZ,
610 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
612 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
613 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
614 RegSetValueExA(subKey, NULL, 0, REG_SZ,
615 PSOA, strlen(PSOA));
616 RegCloseKey(subKey);
619 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
620 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
621 RegSetValueExA(subKey, NULL, 0, REG_SZ,
622 PSOA, strlen(PSOA));
623 RegCloseKey(subKey);
626 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
627 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
628 CHAR ver[32];
629 StringFromGUID2(&attr->guid, guid, 80);
630 snprintf(ver, sizeof(ver), "%x.%x",
631 attr->wMajorVerNum, attr->wMinorVerNum);
632 RegSetValueExW(subKey, NULL, 0, REG_SZ,
633 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
634 RegSetValueExA(subKey, "Version", 0, REG_SZ,
635 ver, lstrlenA(ver));
636 RegCloseKey(subKey);
639 RegCloseKey(key);
643 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
646 ITypeInfo_Release(tinfo);
649 SysFreeString(name);
653 ITypeLib_ReleaseTLibAttr(ptlib, attr);
655 return res;
659 /******************************************************************************
660 * UnRegisterTypeLib [OLEAUT32.186]
661 * Removes information about a type library from the System Registry
662 * NOTES
664 * RETURNS
665 * Success: S_OK
666 * Failure: Status
668 HRESULT WINAPI UnRegisterTypeLib(
669 REFGUID libid, /* [in] Guid of the library */
670 WORD wVerMajor, /* [in] major version */
671 WORD wVerMinor, /* [in] minor version */
672 LCID lcid, /* [in] locale id */
673 SYSKIND syskind)
675 BSTR tlibPath = NULL;
676 DWORD tmpLength;
677 CHAR keyName[MAX_PATH];
678 CHAR* syskindName;
679 CHAR subKeyName[MAX_PATH];
680 LPSTR guidA;
681 int result = S_OK;
682 DWORD i = 0;
683 OLECHAR guid[80];
684 BOOL deleteOtherStuff;
685 HKEY key = NULL;
686 HKEY subKey = NULL;
687 TYPEATTR* typeAttr = NULL;
688 TYPEKIND kind;
689 ITypeInfo* typeInfo = NULL;
690 ITypeLib* typeLib = NULL;
691 int numTypes;
693 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
695 /* Create the path to the key */
696 StringFromGUID2(libid, guid, 80);
697 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
698 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
699 guidA, wVerMajor, wVerMinor);
700 HeapFree(GetProcessHeap(), 0, guidA);
702 /* Work out the syskind name */
703 switch(syskind) {
704 case SYS_WIN16:
705 syskindName = "win16";
706 break;
708 case SYS_WIN32:
709 syskindName = "win32";
710 break;
712 default:
713 TRACE("Unsupported syskind %i\n", syskind);
714 result = E_INVALIDARG;
715 goto end;
718 /* get the path to the typelib on disk */
719 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
720 result = E_INVALIDARG;
721 goto end;
724 /* Try and open the key to the type library. */
725 if (RegOpenKeyExA(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
726 result = E_INVALIDARG;
727 goto end;
730 /* Try and load the type library */
731 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
732 result = TYPE_E_INVALIDSTATE;
733 goto end;
736 /* remove any types registered with this typelib */
737 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
738 for (i=0; i<numTypes; i++) {
739 /* get the kind of type */
740 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
741 goto enddeleteloop;
744 /* skip non-interfaces, and get type info for the type */
745 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
746 goto enddeleteloop;
748 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
749 goto enddeleteloop;
751 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
752 goto enddeleteloop;
755 /* the path to the type */
756 StringFromGUID2(&typeAttr->guid, guid, 80);
757 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
758 snprintf(subKeyName, sizeof(subKeyName), "Interface\\%s", guidA);
759 HeapFree(GetProcessHeap(), 0, guidA);
761 /* Delete its bits */
762 if (RegOpenKeyExA(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
763 goto enddeleteloop;
765 RegDeleteKeyA(subKey, "ProxyStubClsid");
766 RegDeleteKeyA(subKey, "ProxyStubClsid32");
767 RegDeleteKeyA(subKey, "TypeLib");
768 RegCloseKey(subKey);
769 subKey = NULL;
770 RegDeleteKeyA(HKEY_CLASSES_ROOT, subKeyName);
772 enddeleteloop:
773 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
774 typeAttr = NULL;
775 if (typeInfo) ITypeInfo_Release(typeInfo);
776 typeInfo = NULL;
779 /* Now, delete the type library path subkey */
780 sprintf(subKeyName, "%lu\\%s", lcid, syskindName);
781 RegDeleteKeyA(key, subKeyName);
782 sprintf(subKeyName, "%lu", lcid);
783 RegDeleteKeyA(key, subKeyName);
785 /* check if there is anything besides the FLAGS/HELPDIR keys.
786 If there is, we don't delete them */
787 tmpLength = sizeof(subKeyName);
788 deleteOtherStuff = TRUE;
789 i = 0;
790 while(RegEnumKeyExA(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
791 tmpLength = sizeof(subKeyName);
793 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
794 if (!strcmp(subKeyName, "FLAGS")) continue;
795 if (!strcmp(subKeyName, "HELPDIR")) continue;
796 deleteOtherStuff = FALSE;
797 break;
800 /* only delete the other parts of the key if we're absolutely sure */
801 if (deleteOtherStuff) {
802 RegDeleteKeyA(key, "FLAGS");
803 RegDeleteKeyA(key, "HELPDIR");
804 RegCloseKey(key);
805 key = NULL;
807 StringFromGUID2(libid, guid, 80);
808 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
809 sprintf(keyName, "TypeLib\\%s\\%x.%x", guidA, wVerMajor, wVerMinor);
810 RegDeleteKeyA(HKEY_CLASSES_ROOT, keyName);
811 sprintf(keyName, "TypeLib\\%s", guidA);
812 RegDeleteKeyA(HKEY_CLASSES_ROOT, keyName);
813 HeapFree(GetProcessHeap(), 0, guidA);
816 end:
817 if (tlibPath) SysFreeString(tlibPath);
818 if (typeLib) ITypeLib_Release(typeLib);
819 if (subKey) RegCloseKey(subKey);
820 if (key) RegCloseKey(key);
821 return result;
824 /*======================= ITypeLib implementation =======================*/
826 typedef struct tagTLBCustData
828 GUID guid;
829 VARIANT data;
830 struct tagTLBCustData* next;
831 } TLBCustData;
833 /* data structure for import typelibs */
834 typedef struct tagTLBImpLib
836 int offset; /* offset in the file (MSFT)
837 offset in nametable (SLTG)
838 just used to identify library while reading
839 data from file */
840 GUID guid; /* libid */
841 BSTR name; /* name */
843 LCID lcid; /* lcid of imported typelib */
845 WORD wVersionMajor; /* major version number */
846 WORD wVersionMinor; /* minor version number */
848 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
849 NULL if not yet loaded */
850 struct tagTLBImpLib * next;
851 } TLBImpLib;
853 /* internal ITypeLib data */
854 typedef struct tagITypeLibImpl
856 ITypeLib2Vtbl *lpVtbl;
857 ITypeCompVtbl *lpVtblTypeComp;
858 UINT ref;
859 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
861 /* strings can be stored in tlb as multibyte strings BUT they are *always*
862 * exported to the application as a UNICODE string.
864 BSTR Name;
865 BSTR DocString;
866 BSTR HelpFile;
867 BSTR HelpStringDll;
868 unsigned long dwHelpContext;
869 int TypeInfoCount; /* nr of typeinfo's in librarry */
870 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
871 int ctCustData; /* number of items in cust data list */
872 TLBCustData * pCustData; /* linked list to cust data */
873 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
874 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
875 libary. Only used while read MSFT
876 typelibs */
878 /* typelibs are cached, keyed by path, so store the linked list info within them */
879 struct tagITypeLibImpl *next, *prev;
880 WCHAR *path;
881 } ITypeLibImpl;
883 static struct ITypeLib2Vtbl tlbvt;
884 static struct ITypeCompVtbl tlbtcvt;
886 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
887 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
889 /* ITypeLib methods */
890 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
891 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
893 /*======================= ITypeInfo implementation =======================*/
895 /* data for refernced types */
896 typedef struct tagTLBRefType
898 INT index; /* Type index for internal ref or for external ref
899 it the format is SLTG. -2 indicates to
900 use guid */
902 GUID guid; /* guid of the referenced type */
903 /* if index == TLB_REF_USE_GUID */
905 HREFTYPE reference; /* The href of this ref */
906 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
907 TLB_REF_INTERNAL for internal refs
908 TLB_REF_NOT_FOUND for broken refs */
910 struct tagTLBRefType * next;
911 } TLBRefType;
913 #define TLB_REF_USE_GUID -2
915 #define TLB_REF_INTERNAL (void*)-2
916 #define TLB_REF_NOT_FOUND (void*)-1
918 /* internal Parameter data */
919 typedef struct tagTLBParDesc
921 BSTR Name;
922 int ctCustData;
923 TLBCustData * pCustData; /* linked list to cust data */
924 } TLBParDesc;
926 /* internal Function data */
927 typedef struct tagTLBFuncDesc
929 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
930 BSTR Name; /* the name of this function */
931 TLBParDesc *pParamDesc; /* array with param names and custom data */
932 int helpcontext;
933 int HelpStringContext;
934 BSTR HelpString;
935 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
936 int ctCustData;
937 TLBCustData * pCustData; /* linked list to cust data; */
938 struct tagTLBFuncDesc * next;
939 } TLBFuncDesc;
941 /* internal Variable data */
942 typedef struct tagTLBVarDesc
944 VARDESC vardesc; /* lots of info on the variable and its attributes. */
945 BSTR Name; /* the name of this variable */
946 int HelpContext;
947 int HelpStringContext; /* FIXME: where? */
948 BSTR HelpString;
949 int ctCustData;
950 TLBCustData * pCustData;/* linked list to cust data; */
951 struct tagTLBVarDesc * next;
952 } TLBVarDesc;
954 /* internal implemented interface data */
955 typedef struct tagTLBImplType
957 HREFTYPE hRef; /* hRef of interface */
958 int implflags; /* IMPLFLAG_*s */
959 int ctCustData;
960 TLBCustData * pCustData;/* linked list to custom data; */
961 struct tagTLBImplType *next;
962 } TLBImplType;
964 /* internal TypeInfo data */
965 typedef struct tagITypeInfoImpl
967 ITypeInfo2Vtbl *lpVtbl;
968 ITypeCompVtbl *lpVtblTypeComp;
969 UINT ref;
970 TYPEATTR TypeAttr ; /* _lots_ of type information. */
971 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
972 int index; /* index in this typelib; */
973 /* type libs seem to store the doc strings in ascii
974 * so why should we do it in unicode?
976 BSTR Name;
977 BSTR DocString;
978 unsigned long dwHelpContext;
979 unsigned long dwHelpStringContext;
981 /* functions */
982 TLBFuncDesc * funclist; /* linked list with function descriptions */
984 /* variables */
985 TLBVarDesc * varlist; /* linked list with variable descriptions */
987 /* Implemented Interfaces */
988 TLBImplType * impltypelist;
990 TLBRefType * reflist;
991 int ctCustData;
992 TLBCustData * pCustData; /* linked list to cust data; */
993 struct tagITypeInfoImpl * next;
994 } ITypeInfoImpl;
996 static struct ITypeInfo2Vtbl tinfvt;
997 static struct ITypeCompVtbl tcompvt;
999 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
1001 typedef struct tagTLBContext
1003 unsigned int oStart; /* start of TLB in file */
1004 unsigned int pos; /* current pos */
1005 unsigned int length; /* total length */
1006 void *mapping; /* memory mapping */
1007 MSFT_SegDir * pTblDir;
1008 ITypeLibImpl* pLibInfo;
1009 } TLBContext;
1012 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1015 debug
1017 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1018 if (pTD->vt & VT_RESERVED)
1019 szVarType += strlen(strcpy(szVarType, "reserved | "));
1020 if (pTD->vt & VT_BYREF)
1021 szVarType += strlen(strcpy(szVarType, "ref to "));
1022 if (pTD->vt & VT_ARRAY)
1023 szVarType += strlen(strcpy(szVarType, "array of "));
1024 if (pTD->vt & VT_VECTOR)
1025 szVarType += strlen(strcpy(szVarType, "vector of "));
1026 switch(pTD->vt & VT_TYPEMASK) {
1027 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1028 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1029 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1030 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1031 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1032 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1033 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1034 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1035 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1036 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1037 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1038 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1039 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1040 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1041 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1042 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1043 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1044 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1045 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1046 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); 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);
1106 MESSAGE("\telemdescFunc (return value type):\n");
1107 dump_ELEMDESC(&funcdesc->elemdescFunc);
1110 void dump_IDLDESC(IDLDESC *idl) {
1111 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
1114 static const char * typekind_desc[] =
1116 "TKIND_ENUM",
1117 "TKIND_RECORD",
1118 "TKIND_MODULE",
1119 "TKIND_INTERFACE",
1120 "TKIND_DISPATCH",
1121 "TKIND_COCLASS",
1122 "TKIND_ALIAS",
1123 "TKIND_UNION",
1124 "TKIND_MAX"
1127 void dump_TYPEATTR(TYPEATTR *tattr) {
1128 char buf[200];
1129 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
1130 MESSAGE("\tlcid: %ld\n",tattr->lcid);
1131 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
1132 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
1133 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
1134 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
1135 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
1136 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
1137 MESSAGE("\tcVars: %d\n", tattr->cVars);
1138 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
1139 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
1140 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
1141 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
1142 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
1143 dump_TypeDesc(&tattr->tdescAlias,buf);
1144 MESSAGE("\ttypedesc: %s\n", buf);
1145 dump_IDLDESC(&tattr->idldescType);
1148 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1150 int i;
1151 if (!TRACE_ON(typelib))
1152 return;
1153 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1154 for (i=0;i<pfd->funcdesc.cParams;i++)
1155 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1158 dump_FUNCDESC(&(pfd->funcdesc));
1160 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1161 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1163 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1165 while (pfd)
1167 dump_TLBFuncDescOne(pfd);
1168 pfd = pfd->next;
1171 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1173 while (pvd)
1175 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1176 pvd = pvd->next;
1180 static void dump_TLBImpLib(TLBImpLib *import)
1182 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1183 debugstr_w(import->name));
1184 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1185 import->wVersionMinor, import->lcid, import->offset);
1188 static void dump_TLBRefType(TLBRefType * prt)
1190 while (prt)
1192 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1193 if(prt->index == -1)
1194 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1195 else
1196 TRACE_(typelib)("type no: %d\n", prt->index);
1198 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1199 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1200 TRACE_(typelib)("in lib\n");
1201 dump_TLBImpLib(prt->pImpTLInfo);
1203 prt = prt->next;
1207 static void dump_TLBImplType(TLBImplType * impl)
1209 while (impl) {
1210 TRACE_(typelib)(
1211 "implementing/inheriting interface hRef = %lx implflags %x\n",
1212 impl->hRef, impl->implflags);
1213 impl = impl->next;
1217 void dump_Variant(VARIANT * pvar)
1219 SYSTEMTIME st;
1221 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1223 if (pvar)
1225 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1226 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1228 TRACE(",%p", V_BYREF(pvar));
1230 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1232 TRACE(",FIXME");
1234 else switch (V_TYPE(pvar))
1236 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1237 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1238 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1239 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1240 case VT_INT:
1241 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1242 case VT_UINT:
1243 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1244 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1245 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1246 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1247 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1248 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1249 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1250 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1251 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1252 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1253 V_CY(pvar).s.Lo); break;
1254 case VT_DATE:
1255 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1256 TRACE(",<invalid>");
1257 else
1258 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1259 st.wHour, st.wMinute, st.wSecond);
1260 break;
1261 case VT_ERROR:
1262 case VT_VOID:
1263 case VT_USERDEFINED:
1264 case VT_EMPTY:
1265 case VT_NULL: break;
1266 default: TRACE(",?"); break;
1269 TRACE("}\n");
1272 static void dump_DispParms(DISPPARAMS * pdp)
1274 int index = 0;
1276 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1278 while (index < pdp->cArgs)
1280 dump_Variant( &pdp->rgvarg[index] );
1281 ++index;
1285 static void dump_TypeInfo(ITypeInfoImpl * pty)
1287 TRACE("%p ref=%u\n", pty, pty->ref);
1288 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1289 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1290 TRACE("fct:%u var:%u impl:%u\n",
1291 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1292 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1293 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1294 dump_TLBFuncDesc(pty->funclist);
1295 dump_TLBVarDesc(pty->varlist);
1296 dump_TLBImplType(pty->impltypelist);
1299 void dump_VARDESC(VARDESC *v)
1301 MESSAGE("memid %ld\n",v->memid);
1302 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1303 MESSAGE("oInst %ld\n",v->u.oInst);
1304 dump_ELEMDESC(&(v->elemdescVar));
1305 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1306 MESSAGE("varkind %d\n",v->varkind);
1309 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1311 /* VT_LPWSTR is largest type that */
1312 /* may appear in type description*/
1313 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1314 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1315 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1316 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1317 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1318 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1319 {{0},30},{{0},31}
1322 static void TLB_abort()
1324 DebugBreak();
1326 static void * TLB_Alloc(unsigned size)
1328 void * ret;
1329 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1330 /* FIXME */
1331 ERR("cannot allocate memory\n");
1333 return ret;
1336 static void TLB_Free(void * ptr)
1338 HeapFree(GetProcessHeap(), 0, ptr);
1342 /**********************************************************************
1344 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1346 /* read function */
1347 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1349 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1350 pcx->pos, count, pcx->oStart, pcx->length, where);
1352 if (where != DO_NOT_SEEK)
1354 where += pcx->oStart;
1355 if (where > pcx->length)
1357 /* FIXME */
1358 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1359 TLB_abort();
1361 pcx->pos = where;
1363 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1364 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1365 pcx->pos += count;
1366 return count;
1369 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1370 long where )
1372 DWORD ret;
1374 ret = MSFT_Read(buffer, count, pcx, where);
1375 FromLEDWords(buffer, ret);
1377 return ret;
1380 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1381 long where )
1383 DWORD ret;
1385 ret = MSFT_Read(buffer, count, pcx, where);
1386 FromLEWords(buffer, ret);
1388 return ret;
1391 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1393 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1394 memset(pGuid,0, sizeof(GUID));
1395 return;
1397 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1398 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1399 pGuid->Data2 = FromLEWord(pGuid->Data2);
1400 pGuid->Data3 = FromLEWord(pGuid->Data3);
1401 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1404 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1406 char * name;
1407 MSFT_NameIntro niName;
1408 int lengthInChars;
1409 WCHAR* pwstring = NULL;
1410 BSTR bstrName = NULL;
1412 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1413 pcx->pTblDir->pNametab.offset+offset);
1414 niName.namelen &= 0xFF; /* FIXME: correct ? */
1415 name=TLB_Alloc((niName.namelen & 0xff) +1);
1416 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1417 name[niName.namelen & 0xff]='\0';
1419 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1420 name, -1, NULL, 0);
1422 /* no invalid characters in string */
1423 if (lengthInChars)
1425 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1427 /* don't check for invalid character since this has been done previously */
1428 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1430 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1431 lengthInChars = SysStringLen(bstrName);
1432 HeapFree(GetProcessHeap(), 0, pwstring);
1435 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1436 return bstrName;
1439 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1441 char * string;
1442 INT16 length;
1443 int lengthInChars;
1444 BSTR bstr = NULL;
1446 if(offset<0) return NULL;
1447 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1448 if(length <= 0) return 0;
1449 string=TLB_Alloc(length +1);
1450 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1451 string[length]='\0';
1453 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1454 string, -1, NULL, 0);
1456 /* no invalid characters in string */
1457 if (lengthInChars)
1459 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1461 /* don't check for invalid character since this has been done previously */
1462 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1464 bstr = SysAllocStringLen(pwstring, lengthInChars);
1465 lengthInChars = SysStringLen(bstr);
1466 HeapFree(GetProcessHeap(), 0, pwstring);
1469 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1470 return bstr;
1473 * read a value and fill a VARIANT structure
1475 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1477 int size;
1479 TRACE_(typelib)("\n");
1481 if(offset <0) { /* data are packed in here */
1482 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1483 V_UNION(pVar, iVal) = offset & 0xffff;
1484 return;
1486 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1487 pcx->pTblDir->pCustData.offset + offset );
1488 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1489 switch (V_VT(pVar)){
1490 case VT_EMPTY: /* FIXME: is this right? */
1491 case VT_NULL: /* FIXME: is this right? */
1492 case VT_I2 : /* this should not happen */
1493 case VT_I4 :
1494 case VT_R4 :
1495 case VT_ERROR :
1496 case VT_BOOL :
1497 case VT_I1 :
1498 case VT_UI1 :
1499 case VT_UI2 :
1500 case VT_UI4 :
1501 case VT_INT :
1502 case VT_UINT :
1503 case VT_VOID : /* FIXME: is this right? */
1504 case VT_HRESULT :
1505 size=4; break;
1506 case VT_R8 :
1507 case VT_CY :
1508 case VT_DATE :
1509 case VT_I8 :
1510 case VT_UI8 :
1511 case VT_DECIMAL : /* FIXME: is this right? */
1512 case VT_FILETIME :
1513 size=8;break;
1514 /* pointer types with known behaviour */
1515 case VT_BSTR :{
1516 char * ptr;
1517 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1518 if(size < 0) {
1519 FIXME("BSTR length = %d?\n", size);
1520 } else {
1521 ptr=TLB_Alloc(size);/* allocate temp buffer */
1522 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1523 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1524 /* FIXME: do we need a AtoW conversion here? */
1525 V_UNION(pVar, bstrVal[size])=L'\0';
1526 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1527 TLB_Free(ptr);
1530 size=-4; break;
1531 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1532 case VT_DISPATCH :
1533 case VT_VARIANT :
1534 case VT_UNKNOWN :
1535 case VT_PTR :
1536 case VT_SAFEARRAY :
1537 case VT_CARRAY :
1538 case VT_USERDEFINED :
1539 case VT_LPSTR :
1540 case VT_LPWSTR :
1541 case VT_BLOB :
1542 case VT_STREAM :
1543 case VT_STORAGE :
1544 case VT_STREAMED_OBJECT :
1545 case VT_STORED_OBJECT :
1546 case VT_BLOB_OBJECT :
1547 case VT_CF :
1548 case VT_CLSID :
1549 default:
1550 size=0;
1551 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1552 V_VT(pVar));
1555 if(size>0) /* (big|small) endian correct? */
1556 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1557 return;
1560 * create a linked list with custom data
1562 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1564 MSFT_CDGuid entry;
1565 TLBCustData* pNew;
1566 int count=0;
1568 TRACE_(typelib)("\n");
1570 while(offset >=0){
1571 count++;
1572 pNew=TLB_Alloc(sizeof(TLBCustData));
1573 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1574 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1575 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1576 /* add new custom data at head of the list */
1577 pNew->next=*ppCustData;
1578 *ppCustData=pNew;
1579 offset = entry.next;
1581 return count;
1584 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1585 ITypeInfoImpl *pTI)
1587 if(type <0)
1588 pTd->vt=type & VT_TYPEMASK;
1589 else
1590 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1592 if(pTd->vt == VT_USERDEFINED)
1593 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1595 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1598 static void
1599 MSFT_DoFuncs(TLBContext* pcx,
1600 ITypeInfoImpl* pTI,
1601 int cFuncs,
1602 int cVars,
1603 int offset,
1604 TLBFuncDesc** pptfd)
1607 * member information is stored in a data structure at offset
1608 * indicated by the memoffset field of the typeinfo structure
1609 * There are several distinctive parts.
1610 * the first part starts with a field that holds the total length
1611 * of this (first) part excluding this field. Then follow the records,
1612 * for each member there is one record.
1614 * First entry is always the length of the record (excluding this
1615 * length word).
1616 * Rest of the record depends on the type of the member. If there is
1617 * a field indicating the member type (function variable intereface etc)
1618 * I have not found it yet. At this time we depend on the information
1619 * in the type info and the usual order how things are stored.
1621 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1622 * for each member;
1624 * Third is a equal sized array with file offsets to the name entry
1625 * of each member.
1627 * Forth and last (?) part is an array with offsets to the records in the
1628 * first part of this file segment.
1631 int infolen, nameoffset, reclength, nrattributes, i;
1632 int recoffset = offset + sizeof(INT);
1634 char recbuf[512];
1635 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1637 TRACE_(typelib)("\n");
1639 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1641 for ( i = 0; i < cFuncs ; i++ )
1643 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1645 /* name, eventually add to a hash table */
1646 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1647 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1649 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1651 /* read the function information record */
1652 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1654 reclength &= 0x1ff;
1656 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1658 /* do the attributes */
1659 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1660 / sizeof(int);
1662 if ( nrattributes > 0 )
1664 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1666 if ( nrattributes > 1 )
1668 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1669 pFuncRec->OptAttr[1]) ;
1671 if ( nrattributes > 2 )
1673 if ( pFuncRec->FKCCIC & 0x2000 )
1675 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1677 else
1679 (*pptfd)->Entry = MSFT_ReadString(pcx,
1680 pFuncRec->OptAttr[2]);
1682 if( nrattributes > 5 )
1684 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1686 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1688 MSFT_CustData(pcx,
1689 pFuncRec->OptAttr[6],
1690 &(*pptfd)->pCustData);
1697 /* fill the FuncDesc Structure */
1698 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1699 offset + infolen + ( i + 1) * sizeof(INT));
1701 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1702 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1703 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1704 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1705 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1706 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1707 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1709 MSFT_GetTdesc(pcx,
1710 pFuncRec->DataType,
1711 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1712 pTI);
1714 /* do the parameters/arguments */
1715 if(pFuncRec->nrargs)
1717 int j = 0;
1718 MSFT_ParameterInfo paraminfo;
1720 (*pptfd)->funcdesc.lprgelemdescParam =
1721 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1723 (*pptfd)->pParamDesc =
1724 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1726 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1727 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1729 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1731 TYPEDESC* lpArgTypeDesc = 0;
1733 MSFT_GetTdesc(pcx,
1734 paraminfo.DataType,
1735 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1736 pTI);
1738 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1740 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1742 /* SEEK value = jump to offset,
1743 * from there jump to the end of record,
1744 * go back by (j-1) arguments
1746 MSFT_ReadLEDWords( &paraminfo ,
1747 sizeof(MSFT_ParameterInfo), pcx,
1748 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1749 * sizeof(MSFT_ParameterInfo)));
1750 lpArgTypeDesc =
1751 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1753 while ( lpArgTypeDesc != NULL )
1755 switch ( lpArgTypeDesc->vt )
1757 case VT_PTR:
1758 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1759 break;
1761 case VT_CARRAY:
1762 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1763 break;
1765 case VT_USERDEFINED:
1766 MSFT_DoRefType(pcx, pTI,
1767 lpArgTypeDesc->u.hreftype);
1769 lpArgTypeDesc = NULL;
1770 break;
1772 default:
1773 lpArgTypeDesc = NULL;
1779 /* parameter is the return value! */
1780 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1782 TYPEDESC* lpArgTypeDesc;
1784 (*pptfd)->funcdesc.elemdescFunc =
1785 (*pptfd)->funcdesc.lprgelemdescParam[j];
1787 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1789 while ( lpArgTypeDesc != NULL )
1791 switch ( lpArgTypeDesc->vt )
1793 case VT_PTR:
1794 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1795 break;
1796 case VT_CARRAY:
1797 lpArgTypeDesc =
1798 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1800 break;
1802 case VT_USERDEFINED:
1803 MSFT_DoRefType(pcx,
1804 pTI,
1805 lpArgTypeDesc->u.hreftype);
1807 lpArgTypeDesc = NULL;
1808 break;
1810 default:
1811 lpArgTypeDesc = NULL;
1816 /* second time around */
1817 for(j=0;j<pFuncRec->nrargs;j++)
1819 /* name */
1820 (*pptfd)->pParamDesc[j].Name =
1821 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1823 /* default value */
1824 if ( (PARAMFLAG_FHASDEFAULT &
1825 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1826 ((pFuncRec->FKCCIC) & 0x1000) )
1828 INT* pInt = (INT *)((char *)pFuncRec +
1829 reclength -
1830 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1832 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1834 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1835 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1837 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1838 pInt[j], pcx);
1840 /* custom info */
1841 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1843 MSFT_CustData(pcx,
1844 pFuncRec->OptAttr[7+j],
1845 &(*pptfd)->pParamDesc[j].pCustData);
1850 /* scode is not used: archaic win16 stuff FIXME: right? */
1851 (*pptfd)->funcdesc.cScodes = 0 ;
1852 (*pptfd)->funcdesc.lprgscode = NULL ;
1854 pptfd = & ((*pptfd)->next);
1855 recoffset += reclength;
1859 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1860 int cVars, int offset, TLBVarDesc ** pptvd)
1862 int infolen, nameoffset, reclength;
1863 char recbuf[256];
1864 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1865 int i;
1866 int recoffset;
1868 TRACE_(typelib)("\n");
1870 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1871 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1872 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1873 recoffset += offset+sizeof(INT);
1874 for(i=0;i<cVars;i++){
1875 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1876 /* name, eventually add to a hash table */
1877 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1878 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1879 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1880 /* read the variable information record */
1881 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1882 reclength &=0xff;
1883 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1884 /* Optional data */
1885 if(reclength >(6*sizeof(INT)) )
1886 (*pptvd)->HelpContext=pVarRec->HelpContext;
1887 if(reclength >(7*sizeof(INT)) )
1888 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1889 if(reclength >(8*sizeof(INT)) )
1890 if(reclength >(9*sizeof(INT)) )
1891 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1892 /* fill the VarDesc Structure */
1893 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1894 offset + infolen + ( i + 1) * sizeof(INT));
1895 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1896 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1897 MSFT_GetTdesc(pcx, pVarRec->DataType,
1898 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1899 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1900 if(pVarRec->VarKind == VAR_CONST ){
1901 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1902 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1903 pVarRec->OffsValue, pcx);
1904 } else
1905 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1906 pptvd=&((*pptvd)->next);
1907 recoffset += reclength;
1910 /* fill in data for a hreftype (offset). When the refernced type is contained
1911 * in the typelib, it's just an (file) offset in the type info base dir.
1912 * If comes from import, it's an offset+1 in the ImpInfo table
1913 * */
1914 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1915 int offset)
1917 int j;
1918 TLBRefType **ppRefType = &pTI->reflist;
1920 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1922 while(*ppRefType) {
1923 if((*ppRefType)->reference == offset)
1924 return;
1925 ppRefType = &(*ppRefType)->next;
1928 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1929 sizeof(**ppRefType));
1931 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1932 /* external typelib */
1933 MSFT_ImpInfo impinfo;
1934 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1936 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1938 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1939 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1940 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1941 if(pImpLib->offset==impinfo.oImpFile) break;
1942 pImpLib=pImpLib->next;
1944 if(pImpLib){
1945 (*ppRefType)->reference=offset;
1946 (*ppRefType)->pImpTLInfo = pImpLib;
1947 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1948 (*ppRefType)->index = TLB_REF_USE_GUID;
1949 }else{
1950 ERR("Cannot find a reference\n");
1951 (*ppRefType)->reference=-1;
1952 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1954 }else{
1955 /* in this typelib */
1956 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1957 (*ppRefType)->reference=offset;
1958 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1962 /* process Implemented Interfaces of a com class */
1963 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1964 int offset)
1966 int i;
1967 MSFT_RefRecord refrec;
1968 TLBImplType **ppImpl = &pTI->impltypelist;
1970 TRACE_(typelib)("\n");
1972 for(i=0;i<count;i++){
1973 if(offset<0) break; /* paranoia */
1974 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1975 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1976 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1977 (*ppImpl)->hRef = refrec.reftype;
1978 (*ppImpl)->implflags=refrec.flags;
1979 (*ppImpl)->ctCustData=
1980 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1981 offset=refrec.onext;
1982 ppImpl=&((*ppImpl)->next);
1986 * process a typeinfo record
1988 ITypeInfoImpl * MSFT_DoTypeInfo(
1989 TLBContext *pcx,
1990 int count,
1991 ITypeLibImpl * pLibInfo)
1993 MSFT_TypeInfoBase tiBase;
1994 ITypeInfoImpl *ptiRet;
1996 TRACE_(typelib)("count=%u\n", count);
1998 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1999 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2000 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2001 /* this is where we are coming from */
2002 ptiRet->pTypeLib = pLibInfo;
2003 ptiRet->index=count;
2004 /* fill in the typeattr fields */
2005 WARN("Assign constructor/destructor memid\n");
2007 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2008 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2009 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2010 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2011 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2012 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2013 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2014 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2015 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2016 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2017 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2018 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2019 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2020 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2021 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2022 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2023 MSFT_GetTdesc(pcx, tiBase.datatype1,
2024 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2026 /* FIXME: */
2027 /* IDLDESC idldescType; *//* never saw this one != zero */
2029 /* name, eventually add to a hash table */
2030 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2031 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2032 /* help info */
2033 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2034 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2035 ptiRet->dwHelpContext=tiBase.helpcontext;
2036 /* note: InfoType's Help file and HelpStringDll come from the containing
2037 * library. Further HelpString and Docstring appear to be the same thing :(
2039 /* functions */
2040 if(ptiRet->TypeAttr.cFuncs >0 )
2041 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2042 ptiRet->TypeAttr.cVars,
2043 tiBase.memoffset, & ptiRet->funclist);
2044 /* variables */
2045 if(ptiRet->TypeAttr.cVars >0 )
2046 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2047 ptiRet->TypeAttr.cVars,
2048 tiBase.memoffset, & ptiRet->varlist);
2049 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2050 switch(ptiRet->TypeAttr.typekind)
2052 case TKIND_COCLASS:
2053 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2054 tiBase.datatype1);
2055 break;
2056 case TKIND_DISPATCH:
2057 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2059 if (tiBase.datatype1 != -1)
2061 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2062 ptiRet->impltypelist->hRef = tiBase.datatype1;
2064 else
2065 { /* FIXME: This is a really bad hack to add IDispatch */
2066 const char* szStdOle = "stdole2.tlb\0";
2067 int nStdOleLen = strlen(szStdOle);
2068 TLBRefType **ppRef = &ptiRet->reflist;
2070 while(*ppRef) {
2071 if((*ppRef)->reference == -1)
2072 break;
2073 ppRef = &(*ppRef)->next;
2075 if(!*ppRef) {
2076 *ppRef = TLB_Alloc(sizeof(**ppRef));
2077 (*ppRef)->guid = IID_IDispatch;
2078 (*ppRef)->reference = -1;
2079 (*ppRef)->index = TLB_REF_USE_GUID;
2080 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2081 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2082 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2083 nStdOleLen + 1);
2085 MultiByteToWideChar(CP_ACP,
2086 MB_PRECOMPOSED,
2087 szStdOle,
2089 (*ppRef)->pImpTLInfo->name,
2090 SysStringLen((*ppRef)->pImpTLInfo->name));
2092 (*ppRef)->pImpTLInfo->lcid = 0;
2093 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2094 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2097 break;
2098 default:
2099 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2100 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2101 ptiRet->impltypelist->hRef = tiBase.datatype1;
2102 break;
2105 ptiRet->ctCustData=
2106 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2108 TRACE_(typelib)("%s guid: %s kind:%s\n",
2109 debugstr_w(ptiRet->Name),
2110 debugstr_guid(&ptiRet->TypeAttr.guid),
2111 typekind_desc[ptiRet->TypeAttr.typekind]);
2113 return ptiRet;
2116 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2117 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2118 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2119 * tradeoff here.
2121 static ITypeLibImpl *tlb_cache_first;
2122 static CRITICAL_SECTION cache_section;
2123 static CRITICAL_SECTION_DEBUG cache_section_debug =
2125 0, 0, &cache_section,
2126 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2127 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
2129 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2132 /****************************************************************************
2133 * TLB_ReadTypeLib
2135 * find the type of the typelib file and map the typelib resource into
2136 * the memory
2138 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2139 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2140 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2142 ITypeLibImpl *entry;
2143 int ret = TYPE_E_CANTLOADLIBRARY;
2144 DWORD dwSignature = 0;
2145 HANDLE hFile;
2147 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2149 *ppTypeLib = NULL;
2151 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2152 EnterCriticalSection(&cache_section);
2153 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2155 if (!strcmpiW(entry->path, pszFileName))
2157 TRACE("cache hit\n");
2158 *ppTypeLib = (ITypeLib2*)entry;
2159 ITypeLib_AddRef(*ppTypeLib);
2160 LeaveCriticalSection(&cache_section);
2161 return S_OK;
2164 LeaveCriticalSection(&cache_section);
2166 /* check the signature of the file */
2167 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2168 if (INVALID_HANDLE_VALUE != hFile)
2170 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2171 if (hMapping)
2173 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2174 if(pBase)
2176 /* retrieve file size */
2177 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2179 /* first try to load as *.tlb */
2180 dwSignature = FromLEDWord(*((DWORD*) pBase));
2181 if ( dwSignature == MSFT_SIGNATURE)
2183 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2185 else if ( dwSignature == SLTG_SIGNATURE)
2187 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2189 UnmapViewOfFile(pBase);
2191 CloseHandle(hMapping);
2193 CloseHandle(hFile);
2196 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2198 /* find the typelibrary resource*/
2199 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2200 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2201 if (hinstDLL)
2203 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2204 "TYPELIB");
2205 if (hrsrc)
2207 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2208 if (hGlobal)
2210 LPVOID pBase = LockResource(hGlobal);
2211 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2213 if (pBase)
2215 /* try to load as incore resource */
2216 dwSignature = FromLEDWord(*((DWORD*) pBase));
2217 if ( dwSignature == MSFT_SIGNATURE)
2219 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2221 else if ( dwSignature == SLTG_SIGNATURE)
2223 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2225 else
2227 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2230 FreeResource( hGlobal );
2233 FreeLibrary(hinstDLL);
2237 if(*ppTypeLib) {
2238 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2240 TRACE("adding to cache\n");
2241 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2242 lstrcpyW(impl->path, pszFileName);
2243 /* We should really canonicalise the path here. */
2245 /* FIXME: check if it has added already in the meantime */
2246 EnterCriticalSection(&cache_section);
2247 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2248 impl->prev = NULL;
2249 tlb_cache_first = impl;
2250 LeaveCriticalSection(&cache_section);
2251 ret = S_OK;
2252 } else
2253 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2255 return ret;
2258 /*================== ITypeLib(2) Methods ===================================*/
2260 /****************************************************************************
2261 * ITypeLib2_Constructor_MSFT
2263 * loading an MSFT typelib from an in-memory image
2265 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2267 TLBContext cx;
2268 long lPSegDir;
2269 MSFT_Header tlbHeader;
2270 MSFT_SegDir tlbSegDir;
2271 ITypeLibImpl * pTypeLibImpl;
2273 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2275 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2276 if (!pTypeLibImpl) return NULL;
2278 pTypeLibImpl->lpVtbl = &tlbvt;
2279 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2280 pTypeLibImpl->ref = 1;
2282 /* get pointer to beginning of typelib data */
2283 cx.pos = 0;
2284 cx.oStart=0;
2285 cx.mapping = pLib;
2286 cx.pLibInfo = pTypeLibImpl;
2287 cx.length = dwTLBLength;
2289 /* read header */
2290 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2291 TRACE("header:\n");
2292 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2293 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2294 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2295 return NULL;
2297 /* there is a small amount of information here until the next important
2298 * part:
2299 * the segment directory . Try to calculate the amount of data */
2300 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2302 /* now read the segment directory */
2303 TRACE("read segment directory (at %ld)\n",lPSegDir);
2304 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2305 cx.pTblDir = &tlbSegDir;
2307 /* just check two entries */
2308 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2310 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2311 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2312 return NULL;
2315 /* now fill our internal data */
2316 /* TLIBATTR fields */
2317 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2319 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2320 /* Windows seems to have zero here, is this correct? */
2321 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2322 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2323 else
2324 pTypeLibImpl->LibAttr.lcid = 0;
2326 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2327 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2328 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2329 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2331 /* name, eventually add to a hash table */
2332 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2334 /* help info */
2335 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2336 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2338 if( tlbHeader.varflags & HELPDLLFLAG)
2340 int offset;
2341 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2342 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2345 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2347 /* custom data */
2348 if(tlbHeader.CustomDataOffset >= 0)
2350 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2353 /* fill in typedescriptions */
2354 if(tlbSegDir.pTypdescTab.length > 0)
2356 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2357 INT16 td[4];
2358 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2359 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2360 for(i=0; i<cTD; )
2362 /* FIXME: add several sanity checks here */
2363 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2364 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2366 /* FIXME: check safearray */
2367 if(td[3] < 0)
2368 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2369 else
2370 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2372 else if(td[0] == VT_CARRAY)
2374 /* array descr table here */
2375 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2377 else if(td[0] == VT_USERDEFINED)
2379 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2381 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2384 /* second time around to fill the array subscript info */
2385 for(i=0;i<cTD;i++)
2387 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2388 if(tlbSegDir.pArrayDescriptions.offset>0)
2390 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2391 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2393 if(td[1]<0)
2394 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2395 else
2396 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2398 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2400 for(j = 0; j<td[2]; j++)
2402 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2403 sizeof(INT), &cx, DO_NOT_SEEK);
2404 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2405 sizeof(INT), &cx, DO_NOT_SEEK);
2408 else
2410 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2411 ERR("didn't find array description data\n");
2416 /* imported type libs */
2417 if(tlbSegDir.pImpFiles.offset>0)
2419 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2420 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2421 UINT16 size;
2423 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2425 char *name;
2426 DWORD len;
2428 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2429 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2430 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2432 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2433 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2434 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2435 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2437 size >>= 2;
2438 name = TLB_Alloc(size+1);
2439 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2440 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2441 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2442 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2443 TLB_Free(name);
2445 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2446 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2448 ppImpLib = &(*ppImpLib)->next;
2452 /* type info's */
2453 if(tlbHeader.nrtypeinfos >= 0 )
2455 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2456 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2457 int i;
2459 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2461 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2463 ppTI = &((*ppTI)->next);
2464 (pTypeLibImpl->TypeInfoCount)++;
2468 TRACE("(%p)\n", pTypeLibImpl);
2469 return (ITypeLib2*) pTypeLibImpl;
2473 static BSTR TLB_MultiByteToBSTR(char *ptr)
2475 DWORD len;
2476 WCHAR *nameW;
2477 BSTR ret;
2479 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2480 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2481 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2482 ret = SysAllocString(nameW);
2483 HeapFree(GetProcessHeap(), 0, nameW);
2484 return ret;
2487 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2489 char b[3];
2490 int i;
2491 short s;
2493 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2494 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2495 return FALSE;
2498 guid->Data4[0] = s >> 8;
2499 guid->Data4[1] = s & 0xff;
2501 b[2] = '\0';
2502 for(i = 0; i < 6; i++) {
2503 memcpy(b, str + 24 + 2 * i, 2);
2504 guid->Data4[i + 2] = strtol(b, NULL, 16);
2506 return TRUE;
2509 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2511 WORD bytelen;
2512 DWORD len;
2513 WCHAR *nameW;
2515 *pBstr = NULL;
2516 bytelen = *(WORD*)ptr;
2517 if(bytelen == 0xffff) return 2;
2518 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2519 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2520 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2521 *pBstr = SysAllocStringLen(nameW, len);
2522 HeapFree(GetProcessHeap(), 0, nameW);
2523 return bytelen + 2;
2526 static WORD SLTG_ReadStringA(char *ptr, char **str)
2528 WORD bytelen;
2530 *str = NULL;
2531 bytelen = *(WORD*)ptr;
2532 if(bytelen == 0xffff) return 2;
2533 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2534 memcpy(*str, ptr + 2, bytelen);
2535 (*str)[bytelen] = '\0';
2536 return bytelen + 2;
2539 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2541 char *ptr = pLibBlk;
2542 WORD w;
2544 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2545 FIXME("libblk magic = %04x\n", w);
2546 return 0;
2549 ptr += 6;
2550 if((w = *(WORD*)ptr) != 0xffff) {
2551 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2552 ptr += w;
2554 ptr += 2;
2556 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2558 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2560 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2561 ptr += 4;
2563 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2564 ptr += 2;
2566 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2567 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2568 else
2569 pTypeLibImpl->LibAttr.lcid = 0;
2570 ptr += 2;
2572 ptr += 4; /* skip res12 */
2574 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2575 ptr += 2;
2577 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2578 ptr += 2;
2580 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2581 ptr += 2;
2583 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2584 ptr += sizeof(GUID);
2586 return ptr - (char*)pLibBlk;
2589 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2591 BOOL done = FALSE;
2592 TYPEDESC *pTD = &pElem->tdesc;
2594 /* Handle [in/out] first */
2595 if((*pType & 0xc000) == 0xc000)
2596 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2597 else if(*pType & 0x8000)
2598 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2599 else if(*pType & 0x4000)
2600 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2601 else
2602 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2604 if(*pType & 0x2000)
2605 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2607 if(*pType & 0x80)
2608 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2610 while(!done) {
2611 if((*pType & 0xe00) == 0xe00) {
2612 pTD->vt = VT_PTR;
2613 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2614 sizeof(TYPEDESC));
2615 pTD = pTD->u.lptdesc;
2617 switch(*pType & 0x7f) {
2618 case VT_PTR:
2619 pTD->vt = VT_PTR;
2620 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2621 sizeof(TYPEDESC));
2622 pTD = pTD->u.lptdesc;
2623 break;
2625 case VT_USERDEFINED:
2626 pTD->vt = VT_USERDEFINED;
2627 pTD->u.hreftype = *(++pType) / 4;
2628 done = TRUE;
2629 break;
2631 case VT_CARRAY:
2633 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2634 array */
2636 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2638 pTD->vt = VT_CARRAY;
2639 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2640 sizeof(ARRAYDESC) +
2641 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2642 pTD->u.lpadesc->cDims = pSA->cDims;
2643 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2644 pSA->cDims * sizeof(SAFEARRAYBOUND));
2646 pTD = &pTD->u.lpadesc->tdescElem;
2647 break;
2650 case VT_SAFEARRAY:
2652 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2653 useful? */
2655 pType++;
2656 pTD->vt = VT_SAFEARRAY;
2657 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2658 sizeof(TYPEDESC));
2659 pTD = pTD->u.lptdesc;
2660 break;
2662 default:
2663 pTD->vt = *pType & 0x7f;
2664 done = TRUE;
2665 break;
2667 pType++;
2669 return pType;
2673 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2674 char *pNameTable)
2676 int ref;
2677 char *name;
2678 TLBRefType **ppRefType;
2680 if(pRef->magic != SLTG_REF_MAGIC) {
2681 FIXME("Ref magic = %x\n", pRef->magic);
2682 return;
2684 name = ( (char*)(&pRef->names) + pRef->number);
2686 ppRefType = &pTI->reflist;
2687 for(ref = 0; ref < pRef->number >> 3; ref++) {
2688 char *refname;
2689 unsigned int lib_offs, type_num;
2691 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2692 sizeof(**ppRefType));
2694 name += SLTG_ReadStringA(name, &refname);
2695 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2696 FIXME("Can't sscanf ref\n");
2697 if(lib_offs != 0xffff) {
2698 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2700 while(*import) {
2701 if((*import)->offset == lib_offs)
2702 break;
2703 import = &(*import)->next;
2705 if(!*import) {
2706 char fname[MAX_PATH+1];
2707 int len;
2709 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2710 sizeof(**import));
2711 (*import)->offset = lib_offs;
2712 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2713 &(*import)->guid);
2714 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2715 &(*import)->wVersionMajor,
2716 &(*import)->wVersionMinor,
2717 &(*import)->lcid, fname) != 4) {
2718 FIXME("can't sscanf ref %s\n",
2719 pNameTable + lib_offs + 40);
2721 len = strlen(fname);
2722 if(fname[len-1] != '#')
2723 FIXME("fname = %s\n", fname);
2724 fname[len-1] = '\0';
2725 (*import)->name = TLB_MultiByteToBSTR(fname);
2727 (*ppRefType)->pImpTLInfo = *import;
2728 } else { /* internal ref */
2729 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2731 (*ppRefType)->reference = ref;
2732 (*ppRefType)->index = type_num;
2734 HeapFree(GetProcessHeap(), 0, refname);
2735 ppRefType = &(*ppRefType)->next;
2737 if((BYTE)*name != SLTG_REF_MAGIC)
2738 FIXME("End of ref block magic = %x\n", *name);
2739 dump_TLBRefType(pTI->reflist);
2742 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2743 BOOL OneOnly)
2745 SLTG_ImplInfo *info;
2746 TLBImplType **ppImplType = &pTI->impltypelist;
2747 /* I don't really get this structure, usually it's 0x16 bytes
2748 long, but iuser.tlb contains some that are 0x18 bytes long.
2749 That's ok because we can use the next ptr to jump to the next
2750 one. But how do we know the length of the last one? The WORD
2751 at offs 0x8 might be the clue. For now I'm just assuming that
2752 the last one is the regular 0x16 bytes. */
2754 info = (SLTG_ImplInfo*)pBlk;
2755 while(1) {
2756 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2757 sizeof(**ppImplType));
2758 (*ppImplType)->hRef = info->ref;
2759 (*ppImplType)->implflags = info->impltypeflags;
2760 pTI->TypeAttr.cImplTypes++;
2761 ppImplType = &(*ppImplType)->next;
2763 if(info->next == 0xffff)
2764 break;
2765 if(OneOnly)
2766 FIXME("Interface inheriting more than one interface\n");
2767 info = (SLTG_ImplInfo*)(pBlk + info->next);
2769 info++; /* see comment at top of function */
2770 return (char*)info;
2773 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2774 char *pNameTable)
2776 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2777 SLTG_MemberHeader *pMemHeader;
2778 char *pFirstItem, *pNextItem;
2780 if(pTIHeader->href_table != 0xffffffff) {
2781 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2782 pNameTable);
2786 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2788 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2790 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2791 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2794 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2798 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2799 char *pNameTable)
2801 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2802 SLTG_MemberHeader *pMemHeader;
2803 SLTG_Function *pFunc;
2804 char *pFirstItem, *pNextItem;
2805 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2806 int num = 0;
2808 if(pTIHeader->href_table != 0xffffffff) {
2809 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2810 pNameTable);
2813 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2815 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2817 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2818 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2821 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2822 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2824 int param;
2825 WORD *pType, *pArg;
2827 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2828 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2829 FIXME("func magic = %02x\n", pFunc->magic);
2830 return NULL;
2832 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2833 sizeof(**ppFuncDesc));
2834 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2836 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2837 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2838 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2839 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2840 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2841 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2843 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2844 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2846 if(pFunc->retnextopt & 0x80)
2847 pType = &pFunc->rettype;
2848 else
2849 pType = (WORD*)(pFirstItem + pFunc->rettype);
2852 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2854 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2855 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2856 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2857 (*ppFuncDesc)->pParamDesc =
2858 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2859 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2861 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2863 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2864 char *paramName = pNameTable + *pArg;
2865 BOOL HaveOffs;
2866 /* If arg type follows then paramName points to the 2nd
2867 letter of the name, else the next WORD is an offset to
2868 the arg type and paramName points to the first letter.
2869 So let's take one char off paramName and see if we're
2870 pointing at an alpha-numeric char. However if *pArg is
2871 0xffff or 0xfffe then the param has no name, the former
2872 meaning that the next WORD is the type, the latter
2873 meaning the the next WORD is an offset to the type. */
2875 HaveOffs = FALSE;
2876 if(*pArg == 0xffff)
2877 paramName = NULL;
2878 else if(*pArg == 0xfffe) {
2879 paramName = NULL;
2880 HaveOffs = TRUE;
2882 else if(!isalnum(*(paramName-1)))
2883 HaveOffs = TRUE;
2885 pArg++;
2887 if(HaveOffs) { /* the next word is an offset to type */
2888 pType = (WORD*)(pFirstItem + *pArg);
2889 SLTG_DoType(pType, pFirstItem,
2890 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2891 pArg++;
2892 } else {
2893 if(paramName)
2894 paramName--;
2895 pArg = SLTG_DoType(pArg, pFirstItem,
2896 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2899 /* Are we an optional param ? */
2900 if((*ppFuncDesc)->funcdesc.cParams - param <=
2901 (*ppFuncDesc)->funcdesc.cParamsOpt)
2902 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2904 if(paramName) {
2905 (*ppFuncDesc)->pParamDesc[param].Name =
2906 TLB_MultiByteToBSTR(paramName);
2910 ppFuncDesc = &((*ppFuncDesc)->next);
2911 if(pFunc->next == 0xffff) break;
2913 pTI->TypeAttr.cFuncs = num;
2914 dump_TLBFuncDesc(pTI->funclist);
2915 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2918 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2919 char *pNameTable)
2921 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2922 SLTG_MemberHeader *pMemHeader;
2923 SLTG_RecordItem *pItem;
2924 char *pFirstItem;
2925 TLBVarDesc **ppVarDesc = &pTI->varlist;
2926 int num = 0;
2927 WORD *pType;
2928 char buf[300];
2930 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2932 pFirstItem = (char*)(pMemHeader + 1);
2933 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2934 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2935 if(pItem->magic != SLTG_RECORD_MAGIC) {
2936 FIXME("record magic = %02x\n", pItem->magic);
2937 return NULL;
2939 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2940 sizeof(**ppVarDesc));
2941 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2942 (*ppVarDesc)->vardesc.memid = pItem->memid;
2943 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2944 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2946 if(pItem->typepos == 0x02)
2947 pType = &pItem->type;
2948 else if(pItem->typepos == 0x00)
2949 pType = (WORD*)(pFirstItem + pItem->type);
2950 else {
2951 FIXME("typepos = %02x\n", pItem->typepos);
2952 break;
2955 SLTG_DoType(pType, pFirstItem,
2956 &(*ppVarDesc)->vardesc.elemdescVar);
2958 /* FIXME("helpcontext, helpstring\n"); */
2960 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2962 ppVarDesc = &((*ppVarDesc)->next);
2963 if(pItem->next == 0xffff) break;
2965 pTI->TypeAttr.cVars = num;
2966 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2969 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2970 char *pNameTable)
2972 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2973 SLTG_MemberHeader *pMemHeader;
2974 SLTG_AliasItem *pItem;
2975 int i, mustbelast;
2977 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2978 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2980 mustbelast = 0;
2981 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2982 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2983 if (pItem->vt == 0xffff) {
2984 if (i<(pMemHeader->cbExtra/4-1))
2985 FIXME("Endmarker too early in process alias data!\n");
2986 break;
2988 if (mustbelast) {
2989 FIXME("Chain extends over last entry?\n");
2990 break;
2992 if (pItem->vt == VT_USERDEFINED) {
2993 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2994 /* guessing here ... */
2995 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2996 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2997 mustbelast = 1;
2998 } else {
2999 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3000 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3002 pItem++;
3004 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3007 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3008 char *pNameTable)
3010 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3011 SLTG_MemberHeader *pMemHeader;
3012 SLTG_AliasItem *pItem;
3014 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3015 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3016 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3017 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3018 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3021 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3022 char *pNameTable)
3024 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3025 SLTG_MemberHeader *pMemHeader;
3026 SLTG_EnumItem *pItem;
3027 char *pFirstItem;
3028 TLBVarDesc **ppVarDesc = &pTI->varlist;
3029 int num = 0;
3031 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3033 pFirstItem = (char*)(pMemHeader + 1);
3034 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3035 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3036 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3037 FIXME("enumitem magic = %04x\n", pItem->magic);
3038 return NULL;
3040 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3041 sizeof(**ppVarDesc));
3042 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3043 (*ppVarDesc)->vardesc.memid = pItem->memid;
3044 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3045 sizeof(VARIANT));
3046 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3047 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3048 *(INT*)(pItem->value + pFirstItem);
3049 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3050 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3051 /* FIXME("helpcontext, helpstring\n"); */
3053 ppVarDesc = &((*ppVarDesc)->next);
3054 if(pItem->next == 0xffff) break;
3056 pTI->TypeAttr.cVars = num;
3057 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3060 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
3061 managable copy of it into this */
3062 typedef struct {
3063 WORD small_no;
3064 char *index_name;
3065 char *other_name;
3066 WORD res1a;
3067 WORD name_offs;
3068 WORD more_bytes;
3069 char *extra;
3070 WORD res20;
3071 DWORD helpcontext;
3072 WORD res26;
3073 GUID uuid;
3074 } SLTG_InternalOtherTypeInfo;
3076 /****************************************************************************
3077 * ITypeLib2_Constructor_SLTG
3079 * loading a SLTG typelib from an in-memory image
3081 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3083 ITypeLibImpl *pTypeLibImpl;
3084 SLTG_Header *pHeader;
3085 SLTG_BlkEntry *pBlkEntry;
3086 SLTG_Magic *pMagic;
3087 SLTG_Index *pIndex;
3088 SLTG_Pad9 *pPad9;
3089 LPVOID pBlk, pFirstBlk;
3090 SLTG_LibBlk *pLibBlk;
3091 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3092 char *pAfterOTIBlks = NULL;
3093 char *pNameTable, *ptr;
3094 int i;
3095 DWORD len, order;
3096 ITypeInfoImpl **ppTypeInfoImpl;
3098 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3100 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3101 if (!pTypeLibImpl) return NULL;
3103 pTypeLibImpl->lpVtbl = &tlbvt;
3104 pTypeLibImpl->ref = 1;
3106 pHeader = pLib;
3108 TRACE("header:\n");
3109 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3110 pHeader->nrOfFileBlks );
3111 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3112 FIXME("Header type magic 0x%08lx not supported.\n",
3113 pHeader->SLTG_magic);
3114 return NULL;
3117 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3118 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3120 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3121 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3123 /* Next we have a magic block */
3124 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3126 /* Let's see if we're still in sync */
3127 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3128 sizeof(SLTG_COMPOBJ_MAGIC))) {
3129 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3130 return NULL;
3132 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3133 sizeof(SLTG_DIR_MAGIC))) {
3134 FIXME("dir magic = %s\n", pMagic->dir_magic);
3135 return NULL;
3138 pIndex = (SLTG_Index*)(pMagic+1);
3140 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3142 pFirstBlk = (LPVOID)(pPad9 + 1);
3144 /* We'll set up a ptr to the main library block, which is the last one. */
3146 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3147 pBlkEntry[order].next != 0;
3148 order = pBlkEntry[order].next - 1, i++) {
3149 pBlk = (char*)pBlk + pBlkEntry[order].len;
3151 pLibBlk = pBlk;
3153 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3155 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3156 interspersed */
3158 len += 0x40;
3160 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3162 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3163 sizeof(*pOtherTypeInfoBlks) *
3164 pTypeLibImpl->TypeInfoCount);
3167 ptr = (char*)pLibBlk + len;
3169 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3170 WORD w, extra;
3171 len = 0;
3173 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3175 w = *(WORD*)(ptr + 2);
3176 if(w != 0xffff) {
3177 len += w;
3178 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3179 w+1);
3180 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3181 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3183 w = *(WORD*)(ptr + 4 + len);
3184 if(w != 0xffff) {
3185 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3186 len += w;
3187 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3188 w+1);
3189 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3190 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3192 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3193 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3194 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3195 if(extra) {
3196 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3197 extra);
3198 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3199 len += extra;
3201 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3202 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3203 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3204 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3205 len += sizeof(SLTG_OtherTypeInfo);
3206 ptr += len;
3209 pAfterOTIBlks = ptr;
3211 /* Skip this WORD and get the next DWORD */
3212 len = *(DWORD*)(pAfterOTIBlks + 2);
3214 /* Now add this to pLibBLk look at what we're pointing at and
3215 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3216 dust and we should be pointing at the beginning of the name
3217 table */
3219 pNameTable = (char*)pLibBlk + len;
3221 switch(*(WORD*)pNameTable) {
3222 case 0xffff:
3223 break;
3224 case 0x0200:
3225 pNameTable += 0x20;
3226 break;
3227 default:
3228 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3229 break;
3232 pNameTable += 0x216;
3234 pNameTable += 2;
3236 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3238 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3241 /* Hopefully we now have enough ptrs set up to actually read in
3242 some TypeInfos. It's not clear which order to do them in, so
3243 I'll just follow the links along the BlkEntry chain and read
3244 them in in the order in which they're in the file */
3246 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3248 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3249 pBlkEntry[order].next != 0;
3250 order = pBlkEntry[order].next - 1, i++) {
3252 SLTG_TypeInfoHeader *pTIHeader;
3253 SLTG_TypeInfoTail *pTITail;
3255 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3256 pOtherTypeInfoBlks[i].index_name)) {
3257 FIXME("Index strings don't match\n");
3258 return NULL;
3261 pTIHeader = pBlk;
3262 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3263 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3264 return NULL;
3266 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3267 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3268 (*ppTypeInfoImpl)->index = i;
3269 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3270 pOtherTypeInfoBlks[i].name_offs +
3271 pNameTable);
3272 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3273 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3274 sizeof(GUID));
3275 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3276 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3277 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3278 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3279 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3281 if((pTIHeader->typeflags1 & 7) != 2)
3282 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3283 if(pTIHeader->typeflags3 != 2)
3284 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3286 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3287 debugstr_w((*ppTypeInfoImpl)->Name),
3288 typekind_desc[pTIHeader->typekind],
3289 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3290 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3292 switch(pTIHeader->typekind) {
3293 case TKIND_ENUM:
3294 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3295 break;
3297 case TKIND_RECORD:
3298 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3299 break;
3301 case TKIND_INTERFACE:
3302 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3303 break;
3305 case TKIND_COCLASS:
3306 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3307 break;
3309 case TKIND_ALIAS:
3310 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3311 if (pTITail->tdescalias_vt)
3312 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3313 break;
3315 case TKIND_DISPATCH:
3316 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3317 break;
3319 default:
3320 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3321 pTITail = NULL;
3322 break;
3326 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3327 but we've already set those */
3328 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3329 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3330 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3332 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3333 X(06);
3334 X(08);
3335 X(0a);
3336 X(0c);
3337 X(0e);
3338 X(10);
3339 X(12);
3340 X(16);
3341 X(18);
3342 X(1a);
3343 X(1c);
3344 X(1e);
3345 X(24);
3346 X(26);
3347 X(2a);
3348 X(2c);
3349 X(2e);
3350 X(30);
3351 X(32);
3352 X(34);
3354 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3355 pBlk = (char*)pBlk + pBlkEntry[order].len;
3358 if(i != pTypeLibImpl->TypeInfoCount) {
3359 FIXME("Somehow processed %d TypeInfos\n", i);
3360 return NULL;
3363 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3364 return (ITypeLib2*)pTypeLibImpl;
3367 /* ITypeLib::QueryInterface
3369 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3370 ITypeLib2 * iface,
3371 REFIID riid,
3372 VOID **ppvObject)
3374 ICOM_THIS( ITypeLibImpl, iface);
3376 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3378 *ppvObject=NULL;
3379 if(IsEqualIID(riid, &IID_IUnknown) ||
3380 IsEqualIID(riid,&IID_ITypeLib)||
3381 IsEqualIID(riid,&IID_ITypeLib2))
3383 *ppvObject = This;
3386 if(*ppvObject)
3388 ITypeLib2_AddRef(iface);
3389 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3390 return S_OK;
3392 TRACE("-- Interface: E_NOINTERFACE\n");
3393 return E_NOINTERFACE;
3396 /* ITypeLib::AddRef
3398 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3400 ICOM_THIS( ITypeLibImpl, iface);
3402 TRACE("(%p)->ref was %u\n",This, This->ref);
3404 return ++(This->ref);
3407 /* ITypeLib::Release
3409 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3411 ICOM_THIS( ITypeLibImpl, iface);
3413 --(This->ref);
3415 TRACE("(%p)->(%u)\n",This, This->ref);
3417 if (!This->ref)
3419 /* remove cache entry */
3420 TRACE("removing from cache list\n");
3421 EnterCriticalSection(&cache_section);
3422 if (This->next) This->next->prev = This->prev;
3423 if (This->prev) This->prev->next = This->next;
3424 else tlb_cache_first = This->next;
3425 LeaveCriticalSection(&cache_section);
3427 /* FIXME destroy child objects */
3428 TRACE(" destroying ITypeLib(%p)\n",This);
3430 if (This->Name)
3432 SysFreeString(This->Name);
3433 This->Name = NULL;
3436 if (This->DocString)
3438 SysFreeString(This->DocString);
3439 This->DocString = NULL;
3442 if (This->HelpFile)
3444 SysFreeString(This->HelpFile);
3445 This->HelpFile = NULL;
3448 if (This->HelpStringDll)
3450 SysFreeString(This->HelpStringDll);
3451 This->HelpStringDll = NULL;
3454 if (This->pTypeInfo) /* can be NULL */
3455 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3456 HeapFree(GetProcessHeap(),0,This);
3457 return 0;
3460 return This->ref;
3463 /* ITypeLib::GetTypeInfoCount
3465 * Returns the number of type descriptions in the type library
3467 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3469 ICOM_THIS( ITypeLibImpl, iface);
3470 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3471 return This->TypeInfoCount;
3474 /* ITypeLib::GetTypeInfo
3476 * retrieves the specified type description in the library.
3478 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3479 ITypeLib2 *iface,
3480 UINT index,
3481 ITypeInfo **ppTInfo)
3483 int i;
3485 ICOM_THIS( ITypeLibImpl, iface);
3486 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3488 TRACE("(%p)->(index=%d) \n", This, index);
3490 if (!ppTInfo) return E_INVALIDARG;
3492 /* search element n in list */
3493 for(i=0; i < index; i++)
3495 pTypeInfo = pTypeInfo->next;
3496 if (!pTypeInfo)
3498 TRACE("-- element not found\n");
3499 return TYPE_E_ELEMENTNOTFOUND;
3503 *ppTInfo = (ITypeInfo *) pTypeInfo;
3505 ITypeInfo_AddRef(*ppTInfo);
3506 TRACE("-- found (%p)\n",*ppTInfo);
3507 return S_OK;
3511 /* ITypeLibs::GetTypeInfoType
3513 * Retrieves the type of a type description.
3515 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3516 ITypeLib2 *iface,
3517 UINT index,
3518 TYPEKIND *pTKind)
3520 ICOM_THIS( ITypeLibImpl, iface);
3521 int i;
3522 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3524 TRACE("(%p) index %d \n",This, index);
3526 if(!pTKind) return E_INVALIDARG;
3528 /* search element n in list */
3529 for(i=0; i < index; i++)
3531 if(!pTInfo)
3533 TRACE("-- element not found\n");
3534 return TYPE_E_ELEMENTNOTFOUND;
3536 pTInfo = pTInfo->next;
3539 *pTKind = pTInfo->TypeAttr.typekind;
3540 TRACE("-- found Type (%d)\n", *pTKind);
3541 return S_OK;
3544 /* ITypeLib::GetTypeInfoOfGuid
3546 * Retrieves the type description that corresponds to the specified GUID.
3549 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3550 ITypeLib2 *iface,
3551 REFGUID guid,
3552 ITypeInfo **ppTInfo)
3554 ICOM_THIS( ITypeLibImpl, iface);
3555 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3557 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3559 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3561 /* search linked list for guid */
3562 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3564 pTypeInfo = pTypeInfo->next;
3566 if (!pTypeInfo)
3568 /* end of list reached */
3569 TRACE("-- element not found\n");
3570 return TYPE_E_ELEMENTNOTFOUND;
3574 TRACE("-- found (%p, %s)\n",
3575 pTypeInfo,
3576 debugstr_w(pTypeInfo->Name));
3578 *ppTInfo = (ITypeInfo*)pTypeInfo;
3579 ITypeInfo_AddRef(*ppTInfo);
3580 return S_OK;
3583 /* ITypeLib::GetLibAttr
3585 * Retrieves the structure that contains the library's attributes.
3588 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3589 ITypeLib2 *iface,
3590 LPTLIBATTR *ppTLibAttr)
3592 ICOM_THIS( ITypeLibImpl, iface);
3593 TRACE("(%p)\n",This);
3594 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3595 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3596 return S_OK;
3599 /* ITypeLib::GetTypeComp
3601 * Enables a client compiler to bind to a library's types, variables,
3602 * constants, and global functions.
3605 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3606 ITypeLib2 *iface,
3607 ITypeComp **ppTComp)
3609 ICOM_THIS( ITypeLibImpl, iface);
3611 TRACE("(%p)->(%p)\n",This,ppTComp);
3612 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3613 ITypeComp_AddRef(*ppTComp);
3615 return S_OK;
3618 /* ITypeLib::GetDocumentation
3620 * Retrieves the library's documentation string, the complete Help file name
3621 * and path, and the context identifier for the library Help topic in the Help
3622 * file.
3624 * On a successful return all non-null BSTR pointers will have been set,
3625 * possibly to NULL.
3627 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3628 ITypeLib2 *iface,
3629 INT index,
3630 BSTR *pBstrName,
3631 BSTR *pBstrDocString,
3632 DWORD *pdwHelpContext,
3633 BSTR *pBstrHelpFile)
3635 ICOM_THIS( ITypeLibImpl, iface);
3637 HRESULT result = E_INVALIDARG;
3639 ITypeInfo *pTInfo;
3642 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3643 This, index,
3644 pBstrName, pBstrDocString,
3645 pdwHelpContext, pBstrHelpFile);
3647 if(index<0)
3649 /* documentation for the typelib */
3650 if(pBstrName)
3652 if (This->Name)
3653 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3654 else
3655 *pBstrName = NULL;
3657 if(pBstrDocString)
3659 if (This->DocString)
3660 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3661 else if (This->Name)
3662 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3663 else
3664 *pBstrDocString = NULL;
3666 if(pdwHelpContext)
3668 *pdwHelpContext = This->dwHelpContext;
3670 if(pBstrHelpFile)
3672 if (This->HelpFile)
3673 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3674 else
3675 *pBstrHelpFile = NULL;
3678 result = S_OK;
3680 else
3682 /* for a typeinfo */
3683 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3685 if(SUCCEEDED(result))
3687 result = ITypeInfo_GetDocumentation(pTInfo,
3688 MEMBERID_NIL,
3689 pBstrName,
3690 pBstrDocString,
3691 pdwHelpContext, pBstrHelpFile);
3693 ITypeInfo_Release(pTInfo);
3696 return result;
3697 memerr3:
3698 if (pBstrDocString) SysFreeString (*pBstrDocString);
3699 memerr2:
3700 if (pBstrName) SysFreeString (*pBstrName);
3701 memerr1:
3702 return STG_E_INSUFFICIENTMEMORY;
3705 /* ITypeLib::IsName
3707 * Indicates whether a passed-in string contains the name of a type or member
3708 * described in the library.
3711 static HRESULT WINAPI ITypeLib2_fnIsName(
3712 ITypeLib2 *iface,
3713 LPOLESTR szNameBuf,
3714 ULONG lHashVal,
3715 BOOL *pfName)
3717 ICOM_THIS( ITypeLibImpl, iface);
3718 ITypeInfoImpl *pTInfo;
3719 TLBFuncDesc *pFInfo;
3720 TLBVarDesc *pVInfo;
3721 int i;
3722 UINT nNameBufLen = SysStringLen(szNameBuf);
3724 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3725 pfName);
3727 *pfName=TRUE;
3728 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3729 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3730 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3731 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3732 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3733 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3734 goto ITypeLib2_fnIsName_exit;
3736 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3737 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3740 *pfName=FALSE;
3742 ITypeLib2_fnIsName_exit:
3743 TRACE("(%p)slow! search for %s: %s found!\n", This,
3744 debugstr_w(szNameBuf), *pfName?"NOT":"");
3746 return S_OK;
3749 /* ITypeLib::FindName
3751 * Finds occurrences of a type description in a type library. This may be used
3752 * to quickly verify that a name exists in a type library.
3755 static HRESULT WINAPI ITypeLib2_fnFindName(
3756 ITypeLib2 *iface,
3757 LPOLESTR szNameBuf,
3758 ULONG lHashVal,
3759 ITypeInfo **ppTInfo,
3760 MEMBERID *rgMemId,
3761 UINT16 *pcFound)
3763 ICOM_THIS( ITypeLibImpl, iface);
3764 ITypeInfoImpl *pTInfo;
3765 TLBFuncDesc *pFInfo;
3766 TLBVarDesc *pVInfo;
3767 int i,j = 0;
3769 UINT nNameBufLen = SysStringLen(szNameBuf);
3771 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3772 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3773 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3774 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3775 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3776 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3777 goto ITypeLib2_fnFindName_exit;
3779 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3780 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3781 continue;
3782 ITypeLib2_fnFindName_exit:
3783 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3784 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3785 j++;
3787 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3788 This, *pcFound, debugstr_w(szNameBuf), j);
3790 *pcFound=j;
3792 return S_OK;
3795 /* ITypeLib::ReleaseTLibAttr
3797 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3800 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3801 ITypeLib2 *iface,
3802 TLIBATTR *pTLibAttr)
3804 ICOM_THIS( ITypeLibImpl, iface);
3805 TRACE("freeing (%p)\n",This);
3806 HeapFree(GetProcessHeap(),0,pTLibAttr);
3810 /* ITypeLib2::GetCustData
3812 * gets the custom data
3814 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3815 ITypeLib2 * iface,
3816 REFGUID guid,
3817 VARIANT *pVarVal)
3819 ICOM_THIS( ITypeLibImpl, iface);
3820 TLBCustData *pCData;
3822 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3824 if( IsEqualIID(guid, &pCData->guid)) break;
3827 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3829 if(pCData)
3831 VariantInit( pVarVal);
3832 VariantCopy( pVarVal, &pCData->data);
3833 return S_OK;
3835 return E_INVALIDARG; /* FIXME: correct? */
3838 /* ITypeLib2::GetLibStatistics
3840 * Returns statistics about a type library that are required for efficient
3841 * sizing of hash tables.
3844 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3845 ITypeLib2 * iface,
3846 ULONG *pcUniqueNames,
3847 ULONG *pcchUniqueNames)
3849 ICOM_THIS( ITypeLibImpl, iface);
3851 FIXME("(%p): stub!\n", This);
3853 if(pcUniqueNames) *pcUniqueNames=1;
3854 if(pcchUniqueNames) *pcchUniqueNames=1;
3855 return S_OK;
3858 /* ITypeLib2::GetDocumentation2
3860 * Retrieves the library's documentation string, the complete Help file name
3861 * and path, the localization context to use, and the context ID for the
3862 * library Help topic in the Help file.
3865 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3866 ITypeLib2 * iface,
3867 INT index,
3868 LCID lcid,
3869 BSTR *pbstrHelpString,
3870 DWORD *pdwHelpStringContext,
3871 BSTR *pbstrHelpStringDll)
3873 ICOM_THIS( ITypeLibImpl, iface);
3874 HRESULT result;
3875 ITypeInfo *pTInfo;
3877 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3879 /* the help string should be obtained from the helpstringdll,
3880 * using the _DLLGetDocumentation function, based on the supplied
3881 * lcid. Nice to do sometime...
3883 if(index<0)
3885 /* documentation for the typelib */
3886 if(pbstrHelpString)
3887 *pbstrHelpString=SysAllocString(This->DocString);
3888 if(pdwHelpStringContext)
3889 *pdwHelpStringContext=This->dwHelpContext;
3890 if(pbstrHelpStringDll)
3891 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3893 result = S_OK;
3895 else
3897 /* for a typeinfo */
3898 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3900 if(SUCCEEDED(result))
3902 ITypeInfo2 * pTInfo2;
3903 result = ITypeInfo_QueryInterface(pTInfo,
3904 &IID_ITypeInfo2,
3905 (LPVOID*) &pTInfo2);
3907 if(SUCCEEDED(result))
3909 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3910 MEMBERID_NIL,
3911 lcid,
3912 pbstrHelpString,
3913 pdwHelpStringContext,
3914 pbstrHelpStringDll);
3916 ITypeInfo2_Release(pTInfo2);
3919 ITypeInfo_Release(pTInfo);
3922 return result;
3925 /* ITypeLib2::GetAllCustData
3927 * Gets all custom data items for the library.
3930 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3931 ITypeLib2 * iface,
3932 CUSTDATA *pCustData)
3934 ICOM_THIS( ITypeLibImpl, iface);
3935 TLBCustData *pCData;
3936 int i;
3937 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3938 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3939 if(pCustData->prgCustData ){
3940 pCustData->cCustData=This->ctCustData;
3941 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3942 pCustData->prgCustData[i].guid=pCData->guid;
3943 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3945 }else{
3946 ERR(" OUT OF MEMORY! \n");
3947 return E_OUTOFMEMORY;
3949 return S_OK;
3952 static ITypeLib2Vtbl tlbvt = {
3953 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3954 ITypeLib2_fnQueryInterface,
3955 ITypeLib2_fnAddRef,
3956 ITypeLib2_fnRelease,
3957 ITypeLib2_fnGetTypeInfoCount,
3958 ITypeLib2_fnGetTypeInfo,
3959 ITypeLib2_fnGetTypeInfoType,
3960 ITypeLib2_fnGetTypeInfoOfGuid,
3961 ITypeLib2_fnGetLibAttr,
3962 ITypeLib2_fnGetTypeComp,
3963 ITypeLib2_fnGetDocumentation,
3964 ITypeLib2_fnIsName,
3965 ITypeLib2_fnFindName,
3966 ITypeLib2_fnReleaseTLibAttr,
3968 ITypeLib2_fnGetCustData,
3969 ITypeLib2_fnGetLibStatistics,
3970 ITypeLib2_fnGetDocumentation2,
3971 ITypeLib2_fnGetAllCustData
3975 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
3977 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3979 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
3982 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
3984 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3986 return ITypeInfo_AddRef((ITypeInfo *)This);
3989 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
3991 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3993 return ITypeInfo_Release((ITypeInfo *)This);
3996 static HRESULT WINAPI ITypeLibComp_fnBind(
3997 ITypeComp * iface,
3998 OLECHAR * szName,
3999 unsigned long lHash,
4000 unsigned short wFlags,
4001 ITypeInfo ** ppTInfo,
4002 DESCKIND * pDescKind,
4003 BINDPTR * pBindPtr)
4005 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4006 return E_NOTIMPL;
4009 static HRESULT WINAPI ITypeLibComp_fnBindType(
4010 ITypeComp * iface,
4011 OLECHAR * szName,
4012 unsigned long lHash,
4013 ITypeInfo ** ppTInfo,
4014 ITypeComp ** ppTComp)
4016 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4017 return E_NOTIMPL;
4020 static ITypeCompVtbl tlbtcvt =
4022 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4024 ITypeLibComp_fnQueryInterface,
4025 ITypeLibComp_fnAddRef,
4026 ITypeLibComp_fnRelease,
4028 ITypeLibComp_fnBind,
4029 ITypeLibComp_fnBindType
4032 /*================== ITypeInfo(2) Methods ===================================*/
4033 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4035 ITypeInfoImpl * pTypeInfoImpl;
4037 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4038 if (pTypeInfoImpl)
4040 pTypeInfoImpl->lpVtbl = &tinfvt;
4041 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4042 pTypeInfoImpl->ref=1;
4044 TRACE("(%p)\n", pTypeInfoImpl);
4045 return (ITypeInfo2*) pTypeInfoImpl;
4048 /* ITypeInfo::QueryInterface
4050 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4051 ITypeInfo2 *iface,
4052 REFIID riid,
4053 VOID **ppvObject)
4055 ICOM_THIS( ITypeLibImpl, iface);
4057 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4059 *ppvObject=NULL;
4060 if(IsEqualIID(riid, &IID_IUnknown) ||
4061 IsEqualIID(riid,&IID_ITypeInfo)||
4062 IsEqualIID(riid,&IID_ITypeInfo2))
4063 *ppvObject = This;
4065 if(*ppvObject){
4066 ITypeInfo_AddRef(iface);
4067 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4068 return S_OK;
4070 TRACE("-- Interface: E_NOINTERFACE\n");
4071 return E_NOINTERFACE;
4074 /* ITypeInfo::AddRef
4076 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4078 ICOM_THIS( ITypeInfoImpl, iface);
4080 ++(This->ref);
4081 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4083 TRACE("(%p)->ref is %u\n",This, This->ref);
4084 return This->ref;
4087 /* ITypeInfo::Release
4089 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4091 ICOM_THIS( ITypeInfoImpl, iface);
4093 --(This->ref);
4095 TRACE("(%p)->(%u)\n",This, This->ref);
4097 if (This->ref) {
4098 /* We don't release ITypeLib when ref=0 becouse
4099 it means that funtion is called by ITypeLi2_Release */
4100 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4101 } else {
4102 FIXME("destroy child objects\n");
4104 TRACE("destroying ITypeInfo(%p)\n",This);
4105 if (This->Name)
4107 SysFreeString(This->Name);
4108 This->Name = 0;
4111 if (This->DocString)
4113 SysFreeString(This->DocString);
4114 This->DocString = 0;
4117 if (This->next)
4119 ITypeInfo_Release((ITypeInfo*)This->next);
4122 HeapFree(GetProcessHeap(),0,This);
4123 return 0;
4125 return This->ref;
4128 /* ITypeInfo::GetTypeAttr
4130 * Retrieves a TYPEATTR structure that contains the attributes of the type
4131 * description.
4134 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4135 LPTYPEATTR *ppTypeAttr)
4137 ICOM_THIS( ITypeInfoImpl, iface);
4138 TRACE("(%p)\n",This);
4139 /* FIXME: must do a copy here */
4140 *ppTypeAttr=&This->TypeAttr;
4141 return S_OK;
4144 /* ITypeInfo::GetTypeComp
4146 * Retrieves the ITypeComp interface for the type description, which enables a
4147 * client compiler to bind to the type description's members.
4150 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4151 ITypeComp * *ppTComp)
4153 ICOM_THIS( ITypeInfoImpl, iface);
4155 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4157 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4158 ITypeComp_AddRef(*ppTComp);
4159 return S_OK;
4162 /* ITypeInfo::GetFuncDesc
4164 * Retrieves the FUNCDESC structure that contains information about a
4165 * specified function.
4168 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4169 LPFUNCDESC *ppFuncDesc)
4171 ICOM_THIS( ITypeInfoImpl, iface);
4172 int i;
4173 TLBFuncDesc * pFDesc;
4174 TRACE("(%p) index %d\n", This, index);
4175 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4177 if(pFDesc){
4178 /* FIXME: must do a copy here */
4179 *ppFuncDesc=&pFDesc->funcdesc;
4180 return S_OK;
4182 return E_INVALIDARG;
4185 /* ITypeInfo::GetVarDesc
4187 * Retrieves a VARDESC structure that describes the specified variable.
4190 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4191 LPVARDESC *ppVarDesc)
4193 ICOM_THIS( ITypeInfoImpl, iface);
4194 int i;
4195 TLBVarDesc * pVDesc;
4196 TRACE("(%p) index %d\n", This, index);
4197 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4199 if(pVDesc){
4200 /* FIXME: must do a copy here */
4201 *ppVarDesc=&pVDesc->vardesc;
4202 return S_OK;
4204 return E_INVALIDARG;
4207 /* ITypeInfo_GetNames
4209 * Retrieves the variable with the specified member ID (or the name of the
4210 * property or method and its parameters) that correspond to the specified
4211 * function ID.
4213 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4214 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4216 ICOM_THIS( ITypeInfoImpl, iface);
4217 TLBFuncDesc * pFDesc;
4218 TLBVarDesc * pVDesc;
4219 int i;
4220 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4221 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4222 if(pFDesc)
4224 /* function found, now return function and parameter names */
4225 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4227 if(!i)
4228 *rgBstrNames=SysAllocString(pFDesc->Name);
4229 else
4230 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4232 *pcNames=i;
4234 else
4236 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4237 if(pVDesc)
4239 *rgBstrNames=SysAllocString(pVDesc->Name);
4240 *pcNames=1;
4242 else
4244 if(This->TypeAttr.cImplTypes &&
4245 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4246 /* recursive search */
4247 ITypeInfo *pTInfo;
4248 HRESULT result;
4249 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4250 &pTInfo);
4251 if(SUCCEEDED(result))
4253 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4254 ITypeInfo_Release(pTInfo);
4255 return result;
4257 WARN("Could not search inherited interface!\n");
4259 else
4261 WARN("no names found\n");
4263 *pcNames=0;
4264 return TYPE_E_ELEMENTNOTFOUND;
4267 return S_OK;
4271 /* ITypeInfo::GetRefTypeOfImplType
4273 * If a type description describes a COM class, it retrieves the type
4274 * description of the implemented interface types. For an interface,
4275 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4276 * if any exist.
4279 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4280 ITypeInfo2 *iface,
4281 UINT index,
4282 HREFTYPE *pRefType)
4284 ICOM_THIS( ITypeInfoImpl, iface);
4285 int(i);
4286 TLBImplType *pImpl = This->impltypelist;
4288 TRACE("(%p) index %d\n", This, index);
4289 if (TRACE_ON(ole)) dump_TypeInfo(This);
4291 if(index==(UINT)-1)
4293 /* only valid on dual interfaces;
4294 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4296 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4298 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4299 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4301 *pRefType = -1;
4303 else
4305 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4306 *pRefType = pImpl->hRef;
4309 else
4311 /* get element n from linked list */
4312 for(i=0; pImpl && i<index; i++)
4314 pImpl = pImpl->next;
4317 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4319 *pRefType = pImpl->hRef;
4321 TRACE("-- 0x%08lx\n", pImpl->hRef );
4324 return S_OK;
4328 /* ITypeInfo::GetImplTypeFlags
4330 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4331 * or base interface in a type description.
4333 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4334 UINT index, INT *pImplTypeFlags)
4336 ICOM_THIS( ITypeInfoImpl, iface);
4337 int i;
4338 TLBImplType *pImpl;
4340 TRACE("(%p) index %d\n", This, index);
4341 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4342 i++, pImpl=pImpl->next)
4344 if(i==index && pImpl){
4345 *pImplTypeFlags=pImpl->implflags;
4346 return S_OK;
4348 *pImplTypeFlags=0;
4349 return TYPE_E_ELEMENTNOTFOUND;
4352 /* GetIDsOfNames
4353 * Maps between member names and member IDs, and parameter names and
4354 * parameter IDs.
4356 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4357 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4359 ICOM_THIS( ITypeInfoImpl, iface);
4360 TLBFuncDesc * pFDesc;
4361 TLBVarDesc * pVDesc;
4362 HRESULT ret=S_OK;
4364 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4365 cNames);
4366 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4367 int i, j;
4368 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4369 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4370 for(i=1; i < cNames; i++){
4371 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4372 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4373 break;
4374 if( j<pFDesc->funcdesc.cParams)
4375 pMemId[i]=j;
4376 else
4377 ret=DISP_E_UNKNOWNNAME;
4379 return ret;
4382 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4383 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4384 if(cNames) *pMemId=pVDesc->vardesc.memid;
4385 return ret;
4388 /* not found, see if this is and interface with an inheritance */
4389 if(This->TypeAttr.cImplTypes &&
4390 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4391 /* recursive search */
4392 ITypeInfo *pTInfo;
4393 ret=ITypeInfo_GetRefTypeInfo(iface,
4394 This->impltypelist->hRef, &pTInfo);
4395 if(SUCCEEDED(ret)){
4396 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4397 ITypeInfo_Release(pTInfo);
4398 return ret;
4400 WARN("Could not search inherited interface!\n");
4401 } else
4402 WARN("no names found\n");
4403 return DISP_E_UNKNOWNNAME;
4406 /* ITypeInfo::Invoke
4408 * Invokes a method, or accesses a property of an object, that implements the
4409 * interface described by the type description.
4411 DWORD
4412 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4413 DWORD res;
4415 if (TRACE_ON(ole)) {
4416 int i;
4417 TRACE("Calling %p(",func);
4418 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4419 TRACE(")\n");
4422 switch (callconv) {
4423 case CC_STDCALL:
4425 switch (nrargs) {
4426 case 0:
4427 res = func();
4428 break;
4429 case 1:
4430 res = func(args[0]);
4431 break;
4432 case 2:
4433 res = func(args[0],args[1]);
4434 break;
4435 case 3:
4436 res = func(args[0],args[1],args[2]);
4437 break;
4438 case 4:
4439 res = func(args[0],args[1],args[2],args[3]);
4440 break;
4441 case 5:
4442 res = func(args[0],args[1],args[2],args[3],args[4]);
4443 break;
4444 case 6:
4445 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4446 break;
4447 case 7:
4448 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4449 break;
4450 case 8:
4451 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4452 break;
4453 case 9:
4454 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4455 break;
4456 case 10:
4457 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4458 break;
4459 case 11:
4460 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4461 break;
4462 default:
4463 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4464 res = -1;
4465 break;
4467 break;
4468 default:
4469 FIXME("unsupported calling convention %d\n",callconv);
4470 res = -1;
4471 break;
4473 TRACE("returns %08lx\n",res);
4474 return res;
4477 extern int const _argsize(DWORD vt);
4479 /****************************************************************************
4480 * Helper functions for Dispcall / Invoke, which copies one variant
4481 * with target type onto the argument stack.
4483 static HRESULT
4484 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4485 DWORD *argpos, VARIANT *arg, VARTYPE vt
4487 UINT arglen = _argsize(vt)*sizeof(DWORD);
4488 VARTYPE oldvt;
4489 VARIANT va;
4491 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4492 memcpy(argpos,&arg,sizeof(void*));
4493 return S_OK;
4496 if (V_VT(arg) == vt) {
4497 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4498 return S_OK;
4501 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4502 memcpy(argpos, &V_UNION(arg,parray), sizeof(SAFEARRAY*));
4503 return S_OK;
4506 if (vt == VT_VARIANT) {
4507 memcpy(argpos, arg, arglen);
4508 return S_OK;
4510 /* Deref BYREF vars if there is need */
4511 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4512 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4513 return S_OK;
4515 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4516 /* in this context, if the type lib specifies IUnknown*, giving an
4517 IDispatch* is correct; so, don't invoke VariantChangeType */
4518 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4519 return S_OK;
4521 if ((vt == VT_PTR) && tdesc)
4522 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4524 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4525 ITypeInfo *tinfo2 = NULL;
4526 TYPEATTR *tattr = NULL;
4527 HRESULT hres;
4529 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4530 if (hres) {
4531 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4532 "while coercing from vt 0x%x. Copying 4 byte.\n",
4533 tdesc->u.hreftype,V_VT(arg));
4534 memcpy(argpos, &V_UNION(arg,lVal), 4);
4535 return S_OK;
4537 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4538 if( hres )
4540 ERR("GetTypeAttr failed\n");
4541 ITypeInfo_Release(tinfo2);
4542 return hres;
4544 switch (tattr->typekind) {
4545 case TKIND_ENUM:
4546 switch ( V_VT( arg ) ) {
4547 case VT_I2:
4548 *argpos = V_UNION(arg,iVal);
4549 hres = S_OK;
4550 break;
4551 case VT_I4:
4552 memcpy(argpos, &V_UNION(arg,lVal), 4);
4553 hres = S_OK;
4554 break;
4555 default:
4556 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4557 hres = E_FAIL;
4558 break;
4560 break;
4562 case TKIND_ALIAS:
4563 tdesc = &(tattr->tdescAlias);
4564 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4565 break;
4567 case TKIND_INTERFACE:
4568 if (V_VT(arg) == VT_DISPATCH) {
4569 IDispatch *disp;
4570 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4571 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4572 hres = S_OK;
4573 break;
4575 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),
4576 &IID_IDispatch,(LPVOID*)&disp);
4577 if (SUCCEEDED(hres)) {
4578 memcpy(argpos,&disp,4);
4579 IUnknown_Release(V_UNION(arg,pdispVal));
4580 hres = S_OK;
4581 break;
4583 FIXME("Failed to query IDispatch interface from %s while "
4584 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4585 hres = E_FAIL;
4586 break;
4588 if (V_VT(arg) == VT_UNKNOWN) {
4589 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4590 hres = S_OK;
4591 break;
4593 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4594 V_VT(arg),debugstr_guid(&(tattr->guid)));
4595 hres = E_FAIL;
4596 break;
4598 case TKIND_DISPATCH:
4599 if (V_VT(arg) == VT_DISPATCH) {
4600 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4601 hres = S_OK;
4603 else {
4604 hres = E_FAIL;
4605 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4607 break;
4608 case TKIND_RECORD:
4609 FIXME("TKIND_RECORD unhandled.\n");
4610 hres = E_FAIL;
4611 break;
4612 default:
4613 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4614 hres = E_FAIL;
4615 break;
4617 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4618 ITypeInfo_Release(tinfo2);
4619 return hres;
4622 oldvt = V_VT(arg);
4623 VariantInit(&va);
4624 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4625 memcpy(argpos,&V_UNION(&va,lVal), arglen);
4626 FIXME("Should not use VariantChangeType here."
4627 " (conversion from 0x%x -> 0x%x) %08lx\n",
4628 V_VT(arg), vt, *argpos
4630 return S_OK;
4632 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4633 return E_FAIL;
4636 /***********************************************************************
4637 * DispCallFunc (OLEAUT32.@)
4639 HRESULT WINAPI
4640 DispCallFunc(
4641 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4642 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4644 int i, argsize, argspos;
4645 DWORD *args;
4646 HRESULT hres;
4648 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4649 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4651 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4652 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4653 argsize = 1;
4654 for (i=0;i<cActuals;i++) {
4655 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4656 dump_Variant(prgpvarg[i]);
4657 argsize += _argsize(prgvt[i]);
4659 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4660 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4661 argspos = 1;
4662 for (i=0;i<cActuals;i++) {
4663 VARIANT *arg = prgpvarg[i];
4664 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4665 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4666 argspos += _argsize(prgvt[i]);
4669 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4671 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4672 hres=S_OK;
4674 else
4676 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4677 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4678 FIXME("Method returned %lx\n",hres);
4680 HeapFree(GetProcessHeap(),0,args);
4681 return hres;
4684 static HRESULT WINAPI ITypeInfo_fnInvoke(
4685 ITypeInfo2 *iface,
4686 VOID *pIUnk,
4687 MEMBERID memid,
4688 UINT16 dwFlags,
4689 DISPPARAMS *pDispParams,
4690 VARIANT *pVarResult,
4691 EXCEPINFO *pExcepInfo,
4692 UINT *pArgErr)
4694 ICOM_THIS( ITypeInfoImpl, iface);
4695 TLBFuncDesc * pFDesc;
4696 TLBVarDesc * pVDesc;
4697 int i;
4698 HRESULT hres;
4700 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4701 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4703 dump_DispParms(pDispParams);
4705 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4706 if (pFDesc->funcdesc.memid == memid) {
4707 if (pFDesc->funcdesc.invkind & dwFlags)
4708 break;
4711 if (pFDesc) {
4712 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4713 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4714 switch (pFDesc->funcdesc.funckind) {
4715 case FUNC_PUREVIRTUAL:
4716 case FUNC_VIRTUAL: {
4717 DWORD res;
4718 int numargs, numargs2, argspos, args2pos;
4719 DWORD *args , *args2;
4722 numargs = 1; numargs2 = 0;
4723 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4724 if (i<pDispParams->cArgs)
4725 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4726 else {
4727 numargs += 1; /* sizeof(lpvoid) */
4728 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4732 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4733 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4735 args[0] = (DWORD)pIUnk;
4736 argspos = 1; args2pos = 0;
4737 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4738 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4739 if (i<pDispParams->cArgs) {
4740 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4741 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4742 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4743 if (FAILED(hres)) return hres;
4744 argspos += arglen;
4745 } else {
4746 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4747 if (tdesc->vt != VT_PTR)
4748 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4749 /*FIXME: give pointers for the rest, so propertyget works*/
4750 args[argspos] = (DWORD)&args2[args2pos];
4752 /* If pointer to variant, pass reference it. */
4753 if ((tdesc->vt == VT_PTR) &&
4754 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4755 pVarResult
4757 args[argspos]= (DWORD)pVarResult;
4758 argspos += 1;
4759 args2pos += arglen;
4762 if (pFDesc->funcdesc.cParamsOpt)
4763 FIXME("Does not support optional parameters (%d)\n",
4764 pFDesc->funcdesc.cParamsOpt
4767 res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4],
4768 pFDesc->funcdesc.callconv,
4769 numargs,
4770 args
4772 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4773 args2pos = 0;
4774 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4775 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4776 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4777 TYPEDESC i4_tdesc;
4778 i4_tdesc.vt = VT_I4;
4780 /* If we are a pointer to a variant, we are done already */
4781 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4782 continue;
4784 VariantInit(pVarResult);
4785 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4787 if (tdesc->vt == VT_PTR)
4788 tdesc = tdesc->u.lptdesc;
4789 if (tdesc->vt == VT_USERDEFINED) {
4790 ITypeInfo *tinfo2;
4791 TYPEATTR *tattr;
4793 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4794 if (hres) {
4795 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4796 return E_FAIL;
4798 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4799 switch (tattr->typekind) {
4800 case TKIND_ENUM:
4801 /* force the return type to be VT_I4 */
4802 tdesc = &i4_tdesc;
4803 break;
4804 case TKIND_ALIAS:
4805 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4806 tdesc = &(tattr->tdescAlias);
4807 break;
4809 case TKIND_INTERFACE:
4810 FIXME("TKIND_INTERFACE unhandled.\n");
4811 break;
4812 case TKIND_DISPATCH:
4813 FIXME("TKIND_DISPATCH unhandled.\n");
4814 break;
4815 case TKIND_RECORD:
4816 FIXME("TKIND_RECORD unhandled.\n");
4817 break;
4818 default:
4819 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4820 break;
4822 ITypeInfo_Release(tinfo2);
4824 V_VT(pVarResult) = tdesc->vt;
4826 /* HACK: VB5 likes this.
4827 * I do not know why. There is 1 example in MSDN which uses
4828 * this which appears broken (mixes int vals and
4829 * IDispatch*.).
4831 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4832 V_VT(pVarResult) = VT_DISPATCH;
4833 TRACE("storing into variant:\n");
4834 dump_Variant(pVarResult);
4835 args2pos += arglen;
4838 HeapFree(GetProcessHeap(),0,args2);
4839 HeapFree(GetProcessHeap(),0,args);
4840 return S_OK;
4842 case FUNC_DISPATCH: {
4843 IDispatch *disp;
4844 HRESULT hr;
4846 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4847 if (hr) {
4848 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4849 return hr;
4851 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4852 hr = IDispatch_Invoke(
4853 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4854 pVarResult,pExcepInfo,pArgErr
4856 if (hr)
4857 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4858 IDispatch_Release(disp);
4859 return hr;
4861 default:
4862 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4863 return E_FAIL;
4865 } else {
4866 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4867 if (pVDesc->vardesc.memid == memid) {
4868 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4869 dump_TLBVarDesc(pVDesc);
4870 break;
4874 /* not found, look for it in inherited interfaces */
4875 if (This->TypeAttr.cImplTypes &&
4876 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4877 /* recursive search */
4878 ITypeInfo *pTInfo;
4879 HRESULT hr;
4880 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4881 if(SUCCEEDED(hr)){
4882 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4883 ITypeInfo_Release(pTInfo);
4884 return hr;
4886 WARN("Could not search inherited interface!\n");
4888 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4889 return DISP_E_MEMBERNOTFOUND;
4892 /* ITypeInfo::GetDocumentation
4894 * Retrieves the documentation string, the complete Help file name and path,
4895 * and the context ID for the Help topic for a specified type description.
4897 * (Can be tested by the Visual Basic Editor in Word for instance.)
4899 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4900 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4901 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4903 ICOM_THIS( ITypeInfoImpl, iface);
4904 TLBFuncDesc * pFDesc;
4905 TLBVarDesc * pVDesc;
4906 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4907 " HelpContext(%p) HelpFile(%p)\n",
4908 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4909 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4910 if(pBstrName)
4911 *pBstrName=SysAllocString(This->Name);
4912 if(pBstrDocString)
4913 *pBstrDocString=SysAllocString(This->DocString);
4914 if(pdwHelpContext)
4915 *pdwHelpContext=This->dwHelpContext;
4916 if(pBstrHelpFile)
4917 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4918 return S_OK;
4919 }else {/* for a member */
4920 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4921 if(pFDesc->funcdesc.memid==memid){
4922 if(pBstrName)
4923 *pBstrName = SysAllocString(pFDesc->Name);
4924 if(pBstrDocString)
4925 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4926 if(pdwHelpContext)
4927 *pdwHelpContext=pFDesc->helpcontext;
4928 return S_OK;
4930 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4931 if(pVDesc->vardesc.memid==memid){
4932 if(pBstrName)
4933 *pBstrName = SysAllocString(pVDesc->Name);
4934 if(pBstrDocString)
4935 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4936 if(pdwHelpContext)
4937 *pdwHelpContext=pVDesc->HelpContext;
4938 return S_OK;
4941 return TYPE_E_ELEMENTNOTFOUND;
4944 /* ITypeInfo::GetDllEntry
4946 * Retrieves a description or specification of an entry point for a function
4947 * in a DLL.
4949 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4950 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4951 WORD *pwOrdinal)
4953 ICOM_THIS( ITypeInfoImpl, iface);
4954 TLBFuncDesc *pFDesc;
4956 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4958 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4959 if(pFDesc->funcdesc.memid==memid){
4960 dump_TypeInfo(This);
4961 dump_TLBFuncDescOne(pFDesc);
4963 /* FIXME: This is wrong, but how do you find that out? */
4964 if (pBstrDllName) {
4965 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4966 *pBstrDllName = SysAllocString(oleaut32W);
4969 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4970 if (pBstrName)
4971 *pBstrName = SysAllocString(pFDesc->Entry);
4972 if (pwOrdinal)
4973 *pwOrdinal = -1;
4974 return S_OK;
4976 if (pBstrName)
4977 *pBstrName = NULL;
4978 if (pwOrdinal)
4979 *pwOrdinal = (DWORD)pFDesc->Entry;
4980 return S_OK;
4982 return E_FAIL;
4985 /* ITypeInfo::GetRefTypeInfo
4987 * If a type description references other type descriptions, it retrieves
4988 * the referenced type descriptions.
4990 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4991 ITypeInfo2 *iface,
4992 HREFTYPE hRefType,
4993 ITypeInfo **ppTInfo)
4995 ICOM_THIS( ITypeInfoImpl, iface);
4996 HRESULT result = E_FAIL;
4999 if (hRefType == -1 &&
5000 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5001 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5003 /* when we meet a DUAL dispinterface, we must create the interface
5004 * version of it.
5006 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5009 /* the interface version contains the same information as the dispinterface
5010 * copy the contents of the structs.
5012 *pTypeInfoImpl = *This;
5013 pTypeInfoImpl->ref = 1;
5015 /* change the type to interface */
5016 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5018 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5020 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5022 result = S_OK;
5024 } else {
5025 TLBRefType *pRefType;
5026 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5027 if(pRefType->reference == hRefType)
5028 break;
5030 if(!pRefType)
5031 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5032 if(pRefType && hRefType != -1) {
5033 ITypeLib *pTLib = NULL;
5035 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5036 int Index;
5037 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5038 } else {
5039 if(pRefType->pImpTLInfo->pImpTypeLib) {
5040 TRACE("typeinfo in imported typelib that is already loaded\n");
5041 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5042 ITypeLib2_AddRef((ITypeLib*) pTLib);
5043 result = S_OK;
5044 } else {
5045 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5046 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5047 pRefType->pImpTLInfo->wVersionMajor,
5048 pRefType->pImpTLInfo->wVersionMinor,
5049 pRefType->pImpTLInfo->lcid,
5050 &pTLib);
5052 if(!SUCCEEDED(result)) {
5053 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5054 result=LoadTypeLib(libnam, &pTLib);
5055 SysFreeString(libnam);
5057 if(SUCCEEDED(result)) {
5058 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5059 ITypeLib2_AddRef(pTLib);
5063 if(SUCCEEDED(result)) {
5064 if(pRefType->index == TLB_REF_USE_GUID)
5065 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5066 &pRefType->guid,
5067 ppTInfo);
5068 else
5069 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5070 ppTInfo);
5072 if (pTLib != NULL)
5073 ITypeLib2_Release(pTLib);
5077 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5078 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5079 return result;
5082 /* ITypeInfo::AddressOfMember
5084 * Retrieves the addresses of static functions or variables, such as those
5085 * defined in a DLL.
5087 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5088 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5090 ICOM_THIS( ITypeInfoImpl, iface);
5091 FIXME("(%p) stub!\n", This);
5092 return S_OK;
5095 /* ITypeInfo::CreateInstance
5097 * Creates a new instance of a type that describes a component object class
5098 * (coclass).
5100 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5101 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5103 ICOM_THIS( ITypeInfoImpl, iface);
5104 FIXME("(%p) stub!\n", This);
5105 return S_OK;
5108 /* ITypeInfo::GetMops
5110 * Retrieves marshalling information.
5112 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5113 BSTR *pBstrMops)
5115 ICOM_THIS( ITypeInfoImpl, iface);
5116 FIXME("(%p) stub!\n", This);
5117 return S_OK;
5120 /* ITypeInfo::GetContainingTypeLib
5122 * Retrieves the containing type library and the index of the type description
5123 * within that type library.
5125 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5126 ITypeLib * *ppTLib, UINT *pIndex)
5128 ICOM_THIS( ITypeInfoImpl, iface);
5130 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5131 if (pIndex) {
5132 *pIndex=This->index;
5133 TRACE("returning pIndex=%d\n", *pIndex);
5136 if (ppTLib) {
5137 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5138 ITypeLib2_AddRef(*ppTLib);
5139 TRACE("returning ppTLib=%p\n", *ppTLib);
5142 return S_OK;
5145 /* ITypeInfo::ReleaseTypeAttr
5147 * Releases a TYPEATTR previously returned by GetTypeAttr.
5150 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5151 TYPEATTR* pTypeAttr)
5153 ICOM_THIS( ITypeInfoImpl, iface);
5154 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5157 /* ITypeInfo::ReleaseFuncDesc
5159 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5161 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5162 ITypeInfo2 *iface,
5163 FUNCDESC *pFuncDesc)
5165 ICOM_THIS( ITypeInfoImpl, iface);
5166 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5169 /* ITypeInfo::ReleaseVarDesc
5171 * Releases a VARDESC previously returned by GetVarDesc.
5173 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5174 VARDESC *pVarDesc)
5176 ICOM_THIS( ITypeInfoImpl, iface);
5177 TRACE("(%p)->(%p)\n", This, pVarDesc);
5180 /* ITypeInfo2::GetTypeKind
5182 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5185 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5186 TYPEKIND *pTypeKind)
5188 ICOM_THIS( ITypeInfoImpl, iface);
5189 *pTypeKind=This->TypeAttr.typekind;
5190 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5191 return S_OK;
5194 /* ITypeInfo2::GetTypeFlags
5196 * Returns the type flags without any allocations. This returns a DWORD type
5197 * flag, which expands the type flags without growing the TYPEATTR (type
5198 * attribute).
5201 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5203 ICOM_THIS( ITypeInfoImpl, iface);
5204 *pTypeFlags=This->TypeAttr.wTypeFlags;
5205 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5206 return S_OK;
5209 /* ITypeInfo2::GetFuncIndexOfMemId
5210 * Binds to a specific member based on a known DISPID, where the member name
5211 * is not known (for example, when binding to a default member).
5214 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5215 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5217 ICOM_THIS( ITypeInfoImpl, iface);
5218 TLBFuncDesc *pFuncInfo;
5219 int i;
5220 HRESULT result;
5221 /* FIXME: should check for invKind??? */
5222 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
5223 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
5224 if(pFuncInfo){
5225 *pFuncIndex=i;
5226 result= S_OK;
5227 }else{
5228 *pFuncIndex=0;
5229 result=E_INVALIDARG;
5231 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5232 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
5233 return result;
5236 /* TypeInfo2::GetVarIndexOfMemId
5238 * Binds to a specific member based on a known DISPID, where the member name
5239 * is not known (for example, when binding to a default member).
5242 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5243 MEMBERID memid, UINT *pVarIndex)
5245 ICOM_THIS( ITypeInfoImpl, iface);
5246 TLBVarDesc *pVarInfo;
5247 int i;
5248 HRESULT result;
5249 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5250 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5252 if(pVarInfo){
5253 *pVarIndex=i;
5254 result= S_OK;
5255 }else{
5256 *pVarIndex=0;
5257 result=E_INVALIDARG;
5259 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5260 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
5261 return result;
5264 /* ITypeInfo2::GetCustData
5266 * Gets the custom data
5268 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5269 ITypeInfo2 * iface,
5270 REFGUID guid,
5271 VARIANT *pVarVal)
5273 ICOM_THIS( ITypeInfoImpl, iface);
5274 TLBCustData *pCData;
5276 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5277 if( IsEqualIID(guid, &pCData->guid)) break;
5279 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5281 if(pCData)
5283 VariantInit( pVarVal);
5284 VariantCopy( pVarVal, &pCData->data);
5285 return S_OK;
5287 return E_INVALIDARG; /* FIXME: correct? */
5290 /* ITypeInfo2::GetFuncCustData
5292 * Gets the custom data
5294 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5295 ITypeInfo2 * iface,
5296 UINT index,
5297 REFGUID guid,
5298 VARIANT *pVarVal)
5300 ICOM_THIS( ITypeInfoImpl, iface);
5301 TLBCustData *pCData=NULL;
5302 TLBFuncDesc * pFDesc;
5303 int i;
5304 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5305 pFDesc=pFDesc->next);
5307 if(pFDesc)
5308 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5309 if( IsEqualIID(guid, &pCData->guid)) break;
5311 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5313 if(pCData){
5314 VariantInit( pVarVal);
5315 VariantCopy( pVarVal, &pCData->data);
5316 return S_OK;
5318 return E_INVALIDARG; /* FIXME: correct? */
5321 /* ITypeInfo2::GetParamCustData
5323 * Gets the custom data
5325 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5326 ITypeInfo2 * iface,
5327 UINT indexFunc,
5328 UINT indexParam,
5329 REFGUID guid,
5330 VARIANT *pVarVal)
5332 ICOM_THIS( ITypeInfoImpl, iface);
5333 TLBCustData *pCData=NULL;
5334 TLBFuncDesc * pFDesc;
5335 int i;
5337 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5339 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5340 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5341 pCData = pCData->next)
5342 if( IsEqualIID(guid, &pCData->guid)) break;
5344 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5346 if(pCData)
5348 VariantInit( pVarVal);
5349 VariantCopy( pVarVal, &pCData->data);
5350 return S_OK;
5352 return E_INVALIDARG; /* FIXME: correct? */
5355 /* ITypeInfo2::GetVarCustData
5357 * Gets the custom data
5359 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5360 ITypeInfo2 * iface,
5361 UINT index,
5362 REFGUID guid,
5363 VARIANT *pVarVal)
5365 ICOM_THIS( ITypeInfoImpl, iface);
5366 TLBCustData *pCData=NULL;
5367 TLBVarDesc * pVDesc;
5368 int i;
5370 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5372 if(pVDesc)
5374 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5376 if( IsEqualIID(guid, &pCData->guid)) break;
5380 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5382 if(pCData)
5384 VariantInit( pVarVal);
5385 VariantCopy( pVarVal, &pCData->data);
5386 return S_OK;
5388 return E_INVALIDARG; /* FIXME: correct? */
5391 /* ITypeInfo2::GetImplCustData
5393 * Gets the custom data
5395 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5396 ITypeInfo2 * iface,
5397 UINT index,
5398 REFGUID guid,
5399 VARIANT *pVarVal)
5401 ICOM_THIS( ITypeInfoImpl, iface);
5402 TLBCustData *pCData=NULL;
5403 TLBImplType * pRDesc;
5404 int i;
5406 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5408 if(pRDesc)
5410 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5412 if( IsEqualIID(guid, &pCData->guid)) break;
5416 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5418 if(pCData)
5420 VariantInit( pVarVal);
5421 VariantCopy( pVarVal, &pCData->data);
5422 return S_OK;
5424 return E_INVALIDARG; /* FIXME: correct? */
5427 /* ITypeInfo2::GetDocumentation2
5429 * Retrieves the documentation string, the complete Help file name and path,
5430 * the localization context to use, and the context ID for the library Help
5431 * topic in the Help file.
5434 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5435 ITypeInfo2 * iface,
5436 MEMBERID memid,
5437 LCID lcid,
5438 BSTR *pbstrHelpString,
5439 DWORD *pdwHelpStringContext,
5440 BSTR *pbstrHelpStringDll)
5442 ICOM_THIS( ITypeInfoImpl, iface);
5443 TLBFuncDesc * pFDesc;
5444 TLBVarDesc * pVDesc;
5445 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5446 "HelpStringContext(%p) HelpStringDll(%p)\n",
5447 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5448 pbstrHelpStringDll );
5449 /* the help string should be obtained from the helpstringdll,
5450 * using the _DLLGetDocumentation function, based on the supplied
5451 * lcid. Nice to do sometime...
5453 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5454 if(pbstrHelpString)
5455 *pbstrHelpString=SysAllocString(This->Name);
5456 if(pdwHelpStringContext)
5457 *pdwHelpStringContext=This->dwHelpStringContext;
5458 if(pbstrHelpStringDll)
5459 *pbstrHelpStringDll=
5460 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5461 return S_OK;
5462 }else {/* for a member */
5463 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5464 if(pFDesc->funcdesc.memid==memid){
5465 if(pbstrHelpString)
5466 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5467 if(pdwHelpStringContext)
5468 *pdwHelpStringContext=pFDesc->HelpStringContext;
5469 if(pbstrHelpStringDll)
5470 *pbstrHelpStringDll=
5471 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5472 return S_OK;
5474 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5475 if(pVDesc->vardesc.memid==memid){
5476 if(pbstrHelpString)
5477 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5478 if(pdwHelpStringContext)
5479 *pdwHelpStringContext=pVDesc->HelpStringContext;
5480 if(pbstrHelpStringDll)
5481 *pbstrHelpStringDll=
5482 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5483 return S_OK;
5486 return TYPE_E_ELEMENTNOTFOUND;
5489 /* ITypeInfo2::GetAllCustData
5491 * Gets all custom data items for the Type info.
5494 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5495 ITypeInfo2 * iface,
5496 CUSTDATA *pCustData)
5498 ICOM_THIS( ITypeInfoImpl, iface);
5499 TLBCustData *pCData;
5500 int i;
5502 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5504 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5505 if(pCustData->prgCustData ){
5506 pCustData->cCustData=This->ctCustData;
5507 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5508 pCustData->prgCustData[i].guid=pCData->guid;
5509 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5511 }else{
5512 ERR(" OUT OF MEMORY! \n");
5513 return E_OUTOFMEMORY;
5515 return S_OK;
5518 /* ITypeInfo2::GetAllFuncCustData
5520 * Gets all custom data items for the specified Function
5523 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5524 ITypeInfo2 * iface,
5525 UINT index,
5526 CUSTDATA *pCustData)
5528 ICOM_THIS( ITypeInfoImpl, iface);
5529 TLBCustData *pCData;
5530 TLBFuncDesc * pFDesc;
5531 int i;
5532 TRACE("(%p) index %d\n", This, index);
5533 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5534 pFDesc=pFDesc->next)
5536 if(pFDesc){
5537 pCustData->prgCustData =
5538 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5539 if(pCustData->prgCustData ){
5540 pCustData->cCustData=pFDesc->ctCustData;
5541 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5542 pCData = pCData->next){
5543 pCustData->prgCustData[i].guid=pCData->guid;
5544 VariantCopy(& pCustData->prgCustData[i].varValue,
5545 & pCData->data);
5547 }else{
5548 ERR(" OUT OF MEMORY! \n");
5549 return E_OUTOFMEMORY;
5551 return S_OK;
5553 return TYPE_E_ELEMENTNOTFOUND;
5556 /* ITypeInfo2::GetAllParamCustData
5558 * Gets all custom data items for the Functions
5561 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5562 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5564 ICOM_THIS( ITypeInfoImpl, iface);
5565 TLBCustData *pCData=NULL;
5566 TLBFuncDesc * pFDesc;
5567 int i;
5568 TRACE("(%p) index %d\n", This, indexFunc);
5569 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5570 pFDesc=pFDesc->next)
5572 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5573 pCustData->prgCustData =
5574 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5575 sizeof(CUSTDATAITEM));
5576 if(pCustData->prgCustData ){
5577 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5578 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5579 pCData; i++, pCData = pCData->next){
5580 pCustData->prgCustData[i].guid=pCData->guid;
5581 VariantCopy(& pCustData->prgCustData[i].varValue,
5582 & pCData->data);
5584 }else{
5585 ERR(" OUT OF MEMORY! \n");
5586 return E_OUTOFMEMORY;
5588 return S_OK;
5590 return TYPE_E_ELEMENTNOTFOUND;
5593 /* ITypeInfo2::GetAllVarCustData
5595 * Gets all custom data items for the specified Variable
5598 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5599 UINT index, CUSTDATA *pCustData)
5601 ICOM_THIS( ITypeInfoImpl, iface);
5602 TLBCustData *pCData;
5603 TLBVarDesc * pVDesc;
5604 int i;
5605 TRACE("(%p) index %d\n", This, index);
5606 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5607 pVDesc=pVDesc->next)
5609 if(pVDesc){
5610 pCustData->prgCustData =
5611 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5612 if(pCustData->prgCustData ){
5613 pCustData->cCustData=pVDesc->ctCustData;
5614 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5615 pCData = pCData->next){
5616 pCustData->prgCustData[i].guid=pCData->guid;
5617 VariantCopy(& pCustData->prgCustData[i].varValue,
5618 & pCData->data);
5620 }else{
5621 ERR(" OUT OF MEMORY! \n");
5622 return E_OUTOFMEMORY;
5624 return S_OK;
5626 return TYPE_E_ELEMENTNOTFOUND;
5629 /* ITypeInfo2::GetAllImplCustData
5631 * Gets all custom data items for the specified implementation type
5634 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5635 ITypeInfo2 * iface,
5636 UINT index,
5637 CUSTDATA *pCustData)
5639 ICOM_THIS( ITypeInfoImpl, iface);
5640 TLBCustData *pCData;
5641 TLBImplType * pRDesc;
5642 int i;
5643 TRACE("(%p) index %d\n", This, index);
5644 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5645 pRDesc=pRDesc->next)
5647 if(pRDesc){
5648 pCustData->prgCustData =
5649 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5650 if(pCustData->prgCustData ){
5651 pCustData->cCustData=pRDesc->ctCustData;
5652 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5653 pCData = pCData->next){
5654 pCustData->prgCustData[i].guid=pCData->guid;
5655 VariantCopy(& pCustData->prgCustData[i].varValue,
5656 & pCData->data);
5658 }else{
5659 ERR(" OUT OF MEMORY! \n");
5660 return E_OUTOFMEMORY;
5662 return S_OK;
5664 return TYPE_E_ELEMENTNOTFOUND;
5667 static ITypeInfo2Vtbl tinfvt =
5669 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5671 ITypeInfo_fnQueryInterface,
5672 ITypeInfo_fnAddRef,
5673 ITypeInfo_fnRelease,
5675 ITypeInfo_fnGetTypeAttr,
5676 ITypeInfo_fnGetTypeComp,
5677 ITypeInfo_fnGetFuncDesc,
5678 ITypeInfo_fnGetVarDesc,
5679 ITypeInfo_fnGetNames,
5680 ITypeInfo_fnGetRefTypeOfImplType,
5681 ITypeInfo_fnGetImplTypeFlags,
5682 ITypeInfo_fnGetIDsOfNames,
5683 ITypeInfo_fnInvoke,
5684 ITypeInfo_fnGetDocumentation,
5685 ITypeInfo_fnGetDllEntry,
5686 ITypeInfo_fnGetRefTypeInfo,
5687 ITypeInfo_fnAddressOfMember,
5688 ITypeInfo_fnCreateInstance,
5689 ITypeInfo_fnGetMops,
5690 ITypeInfo_fnGetContainingTypeLib,
5691 ITypeInfo_fnReleaseTypeAttr,
5692 ITypeInfo_fnReleaseFuncDesc,
5693 ITypeInfo_fnReleaseVarDesc,
5695 ITypeInfo2_fnGetTypeKind,
5696 ITypeInfo2_fnGetTypeFlags,
5697 ITypeInfo2_fnGetFuncIndexOfMemId,
5698 ITypeInfo2_fnGetVarIndexOfMemId,
5699 ITypeInfo2_fnGetCustData,
5700 ITypeInfo2_fnGetFuncCustData,
5701 ITypeInfo2_fnGetParamCustData,
5702 ITypeInfo2_fnGetVarCustData,
5703 ITypeInfo2_fnGetImplTypeCustData,
5704 ITypeInfo2_fnGetDocumentation2,
5705 ITypeInfo2_fnGetAllCustData,
5706 ITypeInfo2_fnGetAllFuncCustData,
5707 ITypeInfo2_fnGetAllParamCustData,
5708 ITypeInfo2_fnGetAllVarCustData,
5709 ITypeInfo2_fnGetAllImplTypeCustData,
5712 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5714 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5716 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5719 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5721 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5723 return ITypeInfo_AddRef((ITypeInfo *)This);
5726 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5728 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5730 return ITypeInfo_Release((ITypeInfo *)This);
5733 static HRESULT WINAPI ITypeComp_fnBind(
5734 ITypeComp * iface,
5735 OLECHAR * szName,
5736 unsigned long lHash,
5737 unsigned short wFlags,
5738 ITypeInfo ** ppTInfo,
5739 DESCKIND * pDescKind,
5740 BINDPTR * pBindPtr)
5742 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5743 TLBFuncDesc * pFDesc;
5744 TLBVarDesc * pVDesc;
5746 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5748 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5749 if (pFDesc->funcdesc.invkind & wFlags)
5750 if (!strcmpW(pFDesc->Name, szName)) {
5751 break;
5754 if (pFDesc)
5756 *pDescKind = DESCKIND_FUNCDESC;
5757 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5758 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5759 return S_OK;
5760 } else {
5761 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5763 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5764 if (!strcmpW(pVDesc->Name, szName)) {
5765 *pDescKind = DESCKIND_VARDESC;
5766 pBindPtr->lpvardesc = &pVDesc->vardesc;
5767 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5768 return S_OK;
5773 /* not found, look for it in inherited interfaces */
5774 if (This->TypeAttr.cImplTypes &&
5775 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
5776 /* recursive search */
5777 ITypeInfo *pTInfo;
5778 ITypeComp *pTComp;
5779 HRESULT hr;
5780 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5781 if (SUCCEEDED(hr))
5783 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5784 ITypeInfo_Release(pTInfo);
5786 if (SUCCEEDED(hr))
5788 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5789 ITypeComp_Release(pTComp);
5790 return hr;
5792 WARN("Could not search inherited interface!\n");
5794 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5795 *pDescKind = DESCKIND_NONE;
5796 pBindPtr->lpfuncdesc = NULL;
5797 *ppTInfo = NULL;
5798 return DISP_E_MEMBERNOTFOUND;
5801 static HRESULT WINAPI ITypeComp_fnBindType(
5802 ITypeComp * iface,
5803 OLECHAR * szName,
5804 unsigned long lHash,
5805 ITypeInfo ** ppTInfo,
5806 ITypeComp ** ppTComp)
5808 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5810 /* strange behaviour (does nothing) but like the
5811 * original */
5813 if (!ppTInfo || !ppTComp)
5814 return E_POINTER;
5816 *ppTInfo = NULL;
5817 *ppTComp = NULL;
5819 return S_OK;
5822 static ITypeCompVtbl tcompvt =
5824 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5826 ITypeComp_fnQueryInterface,
5827 ITypeComp_fnAddRef,
5828 ITypeComp_fnRelease,
5830 ITypeComp_fnBind,
5831 ITypeComp_fnBindType