Avoid lvalue casts (based on a patch by Marcus Meissner).
[wine/testsucceed.git] / dlls / oleaut32 / typelib.c
blob781626a5eb93a9adaab250258028b36bd5cc517c
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 ICOM_VFIELD(ITypeLib2);
857 ICOM_VTABLE(ITypeComp) * 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 ICOM_VTABLE(ITypeLib2) tlbvt;
884 static struct ICOM_VTABLE(ITypeComp) 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 ICOM_VFIELD(ITypeInfo2);
968 ICOM_VTABLE(ITypeComp) * 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 ICOM_VTABLE(ITypeInfo2) tinfvt;
997 static struct ICOM_VTABLE(ITypeComp) 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 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2464 ppTI = &((*ppTI)->next);
2465 (pTypeLibImpl->TypeInfoCount)++;
2469 TRACE("(%p)\n", pTypeLibImpl);
2470 return (ITypeLib2*) pTypeLibImpl;
2474 static BSTR TLB_MultiByteToBSTR(char *ptr)
2476 DWORD len;
2477 WCHAR *nameW;
2478 BSTR ret;
2480 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2481 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2482 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2483 ret = SysAllocString(nameW);
2484 HeapFree(GetProcessHeap(), 0, nameW);
2485 return ret;
2488 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2490 char b[3];
2491 int i;
2492 short s;
2494 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2495 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2496 return FALSE;
2499 guid->Data4[0] = s >> 8;
2500 guid->Data4[1] = s & 0xff;
2502 b[2] = '\0';
2503 for(i = 0; i < 6; i++) {
2504 memcpy(b, str + 24 + 2 * i, 2);
2505 guid->Data4[i + 2] = strtol(b, NULL, 16);
2507 return TRUE;
2510 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2512 WORD bytelen;
2513 DWORD len;
2514 WCHAR *nameW;
2516 *pBstr = NULL;
2517 bytelen = *(WORD*)ptr;
2518 if(bytelen == 0xffff) return 2;
2519 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2520 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2521 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2522 *pBstr = SysAllocStringLen(nameW, len);
2523 HeapFree(GetProcessHeap(), 0, nameW);
2524 return bytelen + 2;
2527 static WORD SLTG_ReadStringA(char *ptr, char **str)
2529 WORD bytelen;
2531 *str = NULL;
2532 bytelen = *(WORD*)ptr;
2533 if(bytelen == 0xffff) return 2;
2534 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2535 memcpy(*str, ptr + 2, bytelen);
2536 (*str)[bytelen] = '\0';
2537 return bytelen + 2;
2540 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2542 char *ptr = pLibBlk;
2543 WORD w;
2545 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2546 FIXME("libblk magic = %04x\n", w);
2547 return 0;
2550 ptr += 6;
2551 if((w = *(WORD*)ptr) != 0xffff) {
2552 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2553 ptr += w;
2555 ptr += 2;
2557 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2559 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2561 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2562 ptr += 4;
2564 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2565 ptr += 2;
2567 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2568 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2569 else
2570 pTypeLibImpl->LibAttr.lcid = 0;
2571 ptr += 2;
2573 ptr += 4; /* skip res12 */
2575 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2576 ptr += 2;
2578 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2579 ptr += 2;
2581 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2582 ptr += 2;
2584 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2585 ptr += sizeof(GUID);
2587 return ptr - (char*)pLibBlk;
2590 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2592 BOOL done = FALSE;
2593 TYPEDESC *pTD = &pElem->tdesc;
2595 /* Handle [in/out] first */
2596 if((*pType & 0xc000) == 0xc000)
2597 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2598 else if(*pType & 0x8000)
2599 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2600 else if(*pType & 0x4000)
2601 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2602 else
2603 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2605 if(*pType & 0x2000)
2606 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2608 if(*pType & 0x80)
2609 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2611 while(!done) {
2612 if((*pType & 0xe00) == 0xe00) {
2613 pTD->vt = VT_PTR;
2614 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2615 sizeof(TYPEDESC));
2616 pTD = pTD->u.lptdesc;
2618 switch(*pType & 0x7f) {
2619 case VT_PTR:
2620 pTD->vt = VT_PTR;
2621 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2622 sizeof(TYPEDESC));
2623 pTD = pTD->u.lptdesc;
2624 break;
2626 case VT_USERDEFINED:
2627 pTD->vt = VT_USERDEFINED;
2628 pTD->u.hreftype = *(++pType) / 4;
2629 done = TRUE;
2630 break;
2632 case VT_CARRAY:
2634 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2635 array */
2637 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2639 pTD->vt = VT_CARRAY;
2640 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2641 sizeof(ARRAYDESC) +
2642 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2643 pTD->u.lpadesc->cDims = pSA->cDims;
2644 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2645 pSA->cDims * sizeof(SAFEARRAYBOUND));
2647 pTD = &pTD->u.lpadesc->tdescElem;
2648 break;
2651 case VT_SAFEARRAY:
2653 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2654 useful? */
2656 pType++;
2657 pTD->vt = VT_SAFEARRAY;
2658 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2659 sizeof(TYPEDESC));
2660 pTD = pTD->u.lptdesc;
2661 break;
2663 default:
2664 pTD->vt = *pType & 0x7f;
2665 done = TRUE;
2666 break;
2668 pType++;
2670 return pType;
2674 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2675 char *pNameTable)
2677 int ref;
2678 char *name;
2679 TLBRefType **ppRefType;
2681 if(pRef->magic != SLTG_REF_MAGIC) {
2682 FIXME("Ref magic = %x\n", pRef->magic);
2683 return;
2685 name = ( (char*)(&pRef->names) + pRef->number);
2687 ppRefType = &pTI->reflist;
2688 for(ref = 0; ref < pRef->number >> 3; ref++) {
2689 char *refname;
2690 unsigned int lib_offs, type_num;
2692 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2693 sizeof(**ppRefType));
2695 name += SLTG_ReadStringA(name, &refname);
2696 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2697 FIXME("Can't sscanf ref\n");
2698 if(lib_offs != 0xffff) {
2699 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2701 while(*import) {
2702 if((*import)->offset == lib_offs)
2703 break;
2704 import = &(*import)->next;
2706 if(!*import) {
2707 char fname[MAX_PATH+1];
2708 int len;
2710 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2711 sizeof(**import));
2712 (*import)->offset = lib_offs;
2713 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2714 &(*import)->guid);
2715 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2716 &(*import)->wVersionMajor,
2717 &(*import)->wVersionMinor,
2718 &(*import)->lcid, fname) != 4) {
2719 FIXME("can't sscanf ref %s\n",
2720 pNameTable + lib_offs + 40);
2722 len = strlen(fname);
2723 if(fname[len-1] != '#')
2724 FIXME("fname = %s\n", fname);
2725 fname[len-1] = '\0';
2726 (*import)->name = TLB_MultiByteToBSTR(fname);
2728 (*ppRefType)->pImpTLInfo = *import;
2729 } else { /* internal ref */
2730 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2732 (*ppRefType)->reference = ref;
2733 (*ppRefType)->index = type_num;
2735 HeapFree(GetProcessHeap(), 0, refname);
2736 ppRefType = &(*ppRefType)->next;
2738 if((BYTE)*name != SLTG_REF_MAGIC)
2739 FIXME("End of ref block magic = %x\n", *name);
2740 dump_TLBRefType(pTI->reflist);
2743 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2744 BOOL OneOnly)
2746 SLTG_ImplInfo *info;
2747 TLBImplType **ppImplType = &pTI->impltypelist;
2748 /* I don't really get this structure, usually it's 0x16 bytes
2749 long, but iuser.tlb contains some that are 0x18 bytes long.
2750 That's ok because we can use the next ptr to jump to the next
2751 one. But how do we know the length of the last one? The WORD
2752 at offs 0x8 might be the clue. For now I'm just assuming that
2753 the last one is the regular 0x16 bytes. */
2755 info = (SLTG_ImplInfo*)pBlk;
2756 while(1) {
2757 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2758 sizeof(**ppImplType));
2759 (*ppImplType)->hRef = info->ref;
2760 (*ppImplType)->implflags = info->impltypeflags;
2761 pTI->TypeAttr.cImplTypes++;
2762 ppImplType = &(*ppImplType)->next;
2764 if(info->next == 0xffff)
2765 break;
2766 if(OneOnly)
2767 FIXME("Interface inheriting more than one interface\n");
2768 info = (SLTG_ImplInfo*)(pBlk + info->next);
2770 info++; /* see comment at top of function */
2771 return (char*)info;
2774 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2775 char *pNameTable)
2777 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2778 SLTG_MemberHeader *pMemHeader;
2779 char *pFirstItem, *pNextItem;
2781 if(pTIHeader->href_table != 0xffffffff) {
2782 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2783 pNameTable);
2787 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2789 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2791 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2792 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2795 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2799 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2800 char *pNameTable)
2802 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2803 SLTG_MemberHeader *pMemHeader;
2804 SLTG_Function *pFunc;
2805 char *pFirstItem, *pNextItem;
2806 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2807 int num = 0;
2809 if(pTIHeader->href_table != 0xffffffff) {
2810 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2811 pNameTable);
2814 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2816 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2818 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2819 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2822 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2823 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2825 int param;
2826 WORD *pType, *pArg;
2828 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2829 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2830 FIXME("func magic = %02x\n", pFunc->magic);
2831 return NULL;
2833 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2834 sizeof(**ppFuncDesc));
2835 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2837 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2838 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2839 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2840 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2841 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2842 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2844 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2845 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2847 if(pFunc->retnextopt & 0x80)
2848 pType = &pFunc->rettype;
2849 else
2850 pType = (WORD*)(pFirstItem + pFunc->rettype);
2853 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2855 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2856 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2857 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2858 (*ppFuncDesc)->pParamDesc =
2859 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2860 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2862 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2864 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2865 char *paramName = pNameTable + *pArg;
2866 BOOL HaveOffs;
2867 /* If arg type follows then paramName points to the 2nd
2868 letter of the name, else the next WORD is an offset to
2869 the arg type and paramName points to the first letter.
2870 So let's take one char off paramName and see if we're
2871 pointing at an alpha-numeric char. However if *pArg is
2872 0xffff or 0xfffe then the param has no name, the former
2873 meaning that the next WORD is the type, the latter
2874 meaning the the next WORD is an offset to the type. */
2876 HaveOffs = FALSE;
2877 if(*pArg == 0xffff)
2878 paramName = NULL;
2879 else if(*pArg == 0xfffe) {
2880 paramName = NULL;
2881 HaveOffs = TRUE;
2883 else if(!isalnum(*(paramName-1)))
2884 HaveOffs = TRUE;
2886 pArg++;
2888 if(HaveOffs) { /* the next word is an offset to type */
2889 pType = (WORD*)(pFirstItem + *pArg);
2890 SLTG_DoType(pType, pFirstItem,
2891 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2892 pArg++;
2893 } else {
2894 if(paramName)
2895 paramName--;
2896 pArg = SLTG_DoType(pArg, pFirstItem,
2897 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2900 /* Are we an optional param ? */
2901 if((*ppFuncDesc)->funcdesc.cParams - param <=
2902 (*ppFuncDesc)->funcdesc.cParamsOpt)
2903 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2905 if(paramName) {
2906 (*ppFuncDesc)->pParamDesc[param].Name =
2907 TLB_MultiByteToBSTR(paramName);
2911 ppFuncDesc = &((*ppFuncDesc)->next);
2912 if(pFunc->next == 0xffff) break;
2914 pTI->TypeAttr.cFuncs = num;
2915 dump_TLBFuncDesc(pTI->funclist);
2916 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2919 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2920 char *pNameTable)
2922 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2923 SLTG_MemberHeader *pMemHeader;
2924 SLTG_RecordItem *pItem;
2925 char *pFirstItem;
2926 TLBVarDesc **ppVarDesc = &pTI->varlist;
2927 int num = 0;
2928 WORD *pType;
2929 char buf[300];
2931 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2933 pFirstItem = (char*)(pMemHeader + 1);
2934 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2935 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2936 if(pItem->magic != SLTG_RECORD_MAGIC) {
2937 FIXME("record magic = %02x\n", pItem->magic);
2938 return NULL;
2940 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2941 sizeof(**ppVarDesc));
2942 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2943 (*ppVarDesc)->vardesc.memid = pItem->memid;
2944 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2945 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2947 if(pItem->typepos == 0x02)
2948 pType = &pItem->type;
2949 else if(pItem->typepos == 0x00)
2950 pType = (WORD*)(pFirstItem + pItem->type);
2951 else {
2952 FIXME("typepos = %02x\n", pItem->typepos);
2953 break;
2956 SLTG_DoType(pType, pFirstItem,
2957 &(*ppVarDesc)->vardesc.elemdescVar);
2959 /* FIXME("helpcontext, helpstring\n"); */
2961 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2963 ppVarDesc = &((*ppVarDesc)->next);
2964 if(pItem->next == 0xffff) break;
2966 pTI->TypeAttr.cVars = num;
2967 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2970 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2971 char *pNameTable)
2973 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2974 SLTG_MemberHeader *pMemHeader;
2975 SLTG_AliasItem *pItem;
2976 int i, mustbelast;
2978 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2979 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2981 mustbelast = 0;
2982 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2983 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2984 if (pItem->vt == 0xffff) {
2985 if (i<(pMemHeader->cbExtra/4-1))
2986 FIXME("Endmarker too early in process alias data!\n");
2987 break;
2989 if (mustbelast) {
2990 FIXME("Chain extends over last entry?\n");
2991 break;
2993 if (pItem->vt == VT_USERDEFINED) {
2994 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2995 /* guessing here ... */
2996 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2997 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2998 mustbelast = 1;
2999 } else {
3000 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3001 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3003 pItem++;
3005 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3008 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3009 char *pNameTable)
3011 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3012 SLTG_MemberHeader *pMemHeader;
3013 SLTG_AliasItem *pItem;
3015 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3016 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3017 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3018 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3019 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3022 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3023 char *pNameTable)
3025 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3026 SLTG_MemberHeader *pMemHeader;
3027 SLTG_EnumItem *pItem;
3028 char *pFirstItem;
3029 TLBVarDesc **ppVarDesc = &pTI->varlist;
3030 int num = 0;
3032 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3034 pFirstItem = (char*)(pMemHeader + 1);
3035 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3036 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3037 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3038 FIXME("enumitem magic = %04x\n", pItem->magic);
3039 return NULL;
3041 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3042 sizeof(**ppVarDesc));
3043 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3044 (*ppVarDesc)->vardesc.memid = pItem->memid;
3045 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3046 sizeof(VARIANT));
3047 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3048 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3049 *(INT*)(pItem->value + pFirstItem);
3050 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3051 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3052 /* FIXME("helpcontext, helpstring\n"); */
3054 ppVarDesc = &((*ppVarDesc)->next);
3055 if(pItem->next == 0xffff) break;
3057 pTI->TypeAttr.cVars = num;
3058 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3061 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
3062 managable copy of it into this */
3063 typedef struct {
3064 WORD small_no;
3065 char *index_name;
3066 char *other_name;
3067 WORD res1a;
3068 WORD name_offs;
3069 WORD more_bytes;
3070 char *extra;
3071 WORD res20;
3072 DWORD helpcontext;
3073 WORD res26;
3074 GUID uuid;
3075 } SLTG_InternalOtherTypeInfo;
3077 /****************************************************************************
3078 * ITypeLib2_Constructor_SLTG
3080 * loading a SLTG typelib from an in-memory image
3082 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3084 ITypeLibImpl *pTypeLibImpl;
3085 SLTG_Header *pHeader;
3086 SLTG_BlkEntry *pBlkEntry;
3087 SLTG_Magic *pMagic;
3088 SLTG_Index *pIndex;
3089 SLTG_Pad9 *pPad9;
3090 LPVOID pBlk, pFirstBlk;
3091 SLTG_LibBlk *pLibBlk;
3092 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3093 char *pAfterOTIBlks = NULL;
3094 char *pNameTable, *ptr;
3095 int i;
3096 DWORD len, order;
3097 ITypeInfoImpl **ppTypeInfoImpl;
3099 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3101 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3102 if (!pTypeLibImpl) return NULL;
3104 pTypeLibImpl->lpVtbl = &tlbvt;
3105 pTypeLibImpl->ref = 1;
3107 pHeader = pLib;
3109 TRACE("header:\n");
3110 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3111 pHeader->nrOfFileBlks );
3112 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3113 FIXME("Header type magic 0x%08lx not supported.\n",
3114 pHeader->SLTG_magic);
3115 return NULL;
3118 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3119 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3121 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3122 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3124 /* Next we have a magic block */
3125 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3127 /* Let's see if we're still in sync */
3128 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3129 sizeof(SLTG_COMPOBJ_MAGIC))) {
3130 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3131 return NULL;
3133 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3134 sizeof(SLTG_DIR_MAGIC))) {
3135 FIXME("dir magic = %s\n", pMagic->dir_magic);
3136 return NULL;
3139 pIndex = (SLTG_Index*)(pMagic+1);
3141 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3143 pFirstBlk = (LPVOID)(pPad9 + 1);
3145 /* We'll set up a ptr to the main library block, which is the last one. */
3147 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3148 pBlkEntry[order].next != 0;
3149 order = pBlkEntry[order].next - 1, i++) {
3150 pBlk = (char*)pBlk + pBlkEntry[order].len;
3152 pLibBlk = pBlk;
3154 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3156 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3157 interspersed */
3159 len += 0x40;
3161 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3163 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3164 sizeof(*pOtherTypeInfoBlks) *
3165 pTypeLibImpl->TypeInfoCount);
3168 ptr = (char*)pLibBlk + len;
3170 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3171 WORD w, extra;
3172 len = 0;
3174 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3176 w = *(WORD*)(ptr + 2);
3177 if(w != 0xffff) {
3178 len += w;
3179 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3180 w+1);
3181 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3182 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3184 w = *(WORD*)(ptr + 4 + len);
3185 if(w != 0xffff) {
3186 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3187 len += w;
3188 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3189 w+1);
3190 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3191 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3193 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3194 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3195 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3196 if(extra) {
3197 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3198 extra);
3199 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3200 len += extra;
3202 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3203 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3204 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3205 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3206 len += sizeof(SLTG_OtherTypeInfo);
3207 ptr += len;
3210 pAfterOTIBlks = ptr;
3212 /* Skip this WORD and get the next DWORD */
3213 len = *(DWORD*)(pAfterOTIBlks + 2);
3215 /* Now add this to pLibBLk look at what we're pointing at and
3216 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3217 dust and we should be pointing at the beginning of the name
3218 table */
3220 pNameTable = (char*)pLibBlk + len;
3222 switch(*(WORD*)pNameTable) {
3223 case 0xffff:
3224 break;
3225 case 0x0200:
3226 pNameTable += 0x20;
3227 break;
3228 default:
3229 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3230 break;
3233 pNameTable += 0x216;
3235 pNameTable += 2;
3237 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3239 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3242 /* Hopefully we now have enough ptrs set up to actually read in
3243 some TypeInfos. It's not clear which order to do them in, so
3244 I'll just follow the links along the BlkEntry chain and read
3245 them in in the order in which they're in the file */
3247 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3249 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3250 pBlkEntry[order].next != 0;
3251 order = pBlkEntry[order].next - 1, i++) {
3253 SLTG_TypeInfoHeader *pTIHeader;
3254 SLTG_TypeInfoTail *pTITail;
3256 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3257 pOtherTypeInfoBlks[i].index_name)) {
3258 FIXME("Index strings don't match\n");
3259 return NULL;
3262 pTIHeader = pBlk;
3263 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3264 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3265 return NULL;
3267 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3268 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3269 (*ppTypeInfoImpl)->index = i;
3270 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3271 pOtherTypeInfoBlks[i].name_offs +
3272 pNameTable);
3273 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3274 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3275 sizeof(GUID));
3276 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3277 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3278 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3279 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3280 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3282 if((pTIHeader->typeflags1 & 7) != 2)
3283 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3284 if(pTIHeader->typeflags3 != 2)
3285 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3287 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3288 debugstr_w((*ppTypeInfoImpl)->Name),
3289 typekind_desc[pTIHeader->typekind],
3290 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3291 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3293 switch(pTIHeader->typekind) {
3294 case TKIND_ENUM:
3295 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3296 break;
3298 case TKIND_RECORD:
3299 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3300 break;
3302 case TKIND_INTERFACE:
3303 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3304 break;
3306 case TKIND_COCLASS:
3307 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3308 break;
3310 case TKIND_ALIAS:
3311 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3312 if (pTITail->tdescalias_vt)
3313 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3314 break;
3316 case TKIND_DISPATCH:
3317 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3318 break;
3320 default:
3321 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3322 pTITail = NULL;
3323 break;
3327 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3328 but we've already set those */
3329 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3330 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3331 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3333 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3334 X(06);
3335 X(08);
3336 X(0a);
3337 X(0c);
3338 X(0e);
3339 X(10);
3340 X(12);
3341 X(16);
3342 X(18);
3343 X(1a);
3344 X(1c);
3345 X(1e);
3346 X(24);
3347 X(26);
3348 X(2a);
3349 X(2c);
3350 X(2e);
3351 X(30);
3352 X(32);
3353 X(34);
3355 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3356 pBlk = (char*)pBlk + pBlkEntry[order].len;
3359 if(i != pTypeLibImpl->TypeInfoCount) {
3360 FIXME("Somehow processed %d TypeInfos\n", i);
3361 return NULL;
3364 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3365 return (ITypeLib2*)pTypeLibImpl;
3368 /* ITypeLib::QueryInterface
3370 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3371 ITypeLib2 * iface,
3372 REFIID riid,
3373 VOID **ppvObject)
3375 ICOM_THIS( ITypeLibImpl, iface);
3377 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3379 *ppvObject=NULL;
3380 if(IsEqualIID(riid, &IID_IUnknown) ||
3381 IsEqualIID(riid,&IID_ITypeLib)||
3382 IsEqualIID(riid,&IID_ITypeLib2))
3384 *ppvObject = This;
3387 if(*ppvObject)
3389 ITypeLib2_AddRef(iface);
3390 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3391 return S_OK;
3393 TRACE("-- Interface: E_NOINTERFACE\n");
3394 return E_NOINTERFACE;
3397 /* ITypeLib::AddRef
3399 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3401 ICOM_THIS( ITypeLibImpl, iface);
3403 TRACE("(%p)->ref was %u\n",This, This->ref);
3405 return ++(This->ref);
3408 /* ITypeLib::Release
3410 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3412 ICOM_THIS( ITypeLibImpl, iface);
3414 --(This->ref);
3416 TRACE("(%p)->(%u)\n",This, This->ref);
3418 if (!This->ref)
3420 /* remove cache entry */
3421 TRACE("removing from cache list\n");
3422 EnterCriticalSection(&cache_section);
3423 if (This->next) This->next->prev = This->prev;
3424 if (This->prev) This->prev->next = This->next;
3425 else tlb_cache_first = This->next;
3426 LeaveCriticalSection(&cache_section);
3428 /* FIXME destroy child objects */
3429 TRACE(" destroying ITypeLib(%p)\n",This);
3431 if (This->Name)
3433 SysFreeString(This->Name);
3434 This->Name = NULL;
3437 if (This->DocString)
3439 SysFreeString(This->DocString);
3440 This->DocString = NULL;
3443 if (This->HelpFile)
3445 SysFreeString(This->HelpFile);
3446 This->HelpFile = NULL;
3449 if (This->HelpStringDll)
3451 SysFreeString(This->HelpStringDll);
3452 This->HelpStringDll = NULL;
3455 if (This->pTypeInfo) /* can be NULL */
3456 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3457 HeapFree(GetProcessHeap(),0,This);
3458 return 0;
3461 return This->ref;
3464 /* ITypeLib::GetTypeInfoCount
3466 * Returns the number of type descriptions in the type library
3468 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3470 ICOM_THIS( ITypeLibImpl, iface);
3471 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3472 return This->TypeInfoCount;
3475 /* ITypeLib::GetTypeInfo
3477 * retrieves the specified type description in the library.
3479 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3480 ITypeLib2 *iface,
3481 UINT index,
3482 ITypeInfo **ppTInfo)
3484 int i;
3486 ICOM_THIS( ITypeLibImpl, iface);
3487 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3489 TRACE("(%p)->(index=%d) \n", This, index);
3491 if (!ppTInfo) return E_INVALIDARG;
3493 /* search element n in list */
3494 for(i=0; i < index; i++)
3496 pTypeInfo = pTypeInfo->next;
3497 if (!pTypeInfo)
3499 TRACE("-- element not found\n");
3500 return TYPE_E_ELEMENTNOTFOUND;
3504 *ppTInfo = (ITypeInfo *) pTypeInfo;
3506 ITypeInfo_AddRef(*ppTInfo);
3507 TRACE("-- found (%p)\n",*ppTInfo);
3508 return S_OK;
3512 /* ITypeLibs::GetTypeInfoType
3514 * Retrieves the type of a type description.
3516 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3517 ITypeLib2 *iface,
3518 UINT index,
3519 TYPEKIND *pTKind)
3521 ICOM_THIS( ITypeLibImpl, iface);
3522 int i;
3523 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3525 TRACE("(%p) index %d \n",This, index);
3527 if(!pTKind) return E_INVALIDARG;
3529 /* search element n in list */
3530 for(i=0; i < index; i++)
3532 if(!pTInfo)
3534 TRACE("-- element not found\n");
3535 return TYPE_E_ELEMENTNOTFOUND;
3537 pTInfo = pTInfo->next;
3540 *pTKind = pTInfo->TypeAttr.typekind;
3541 TRACE("-- found Type (%d)\n", *pTKind);
3542 return S_OK;
3545 /* ITypeLib::GetTypeInfoOfGuid
3547 * Retrieves the type description that corresponds to the specified GUID.
3550 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3551 ITypeLib2 *iface,
3552 REFGUID guid,
3553 ITypeInfo **ppTInfo)
3555 ICOM_THIS( ITypeLibImpl, iface);
3556 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3558 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3560 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3562 /* search linked list for guid */
3563 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3565 pTypeInfo = pTypeInfo->next;
3567 if (!pTypeInfo)
3569 /* end of list reached */
3570 TRACE("-- element not found\n");
3571 return TYPE_E_ELEMENTNOTFOUND;
3575 TRACE("-- found (%p, %s)\n",
3576 pTypeInfo,
3577 debugstr_w(pTypeInfo->Name));
3579 *ppTInfo = (ITypeInfo*)pTypeInfo;
3580 ITypeInfo_AddRef(*ppTInfo);
3581 return S_OK;
3584 /* ITypeLib::GetLibAttr
3586 * Retrieves the structure that contains the library's attributes.
3589 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3590 ITypeLib2 *iface,
3591 LPTLIBATTR *ppTLibAttr)
3593 ICOM_THIS( ITypeLibImpl, iface);
3594 TRACE("(%p)\n",This);
3595 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3596 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3597 return S_OK;
3600 /* ITypeLib::GetTypeComp
3602 * Enables a client compiler to bind to a library's types, variables,
3603 * constants, and global functions.
3606 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3607 ITypeLib2 *iface,
3608 ITypeComp **ppTComp)
3610 ICOM_THIS( ITypeLibImpl, iface);
3612 TRACE("(%p)->(%p)\n",This,ppTComp);
3613 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3614 ITypeComp_AddRef(*ppTComp);
3616 return S_OK;
3619 /* ITypeLib::GetDocumentation
3621 * Retrieves the library's documentation string, the complete Help file name
3622 * and path, and the context identifier for the library Help topic in the Help
3623 * file.
3625 * On a successful return all non-null BSTR pointers will have been set,
3626 * possibly to NULL.
3628 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3629 ITypeLib2 *iface,
3630 INT index,
3631 BSTR *pBstrName,
3632 BSTR *pBstrDocString,
3633 DWORD *pdwHelpContext,
3634 BSTR *pBstrHelpFile)
3636 ICOM_THIS( ITypeLibImpl, iface);
3638 HRESULT result = E_INVALIDARG;
3640 ITypeInfo *pTInfo;
3643 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3644 This, index,
3645 pBstrName, pBstrDocString,
3646 pdwHelpContext, pBstrHelpFile);
3648 if(index<0)
3650 /* documentation for the typelib */
3651 if(pBstrName)
3653 if (This->Name)
3654 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3655 else
3656 *pBstrName = NULL;
3658 if(pBstrDocString)
3660 if (This->DocString)
3661 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3662 else if (This->Name)
3663 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3664 else
3665 *pBstrDocString = NULL;
3667 if(pdwHelpContext)
3669 *pdwHelpContext = This->dwHelpContext;
3671 if(pBstrHelpFile)
3673 if (This->HelpFile)
3674 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3675 else
3676 *pBstrHelpFile = NULL;
3679 result = S_OK;
3681 else
3683 /* for a typeinfo */
3684 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3686 if(SUCCEEDED(result))
3688 result = ITypeInfo_GetDocumentation(pTInfo,
3689 MEMBERID_NIL,
3690 pBstrName,
3691 pBstrDocString,
3692 pdwHelpContext, pBstrHelpFile);
3694 ITypeInfo_Release(pTInfo);
3697 return result;
3698 memerr3:
3699 if (pBstrDocString) SysFreeString (*pBstrDocString);
3700 memerr2:
3701 if (pBstrName) SysFreeString (*pBstrName);
3702 memerr1:
3703 return STG_E_INSUFFICIENTMEMORY;
3706 /* ITypeLib::IsName
3708 * Indicates whether a passed-in string contains the name of a type or member
3709 * described in the library.
3712 static HRESULT WINAPI ITypeLib2_fnIsName(
3713 ITypeLib2 *iface,
3714 LPOLESTR szNameBuf,
3715 ULONG lHashVal,
3716 BOOL *pfName)
3718 ICOM_THIS( ITypeLibImpl, iface);
3719 ITypeInfoImpl *pTInfo;
3720 TLBFuncDesc *pFInfo;
3721 TLBVarDesc *pVInfo;
3722 int i;
3723 UINT nNameBufLen = SysStringLen(szNameBuf);
3725 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3726 pfName);
3728 *pfName=TRUE;
3729 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3730 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3731 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3732 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3733 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3734 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3735 goto ITypeLib2_fnIsName_exit;
3737 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3738 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3741 *pfName=FALSE;
3743 ITypeLib2_fnIsName_exit:
3744 TRACE("(%p)slow! search for %s: %s found!\n", This,
3745 debugstr_w(szNameBuf), *pfName?"NOT":"");
3747 return S_OK;
3750 /* ITypeLib::FindName
3752 * Finds occurrences of a type description in a type library. This may be used
3753 * to quickly verify that a name exists in a type library.
3756 static HRESULT WINAPI ITypeLib2_fnFindName(
3757 ITypeLib2 *iface,
3758 LPOLESTR szNameBuf,
3759 ULONG lHashVal,
3760 ITypeInfo **ppTInfo,
3761 MEMBERID *rgMemId,
3762 UINT16 *pcFound)
3764 ICOM_THIS( ITypeLibImpl, iface);
3765 ITypeInfoImpl *pTInfo;
3766 TLBFuncDesc *pFInfo;
3767 TLBVarDesc *pVInfo;
3768 int i,j = 0;
3770 UINT nNameBufLen = SysStringLen(szNameBuf);
3772 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3773 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3774 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3775 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3776 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3777 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3778 goto ITypeLib2_fnFindName_exit;
3780 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3781 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3782 continue;
3783 ITypeLib2_fnFindName_exit:
3784 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3785 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3786 j++;
3788 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3789 This, *pcFound, debugstr_w(szNameBuf), j);
3791 *pcFound=j;
3793 return S_OK;
3796 /* ITypeLib::ReleaseTLibAttr
3798 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3801 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3802 ITypeLib2 *iface,
3803 TLIBATTR *pTLibAttr)
3805 ICOM_THIS( ITypeLibImpl, iface);
3806 TRACE("freeing (%p)\n",This);
3807 HeapFree(GetProcessHeap(),0,pTLibAttr);
3811 /* ITypeLib2::GetCustData
3813 * gets the custom data
3815 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3816 ITypeLib2 * iface,
3817 REFGUID guid,
3818 VARIANT *pVarVal)
3820 ICOM_THIS( ITypeLibImpl, iface);
3821 TLBCustData *pCData;
3823 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3825 if( IsEqualIID(guid, &pCData->guid)) break;
3828 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3830 if(pCData)
3832 VariantInit( pVarVal);
3833 VariantCopy( pVarVal, &pCData->data);
3834 return S_OK;
3836 return E_INVALIDARG; /* FIXME: correct? */
3839 /* ITypeLib2::GetLibStatistics
3841 * Returns statistics about a type library that are required for efficient
3842 * sizing of hash tables.
3845 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3846 ITypeLib2 * iface,
3847 ULONG *pcUniqueNames,
3848 ULONG *pcchUniqueNames)
3850 ICOM_THIS( ITypeLibImpl, iface);
3852 FIXME("(%p): stub!\n", This);
3854 if(pcUniqueNames) *pcUniqueNames=1;
3855 if(pcchUniqueNames) *pcchUniqueNames=1;
3856 return S_OK;
3859 /* ITypeLib2::GetDocumentation2
3861 * Retrieves the library's documentation string, the complete Help file name
3862 * and path, the localization context to use, and the context ID for the
3863 * library Help topic in the Help file.
3866 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3867 ITypeLib2 * iface,
3868 INT index,
3869 LCID lcid,
3870 BSTR *pbstrHelpString,
3871 DWORD *pdwHelpStringContext,
3872 BSTR *pbstrHelpStringDll)
3874 ICOM_THIS( ITypeLibImpl, iface);
3875 HRESULT result;
3876 ITypeInfo *pTInfo;
3878 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3880 /* the help string should be obtained from the helpstringdll,
3881 * using the _DLLGetDocumentation function, based on the supplied
3882 * lcid. Nice to do sometime...
3884 if(index<0)
3886 /* documentation for the typelib */
3887 if(pbstrHelpString)
3888 *pbstrHelpString=SysAllocString(This->DocString);
3889 if(pdwHelpStringContext)
3890 *pdwHelpStringContext=This->dwHelpContext;
3891 if(pbstrHelpStringDll)
3892 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3894 result = S_OK;
3896 else
3898 /* for a typeinfo */
3899 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3901 if(SUCCEEDED(result))
3903 ITypeInfo2 * pTInfo2;
3904 result = ITypeInfo_QueryInterface(pTInfo,
3905 &IID_ITypeInfo2,
3906 (LPVOID*) &pTInfo2);
3908 if(SUCCEEDED(result))
3910 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3911 MEMBERID_NIL,
3912 lcid,
3913 pbstrHelpString,
3914 pdwHelpStringContext,
3915 pbstrHelpStringDll);
3917 ITypeInfo2_Release(pTInfo2);
3920 ITypeInfo_Release(pTInfo);
3923 return result;
3926 /* ITypeLib2::GetAllCustData
3928 * Gets all custom data items for the library.
3931 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3932 ITypeLib2 * iface,
3933 CUSTDATA *pCustData)
3935 ICOM_THIS( ITypeLibImpl, iface);
3936 TLBCustData *pCData;
3937 int i;
3938 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3939 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3940 if(pCustData->prgCustData ){
3941 pCustData->cCustData=This->ctCustData;
3942 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3943 pCustData->prgCustData[i].guid=pCData->guid;
3944 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3946 }else{
3947 ERR(" OUT OF MEMORY! \n");
3948 return E_OUTOFMEMORY;
3950 return S_OK;
3953 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3954 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3955 ITypeLib2_fnQueryInterface,
3956 ITypeLib2_fnAddRef,
3957 ITypeLib2_fnRelease,
3958 ITypeLib2_fnGetTypeInfoCount,
3959 ITypeLib2_fnGetTypeInfo,
3960 ITypeLib2_fnGetTypeInfoType,
3961 ITypeLib2_fnGetTypeInfoOfGuid,
3962 ITypeLib2_fnGetLibAttr,
3963 ITypeLib2_fnGetTypeComp,
3964 ITypeLib2_fnGetDocumentation,
3965 ITypeLib2_fnIsName,
3966 ITypeLib2_fnFindName,
3967 ITypeLib2_fnReleaseTLibAttr,
3969 ITypeLib2_fnGetCustData,
3970 ITypeLib2_fnGetLibStatistics,
3971 ITypeLib2_fnGetDocumentation2,
3972 ITypeLib2_fnGetAllCustData
3976 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
3978 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3980 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
3983 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
3985 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3987 return ITypeInfo_AddRef((ITypeInfo *)This);
3990 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
3992 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3994 return ITypeInfo_Release((ITypeInfo *)This);
3997 static HRESULT WINAPI ITypeLibComp_fnBind(
3998 ITypeComp * iface,
3999 OLECHAR * szName,
4000 unsigned long lHash,
4001 unsigned short wFlags,
4002 ITypeInfo ** ppTInfo,
4003 DESCKIND * pDescKind,
4004 BINDPTR * pBindPtr)
4006 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4007 return E_NOTIMPL;
4010 static HRESULT WINAPI ITypeLibComp_fnBindType(
4011 ITypeComp * iface,
4012 OLECHAR * szName,
4013 unsigned long lHash,
4014 ITypeInfo ** ppTInfo,
4015 ITypeComp ** ppTComp)
4017 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4018 return E_NOTIMPL;
4021 static ICOM_VTABLE(ITypeComp) tlbtcvt =
4023 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4025 ITypeLibComp_fnQueryInterface,
4026 ITypeLibComp_fnAddRef,
4027 ITypeLibComp_fnRelease,
4029 ITypeLibComp_fnBind,
4030 ITypeLibComp_fnBindType
4033 /*================== ITypeInfo(2) Methods ===================================*/
4034 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4036 ITypeInfoImpl * pTypeInfoImpl;
4038 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4039 if (pTypeInfoImpl)
4041 pTypeInfoImpl->lpVtbl = &tinfvt;
4042 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4043 pTypeInfoImpl->ref=1;
4045 TRACE("(%p)\n", pTypeInfoImpl);
4046 return (ITypeInfo2*) pTypeInfoImpl;
4049 /* ITypeInfo::QueryInterface
4051 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4052 ITypeInfo2 *iface,
4053 REFIID riid,
4054 VOID **ppvObject)
4056 ICOM_THIS( ITypeLibImpl, iface);
4058 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4060 *ppvObject=NULL;
4061 if(IsEqualIID(riid, &IID_IUnknown) ||
4062 IsEqualIID(riid,&IID_ITypeInfo)||
4063 IsEqualIID(riid,&IID_ITypeInfo2))
4064 *ppvObject = This;
4066 if(*ppvObject){
4067 ITypeInfo_AddRef(iface);
4068 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4069 return S_OK;
4071 TRACE("-- Interface: E_NOINTERFACE\n");
4072 return E_NOINTERFACE;
4075 /* ITypeInfo::AddRef
4077 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4079 ICOM_THIS( ITypeInfoImpl, iface);
4081 ++(This->ref);
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)
4099 FIXME("destroy child objects\n");
4101 TRACE("destroying ITypeInfo(%p)\n",This);
4102 if (This->Name)
4104 SysFreeString(This->Name);
4105 This->Name = 0;
4108 if (This->DocString)
4110 SysFreeString(This->DocString);
4111 This->DocString = 0;
4114 if (This->next)
4116 ITypeInfo_Release((ITypeInfo*)This->next);
4119 HeapFree(GetProcessHeap(),0,This);
4120 return 0;
4122 return This->ref;
4125 /* ITypeInfo::GetTypeAttr
4127 * Retrieves a TYPEATTR structure that contains the attributes of the type
4128 * description.
4131 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4132 LPTYPEATTR *ppTypeAttr)
4134 ICOM_THIS( ITypeInfoImpl, iface);
4135 TRACE("(%p)\n",This);
4136 /* FIXME: must do a copy here */
4137 *ppTypeAttr=&This->TypeAttr;
4138 return S_OK;
4141 /* ITypeInfo::GetTypeComp
4143 * Retrieves the ITypeComp interface for the type description, which enables a
4144 * client compiler to bind to the type description's members.
4147 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4148 ITypeComp * *ppTComp)
4150 ICOM_THIS( ITypeInfoImpl, iface);
4152 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4154 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4155 ITypeComp_AddRef(*ppTComp);
4156 return S_OK;
4159 /* ITypeInfo::GetFuncDesc
4161 * Retrieves the FUNCDESC structure that contains information about a
4162 * specified function.
4165 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4166 LPFUNCDESC *ppFuncDesc)
4168 ICOM_THIS( ITypeInfoImpl, iface);
4169 int i;
4170 TLBFuncDesc * pFDesc;
4171 TRACE("(%p) index %d\n", This, index);
4172 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4174 if(pFDesc){
4175 /* FIXME: must do a copy here */
4176 *ppFuncDesc=&pFDesc->funcdesc;
4177 return S_OK;
4179 return E_INVALIDARG;
4182 /* ITypeInfo::GetVarDesc
4184 * Retrieves a VARDESC structure that describes the specified variable.
4187 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4188 LPVARDESC *ppVarDesc)
4190 ICOM_THIS( ITypeInfoImpl, iface);
4191 int i;
4192 TLBVarDesc * pVDesc;
4193 TRACE("(%p) index %d\n", This, index);
4194 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4196 if(pVDesc){
4197 /* FIXME: must do a copy here */
4198 *ppVarDesc=&pVDesc->vardesc;
4199 return S_OK;
4201 return E_INVALIDARG;
4204 /* ITypeInfo_GetNames
4206 * Retrieves the variable with the specified member ID (or the name of the
4207 * property or method and its parameters) that correspond to the specified
4208 * function ID.
4210 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4211 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4213 ICOM_THIS( ITypeInfoImpl, iface);
4214 TLBFuncDesc * pFDesc;
4215 TLBVarDesc * pVDesc;
4216 int i;
4217 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4218 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4219 if(pFDesc)
4221 /* function found, now return function and parameter names */
4222 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4224 if(!i)
4225 *rgBstrNames=SysAllocString(pFDesc->Name);
4226 else
4227 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4229 *pcNames=i;
4231 else
4233 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4234 if(pVDesc)
4236 *rgBstrNames=SysAllocString(pVDesc->Name);
4237 *pcNames=1;
4239 else
4241 if(This->TypeAttr.cImplTypes &&
4242 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4243 /* recursive search */
4244 ITypeInfo *pTInfo;
4245 HRESULT result;
4246 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4247 &pTInfo);
4248 if(SUCCEEDED(result))
4250 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4251 ITypeInfo_Release(pTInfo);
4252 return result;
4254 WARN("Could not search inherited interface!\n");
4256 else
4258 WARN("no names found\n");
4260 *pcNames=0;
4261 return TYPE_E_ELEMENTNOTFOUND;
4264 return S_OK;
4268 /* ITypeInfo::GetRefTypeOfImplType
4270 * If a type description describes a COM class, it retrieves the type
4271 * description of the implemented interface types. For an interface,
4272 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4273 * if any exist.
4276 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4277 ITypeInfo2 *iface,
4278 UINT index,
4279 HREFTYPE *pRefType)
4281 ICOM_THIS( ITypeInfoImpl, iface);
4282 int(i);
4283 TLBImplType *pImpl = This->impltypelist;
4285 TRACE("(%p) index %d\n", This, index);
4286 if (TRACE_ON(ole)) dump_TypeInfo(This);
4288 if(index==(UINT)-1)
4290 /* only valid on dual interfaces;
4291 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4293 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4295 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4296 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4298 *pRefType = -1;
4300 else
4302 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4303 *pRefType = pImpl->hRef;
4306 else
4308 /* get element n from linked list */
4309 for(i=0; pImpl && i<index; i++)
4311 pImpl = pImpl->next;
4314 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4316 *pRefType = pImpl->hRef;
4318 TRACE("-- 0x%08lx\n", pImpl->hRef );
4321 return S_OK;
4325 /* ITypeInfo::GetImplTypeFlags
4327 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4328 * or base interface in a type description.
4330 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4331 UINT index, INT *pImplTypeFlags)
4333 ICOM_THIS( ITypeInfoImpl, iface);
4334 int i;
4335 TLBImplType *pImpl;
4337 TRACE("(%p) index %d\n", This, index);
4338 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4339 i++, pImpl=pImpl->next)
4341 if(i==index && pImpl){
4342 *pImplTypeFlags=pImpl->implflags;
4343 return S_OK;
4345 *pImplTypeFlags=0;
4346 return TYPE_E_ELEMENTNOTFOUND;
4349 /* GetIDsOfNames
4350 * Maps between member names and member IDs, and parameter names and
4351 * parameter IDs.
4353 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4354 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4356 ICOM_THIS( ITypeInfoImpl, iface);
4357 TLBFuncDesc * pFDesc;
4358 TLBVarDesc * pVDesc;
4359 HRESULT ret=S_OK;
4361 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4362 cNames);
4363 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4364 int i, j;
4365 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4366 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4367 for(i=1; i < cNames; i++){
4368 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4369 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4370 break;
4371 if( j<pFDesc->funcdesc.cParams)
4372 pMemId[i]=j;
4373 else
4374 ret=DISP_E_UNKNOWNNAME;
4376 return ret;
4379 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4380 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4381 if(cNames) *pMemId=pVDesc->vardesc.memid;
4382 return ret;
4385 /* not found, see if this is and interface with an inheritance */
4386 if(This->TypeAttr.cImplTypes &&
4387 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4388 /* recursive search */
4389 ITypeInfo *pTInfo;
4390 ret=ITypeInfo_GetRefTypeInfo(iface,
4391 This->impltypelist->hRef, &pTInfo);
4392 if(SUCCEEDED(ret)){
4393 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4394 ITypeInfo_Release(pTInfo);
4395 return ret;
4397 WARN("Could not search inherited interface!\n");
4398 } else
4399 WARN("no names found\n");
4400 return DISP_E_UNKNOWNNAME;
4403 /* ITypeInfo::Invoke
4405 * Invokes a method, or accesses a property of an object, that implements the
4406 * interface described by the type description.
4408 DWORD
4409 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4410 DWORD res;
4412 if (TRACE_ON(ole)) {
4413 int i;
4414 TRACE("Calling %p(",func);
4415 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4416 TRACE(")\n");
4419 switch (callconv) {
4420 case CC_STDCALL:
4422 switch (nrargs) {
4423 case 0:
4424 res = func();
4425 break;
4426 case 1:
4427 res = func(args[0]);
4428 break;
4429 case 2:
4430 res = func(args[0],args[1]);
4431 break;
4432 case 3:
4433 res = func(args[0],args[1],args[2]);
4434 break;
4435 case 4:
4436 res = func(args[0],args[1],args[2],args[3]);
4437 break;
4438 case 5:
4439 res = func(args[0],args[1],args[2],args[3],args[4]);
4440 break;
4441 case 6:
4442 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4443 break;
4444 case 7:
4445 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4446 break;
4447 case 8:
4448 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4449 break;
4450 case 9:
4451 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4452 break;
4453 case 10:
4454 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4455 break;
4456 case 11:
4457 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4458 break;
4459 default:
4460 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4461 res = -1;
4462 break;
4464 break;
4465 default:
4466 FIXME("unsupported calling convention %d\n",callconv);
4467 res = -1;
4468 break;
4470 TRACE("returns %08lx\n",res);
4471 return res;
4474 extern int const _argsize(DWORD vt);
4476 /****************************************************************************
4477 * Helper functions for Dispcall / Invoke, which copies one variant
4478 * with target type onto the argument stack.
4480 static HRESULT
4481 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4482 DWORD *argpos, VARIANT *arg, VARTYPE vt
4484 UINT arglen = _argsize(vt)*sizeof(DWORD);
4485 VARTYPE oldvt;
4486 VARIANT va;
4488 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4489 memcpy(argpos,&arg,sizeof(void*));
4490 return S_OK;
4493 if (V_VT(arg) == vt) {
4494 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4495 return S_OK;
4498 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4499 memcpy(argpos, &V_UNION(arg,parray), sizeof(SAFEARRAY*));
4500 return S_OK;
4503 if (vt == VT_VARIANT) {
4504 memcpy(argpos, arg, arglen);
4505 return S_OK;
4507 /* Deref BYREF vars if there is need */
4508 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4509 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4510 return S_OK;
4512 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4513 /* in this context, if the type lib specifies IUnknown*, giving an
4514 IDispatch* is correct; so, don't invoke VariantChangeType */
4515 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4516 return S_OK;
4518 if ((vt == VT_PTR) && tdesc)
4519 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4521 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4522 ITypeInfo *tinfo2 = NULL;
4523 TYPEATTR *tattr = NULL;
4524 HRESULT hres;
4526 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4527 if (hres) {
4528 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4529 "while coercing from vt 0x%x. Copying 4 byte.\n",
4530 tdesc->u.hreftype,V_VT(arg));
4531 memcpy(argpos, &V_UNION(arg,lVal), 4);
4532 return S_OK;
4534 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4535 if( hres )
4537 ERR("GetTypeAttr failed\n");
4538 ITypeInfo_Release(tinfo2);
4539 return hres;
4541 switch (tattr->typekind) {
4542 case TKIND_ENUM:
4543 switch ( V_VT( arg ) ) {
4544 case VT_I2:
4545 *argpos = V_UNION(arg,iVal);
4546 hres = S_OK;
4547 break;
4548 case VT_I4:
4549 memcpy(argpos, &V_UNION(arg,lVal), 4);
4550 hres = S_OK;
4551 break;
4552 default:
4553 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4554 hres = E_FAIL;
4555 break;
4557 break;
4559 case TKIND_ALIAS:
4560 tdesc = &(tattr->tdescAlias);
4561 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4562 break;
4564 case TKIND_INTERFACE:
4565 if (V_VT(arg) == VT_DISPATCH) {
4566 IDispatch *disp;
4567 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4568 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4569 hres = S_OK;
4570 break;
4572 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),
4573 &IID_IDispatch,(LPVOID*)&disp);
4574 if (SUCCEEDED(hres)) {
4575 memcpy(argpos,&disp,4);
4576 IUnknown_Release(V_UNION(arg,pdispVal));
4577 hres = S_OK;
4578 break;
4580 FIXME("Failed to query IDispatch interface from %s while "
4581 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4582 hres = E_FAIL;
4583 break;
4585 if (V_VT(arg) == VT_UNKNOWN) {
4586 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4587 hres = S_OK;
4588 break;
4590 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4591 V_VT(arg),debugstr_guid(&(tattr->guid)));
4592 hres = E_FAIL;
4593 break;
4595 case TKIND_DISPATCH:
4596 if (V_VT(arg) == VT_DISPATCH) {
4597 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4598 hres = S_OK;
4600 else {
4601 hres = E_FAIL;
4602 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4604 break;
4605 case TKIND_RECORD:
4606 FIXME("TKIND_RECORD unhandled.\n");
4607 hres = E_FAIL;
4608 break;
4609 default:
4610 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4611 hres = E_FAIL;
4612 break;
4614 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4615 ITypeInfo_Release(tinfo2);
4616 return hres;
4619 oldvt = V_VT(arg);
4620 VariantInit(&va);
4621 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4622 memcpy(argpos,&V_UNION(&va,lVal), arglen);
4623 FIXME("Should not use VariantChangeType here."
4624 " (conversion from 0x%x -> 0x%x) %08lx\n",
4625 V_VT(arg), vt, *argpos
4627 return S_OK;
4629 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4630 return E_FAIL;
4633 /***********************************************************************
4634 * DispCallFunc (OLEAUT32.@)
4636 HRESULT WINAPI
4637 DispCallFunc(
4638 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4639 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4641 int i, argsize, argspos;
4642 DWORD *args;
4643 HRESULT hres;
4645 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4646 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4648 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4649 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4650 argsize = 1;
4651 for (i=0;i<cActuals;i++) {
4652 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4653 dump_Variant(prgpvarg[i]);
4654 argsize += _argsize(prgvt[i]);
4656 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4657 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4658 argspos = 1;
4659 for (i=0;i<cActuals;i++) {
4660 VARIANT *arg = prgpvarg[i];
4661 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4662 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4663 argspos += _argsize(prgvt[i]);
4666 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4668 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4669 hres=S_OK;
4671 else
4673 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4674 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4675 FIXME("Method returned %lx\n",hres);
4677 HeapFree(GetProcessHeap(),0,args);
4678 return hres;
4681 static HRESULT WINAPI ITypeInfo_fnInvoke(
4682 ITypeInfo2 *iface,
4683 VOID *pIUnk,
4684 MEMBERID memid,
4685 UINT16 dwFlags,
4686 DISPPARAMS *pDispParams,
4687 VARIANT *pVarResult,
4688 EXCEPINFO *pExcepInfo,
4689 UINT *pArgErr)
4691 ICOM_THIS( ITypeInfoImpl, iface);
4692 TLBFuncDesc * pFDesc;
4693 TLBVarDesc * pVDesc;
4694 int i;
4695 HRESULT hres;
4697 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4698 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4700 dump_DispParms(pDispParams);
4702 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4703 if (pFDesc->funcdesc.memid == memid) {
4704 if (pFDesc->funcdesc.invkind & dwFlags)
4705 break;
4708 if (pFDesc) {
4709 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4710 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4711 switch (pFDesc->funcdesc.funckind) {
4712 case FUNC_PUREVIRTUAL:
4713 case FUNC_VIRTUAL: {
4714 DWORD res;
4715 int numargs, numargs2, argspos, args2pos;
4716 DWORD *args , *args2;
4719 numargs = 1; numargs2 = 0;
4720 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4721 if (i<pDispParams->cArgs)
4722 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4723 else {
4724 numargs += 1; /* sizeof(lpvoid) */
4725 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4729 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4730 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4732 args[0] = (DWORD)pIUnk;
4733 argspos = 1; args2pos = 0;
4734 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4735 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4736 if (i<pDispParams->cArgs) {
4737 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4738 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4739 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4740 if (FAILED(hres)) return hres;
4741 argspos += arglen;
4742 } else {
4743 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4744 if (tdesc->vt != VT_PTR)
4745 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4746 /*FIXME: give pointers for the rest, so propertyget works*/
4747 args[argspos] = (DWORD)&args2[args2pos];
4749 /* If pointer to variant, pass reference it. */
4750 if ((tdesc->vt == VT_PTR) &&
4751 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4752 pVarResult
4754 args[argspos]= (DWORD)pVarResult;
4755 argspos += 1;
4756 args2pos += arglen;
4759 if (pFDesc->funcdesc.cParamsOpt)
4760 FIXME("Does not support optional parameters (%d)\n",
4761 pFDesc->funcdesc.cParamsOpt
4764 res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4],
4765 pFDesc->funcdesc.callconv,
4766 numargs,
4767 args
4769 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4770 args2pos = 0;
4771 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4772 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4773 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4774 TYPEDESC i4_tdesc;
4775 i4_tdesc.vt = VT_I4;
4777 /* If we are a pointer to a variant, we are done already */
4778 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4779 continue;
4781 VariantInit(pVarResult);
4782 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4784 if (tdesc->vt == VT_PTR)
4785 tdesc = tdesc->u.lptdesc;
4786 if (tdesc->vt == VT_USERDEFINED) {
4787 ITypeInfo *tinfo2;
4788 TYPEATTR *tattr;
4790 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4791 if (hres) {
4792 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4793 return E_FAIL;
4795 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4796 switch (tattr->typekind) {
4797 case TKIND_ENUM:
4798 /* force the return type to be VT_I4 */
4799 tdesc = &i4_tdesc;
4800 break;
4801 case TKIND_ALIAS:
4802 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4803 tdesc = &(tattr->tdescAlias);
4804 break;
4806 case TKIND_INTERFACE:
4807 FIXME("TKIND_INTERFACE unhandled.\n");
4808 break;
4809 case TKIND_DISPATCH:
4810 FIXME("TKIND_DISPATCH unhandled.\n");
4811 break;
4812 case TKIND_RECORD:
4813 FIXME("TKIND_RECORD unhandled.\n");
4814 break;
4815 default:
4816 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4817 break;
4819 ITypeInfo_Release(tinfo2);
4821 V_VT(pVarResult) = tdesc->vt;
4823 /* HACK: VB5 likes this.
4824 * I do not know why. There is 1 example in MSDN which uses
4825 * this which appears broken (mixes int vals and
4826 * IDispatch*.).
4828 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4829 V_VT(pVarResult) = VT_DISPATCH;
4830 TRACE("storing into variant:\n");
4831 dump_Variant(pVarResult);
4832 args2pos += arglen;
4835 HeapFree(GetProcessHeap(),0,args2);
4836 HeapFree(GetProcessHeap(),0,args);
4837 return S_OK;
4839 case FUNC_DISPATCH: {
4840 IDispatch *disp;
4841 HRESULT hr;
4843 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4844 if (hr) {
4845 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4846 return hr;
4848 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4849 hr = IDispatch_Invoke(
4850 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4851 pVarResult,pExcepInfo,pArgErr
4853 if (hr)
4854 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4855 IDispatch_Release(disp);
4856 return hr;
4858 default:
4859 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4860 return E_FAIL;
4862 } else {
4863 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4864 if (pVDesc->vardesc.memid == memid) {
4865 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4866 dump_TLBVarDesc(pVDesc);
4867 break;
4871 /* not found, look for it in inherited interfaces */
4872 if (This->TypeAttr.cImplTypes &&
4873 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4874 /* recursive search */
4875 ITypeInfo *pTInfo;
4876 HRESULT hr;
4877 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4878 if(SUCCEEDED(hr)){
4879 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4880 ITypeInfo_Release(pTInfo);
4881 return hr;
4883 WARN("Could not search inherited interface!\n");
4885 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4886 return DISP_E_MEMBERNOTFOUND;
4889 /* ITypeInfo::GetDocumentation
4891 * Retrieves the documentation string, the complete Help file name and path,
4892 * and the context ID for the Help topic for a specified type description.
4894 * (Can be tested by the Visual Basic Editor in Word for instance.)
4896 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4897 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4898 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4900 ICOM_THIS( ITypeInfoImpl, iface);
4901 TLBFuncDesc * pFDesc;
4902 TLBVarDesc * pVDesc;
4903 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4904 " HelpContext(%p) HelpFile(%p)\n",
4905 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4906 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4907 if(pBstrName)
4908 *pBstrName=SysAllocString(This->Name);
4909 if(pBstrDocString)
4910 *pBstrDocString=SysAllocString(This->DocString);
4911 if(pdwHelpContext)
4912 *pdwHelpContext=This->dwHelpContext;
4913 if(pBstrHelpFile)
4914 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4915 return S_OK;
4916 }else {/* for a member */
4917 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4918 if(pFDesc->funcdesc.memid==memid){
4919 if(pBstrName)
4920 *pBstrName = SysAllocString(pFDesc->Name);
4921 if(pBstrDocString)
4922 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4923 if(pdwHelpContext)
4924 *pdwHelpContext=pFDesc->helpcontext;
4925 return S_OK;
4927 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4928 if(pVDesc->vardesc.memid==memid){
4929 if(pBstrName)
4930 *pBstrName = SysAllocString(pVDesc->Name);
4931 if(pBstrDocString)
4932 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4933 if(pdwHelpContext)
4934 *pdwHelpContext=pVDesc->HelpContext;
4935 return S_OK;
4938 return TYPE_E_ELEMENTNOTFOUND;
4941 /* ITypeInfo::GetDllEntry
4943 * Retrieves a description or specification of an entry point for a function
4944 * in a DLL.
4946 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4947 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4948 WORD *pwOrdinal)
4950 ICOM_THIS( ITypeInfoImpl, iface);
4951 TLBFuncDesc *pFDesc;
4953 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4955 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4956 if(pFDesc->funcdesc.memid==memid){
4957 dump_TypeInfo(This);
4958 dump_TLBFuncDescOne(pFDesc);
4960 /* FIXME: This is wrong, but how do you find that out? */
4961 if (pBstrDllName) {
4962 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4963 *pBstrDllName = SysAllocString(oleaut32W);
4966 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4967 if (pBstrName)
4968 *pBstrName = SysAllocString(pFDesc->Entry);
4969 if (pwOrdinal)
4970 *pwOrdinal = -1;
4971 return S_OK;
4973 if (pBstrName)
4974 *pBstrName = NULL;
4975 if (pwOrdinal)
4976 *pwOrdinal = (DWORD)pFDesc->Entry;
4977 return S_OK;
4979 return E_FAIL;
4982 /* ITypeInfo::GetRefTypeInfo
4984 * If a type description references other type descriptions, it retrieves
4985 * the referenced type descriptions.
4987 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4988 ITypeInfo2 *iface,
4989 HREFTYPE hRefType,
4990 ITypeInfo **ppTInfo)
4992 ICOM_THIS( ITypeInfoImpl, iface);
4993 HRESULT result = E_FAIL;
4996 if (hRefType == -1 &&
4997 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4998 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5000 /* when we meet a DUAL dispinterface, we must create the interface
5001 * version of it.
5003 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5006 /* the interface version contains the same information as the dispinterface
5007 * copy the contents of the structs.
5009 *pTypeInfoImpl = *This;
5010 pTypeInfoImpl->ref = 1;
5012 /* change the type to interface */
5013 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5015 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5017 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5019 result = S_OK;
5021 } else {
5022 TLBRefType *pRefType;
5023 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5024 if(pRefType->reference == hRefType)
5025 break;
5027 if(!pRefType)
5028 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5029 if(pRefType && hRefType != -1) {
5030 ITypeLib *pTLib = NULL;
5032 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5033 int Index;
5034 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5035 } else {
5036 if(pRefType->pImpTLInfo->pImpTypeLib) {
5037 TRACE("typeinfo in imported typelib that is already loaded\n");
5038 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5039 ITypeLib2_AddRef((ITypeLib*) pTLib);
5040 result = S_OK;
5041 } else {
5042 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5043 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5044 pRefType->pImpTLInfo->wVersionMajor,
5045 pRefType->pImpTLInfo->wVersionMinor,
5046 pRefType->pImpTLInfo->lcid,
5047 &pTLib);
5049 if(!SUCCEEDED(result)) {
5050 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5051 result=LoadTypeLib(libnam, &pTLib);
5052 SysFreeString(libnam);
5054 if(SUCCEEDED(result)) {
5055 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5056 ITypeLib2_AddRef(pTLib);
5060 if(SUCCEEDED(result)) {
5061 if(pRefType->index == TLB_REF_USE_GUID)
5062 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5063 &pRefType->guid,
5064 ppTInfo);
5065 else
5066 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5067 ppTInfo);
5069 if (pTLib != NULL)
5070 ITypeLib2_Release(pTLib);
5074 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5075 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5076 return result;
5079 /* ITypeInfo::AddressOfMember
5081 * Retrieves the addresses of static functions or variables, such as those
5082 * defined in a DLL.
5084 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5085 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5087 ICOM_THIS( ITypeInfoImpl, iface);
5088 FIXME("(%p) stub!\n", This);
5089 return S_OK;
5092 /* ITypeInfo::CreateInstance
5094 * Creates a new instance of a type that describes a component object class
5095 * (coclass).
5097 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5098 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5100 ICOM_THIS( ITypeInfoImpl, iface);
5101 FIXME("(%p) stub!\n", This);
5102 return S_OK;
5105 /* ITypeInfo::GetMops
5107 * Retrieves marshalling information.
5109 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5110 BSTR *pBstrMops)
5112 ICOM_THIS( ITypeInfoImpl, iface);
5113 FIXME("(%p) stub!\n", This);
5114 return S_OK;
5117 /* ITypeInfo::GetContainingTypeLib
5119 * Retrieves the containing type library and the index of the type description
5120 * within that type library.
5122 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5123 ITypeLib * *ppTLib, UINT *pIndex)
5125 ICOM_THIS( ITypeInfoImpl, iface);
5127 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5128 if (pIndex) {
5129 *pIndex=This->index;
5130 TRACE("returning pIndex=%d\n", *pIndex);
5133 if (ppTLib) {
5134 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5135 ITypeLib2_AddRef(*ppTLib);
5136 TRACE("returning ppTLib=%p\n", *ppTLib);
5139 return S_OK;
5142 /* ITypeInfo::ReleaseTypeAttr
5144 * Releases a TYPEATTR previously returned by GetTypeAttr.
5147 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5148 TYPEATTR* pTypeAttr)
5150 ICOM_THIS( ITypeInfoImpl, iface);
5151 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5154 /* ITypeInfo::ReleaseFuncDesc
5156 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5158 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5159 ITypeInfo2 *iface,
5160 FUNCDESC *pFuncDesc)
5162 ICOM_THIS( ITypeInfoImpl, iface);
5163 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5166 /* ITypeInfo::ReleaseVarDesc
5168 * Releases a VARDESC previously returned by GetVarDesc.
5170 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5171 VARDESC *pVarDesc)
5173 ICOM_THIS( ITypeInfoImpl, iface);
5174 TRACE("(%p)->(%p)\n", This, pVarDesc);
5177 /* ITypeInfo2::GetTypeKind
5179 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5182 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5183 TYPEKIND *pTypeKind)
5185 ICOM_THIS( ITypeInfoImpl, iface);
5186 *pTypeKind=This->TypeAttr.typekind;
5187 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5188 return S_OK;
5191 /* ITypeInfo2::GetTypeFlags
5193 * Returns the type flags without any allocations. This returns a DWORD type
5194 * flag, which expands the type flags without growing the TYPEATTR (type
5195 * attribute).
5198 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5200 ICOM_THIS( ITypeInfoImpl, iface);
5201 *pTypeFlags=This->TypeAttr.wTypeFlags;
5202 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5203 return S_OK;
5206 /* ITypeInfo2::GetFuncIndexOfMemId
5207 * Binds to a specific member based on a known DISPID, where the member name
5208 * is not known (for example, when binding to a default member).
5211 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5212 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5214 ICOM_THIS( ITypeInfoImpl, iface);
5215 TLBFuncDesc *pFuncInfo;
5216 int i;
5217 HRESULT result;
5218 /* FIXME: should check for invKind??? */
5219 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
5220 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
5221 if(pFuncInfo){
5222 *pFuncIndex=i;
5223 result= S_OK;
5224 }else{
5225 *pFuncIndex=0;
5226 result=E_INVALIDARG;
5228 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5229 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
5230 return result;
5233 /* TypeInfo2::GetVarIndexOfMemId
5235 * Binds to a specific member based on a known DISPID, where the member name
5236 * is not known (for example, when binding to a default member).
5239 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5240 MEMBERID memid, UINT *pVarIndex)
5242 ICOM_THIS( ITypeInfoImpl, iface);
5243 TLBVarDesc *pVarInfo;
5244 int i;
5245 HRESULT result;
5246 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5247 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5249 if(pVarInfo){
5250 *pVarIndex=i;
5251 result= S_OK;
5252 }else{
5253 *pVarIndex=0;
5254 result=E_INVALIDARG;
5256 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5257 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
5258 return result;
5261 /* ITypeInfo2::GetCustData
5263 * Gets the custom data
5265 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5266 ITypeInfo2 * iface,
5267 REFGUID guid,
5268 VARIANT *pVarVal)
5270 ICOM_THIS( ITypeInfoImpl, iface);
5271 TLBCustData *pCData;
5273 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5274 if( IsEqualIID(guid, &pCData->guid)) break;
5276 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5278 if(pCData)
5280 VariantInit( pVarVal);
5281 VariantCopy( pVarVal, &pCData->data);
5282 return S_OK;
5284 return E_INVALIDARG; /* FIXME: correct? */
5287 /* ITypeInfo2::GetFuncCustData
5289 * Gets the custom data
5291 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5292 ITypeInfo2 * iface,
5293 UINT index,
5294 REFGUID guid,
5295 VARIANT *pVarVal)
5297 ICOM_THIS( ITypeInfoImpl, iface);
5298 TLBCustData *pCData=NULL;
5299 TLBFuncDesc * pFDesc;
5300 int i;
5301 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5302 pFDesc=pFDesc->next);
5304 if(pFDesc)
5305 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5306 if( IsEqualIID(guid, &pCData->guid)) break;
5308 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5310 if(pCData){
5311 VariantInit( pVarVal);
5312 VariantCopy( pVarVal, &pCData->data);
5313 return S_OK;
5315 return E_INVALIDARG; /* FIXME: correct? */
5318 /* ITypeInfo2::GetParamCustData
5320 * Gets the custom data
5322 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5323 ITypeInfo2 * iface,
5324 UINT indexFunc,
5325 UINT indexParam,
5326 REFGUID guid,
5327 VARIANT *pVarVal)
5329 ICOM_THIS( ITypeInfoImpl, iface);
5330 TLBCustData *pCData=NULL;
5331 TLBFuncDesc * pFDesc;
5332 int i;
5334 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5336 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5337 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5338 pCData = pCData->next)
5339 if( IsEqualIID(guid, &pCData->guid)) break;
5341 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5343 if(pCData)
5345 VariantInit( pVarVal);
5346 VariantCopy( pVarVal, &pCData->data);
5347 return S_OK;
5349 return E_INVALIDARG; /* FIXME: correct? */
5352 /* ITypeInfo2::GetVarCustData
5354 * Gets the custom data
5356 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5357 ITypeInfo2 * iface,
5358 UINT index,
5359 REFGUID guid,
5360 VARIANT *pVarVal)
5362 ICOM_THIS( ITypeInfoImpl, iface);
5363 TLBCustData *pCData=NULL;
5364 TLBVarDesc * pVDesc;
5365 int i;
5367 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5369 if(pVDesc)
5371 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5373 if( IsEqualIID(guid, &pCData->guid)) break;
5377 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5379 if(pCData)
5381 VariantInit( pVarVal);
5382 VariantCopy( pVarVal, &pCData->data);
5383 return S_OK;
5385 return E_INVALIDARG; /* FIXME: correct? */
5388 /* ITypeInfo2::GetImplCustData
5390 * Gets the custom data
5392 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5393 ITypeInfo2 * iface,
5394 UINT index,
5395 REFGUID guid,
5396 VARIANT *pVarVal)
5398 ICOM_THIS( ITypeInfoImpl, iface);
5399 TLBCustData *pCData=NULL;
5400 TLBImplType * pRDesc;
5401 int i;
5403 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5405 if(pRDesc)
5407 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5409 if( IsEqualIID(guid, &pCData->guid)) break;
5413 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5415 if(pCData)
5417 VariantInit( pVarVal);
5418 VariantCopy( pVarVal, &pCData->data);
5419 return S_OK;
5421 return E_INVALIDARG; /* FIXME: correct? */
5424 /* ITypeInfo2::GetDocumentation2
5426 * Retrieves the documentation string, the complete Help file name and path,
5427 * the localization context to use, and the context ID for the library Help
5428 * topic in the Help file.
5431 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5432 ITypeInfo2 * iface,
5433 MEMBERID memid,
5434 LCID lcid,
5435 BSTR *pbstrHelpString,
5436 DWORD *pdwHelpStringContext,
5437 BSTR *pbstrHelpStringDll)
5439 ICOM_THIS( ITypeInfoImpl, iface);
5440 TLBFuncDesc * pFDesc;
5441 TLBVarDesc * pVDesc;
5442 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5443 "HelpStringContext(%p) HelpStringDll(%p)\n",
5444 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5445 pbstrHelpStringDll );
5446 /* the help string should be obtained from the helpstringdll,
5447 * using the _DLLGetDocumentation function, based on the supplied
5448 * lcid. Nice to do sometime...
5450 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5451 if(pbstrHelpString)
5452 *pbstrHelpString=SysAllocString(This->Name);
5453 if(pdwHelpStringContext)
5454 *pdwHelpStringContext=This->dwHelpStringContext;
5455 if(pbstrHelpStringDll)
5456 *pbstrHelpStringDll=
5457 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5458 return S_OK;
5459 }else {/* for a member */
5460 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5461 if(pFDesc->funcdesc.memid==memid){
5462 if(pbstrHelpString)
5463 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5464 if(pdwHelpStringContext)
5465 *pdwHelpStringContext=pFDesc->HelpStringContext;
5466 if(pbstrHelpStringDll)
5467 *pbstrHelpStringDll=
5468 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5469 return S_OK;
5471 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5472 if(pVDesc->vardesc.memid==memid){
5473 if(pbstrHelpString)
5474 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5475 if(pdwHelpStringContext)
5476 *pdwHelpStringContext=pVDesc->HelpStringContext;
5477 if(pbstrHelpStringDll)
5478 *pbstrHelpStringDll=
5479 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5480 return S_OK;
5483 return TYPE_E_ELEMENTNOTFOUND;
5486 /* ITypeInfo2::GetAllCustData
5488 * Gets all custom data items for the Type info.
5491 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5492 ITypeInfo2 * iface,
5493 CUSTDATA *pCustData)
5495 ICOM_THIS( ITypeInfoImpl, iface);
5496 TLBCustData *pCData;
5497 int i;
5499 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5501 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5502 if(pCustData->prgCustData ){
5503 pCustData->cCustData=This->ctCustData;
5504 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5505 pCustData->prgCustData[i].guid=pCData->guid;
5506 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5508 }else{
5509 ERR(" OUT OF MEMORY! \n");
5510 return E_OUTOFMEMORY;
5512 return S_OK;
5515 /* ITypeInfo2::GetAllFuncCustData
5517 * Gets all custom data items for the specified Function
5520 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5521 ITypeInfo2 * iface,
5522 UINT index,
5523 CUSTDATA *pCustData)
5525 ICOM_THIS( ITypeInfoImpl, iface);
5526 TLBCustData *pCData;
5527 TLBFuncDesc * pFDesc;
5528 int i;
5529 TRACE("(%p) index %d\n", This, index);
5530 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5531 pFDesc=pFDesc->next)
5533 if(pFDesc){
5534 pCustData->prgCustData =
5535 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5536 if(pCustData->prgCustData ){
5537 pCustData->cCustData=pFDesc->ctCustData;
5538 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5539 pCData = pCData->next){
5540 pCustData->prgCustData[i].guid=pCData->guid;
5541 VariantCopy(& pCustData->prgCustData[i].varValue,
5542 & pCData->data);
5544 }else{
5545 ERR(" OUT OF MEMORY! \n");
5546 return E_OUTOFMEMORY;
5548 return S_OK;
5550 return TYPE_E_ELEMENTNOTFOUND;
5553 /* ITypeInfo2::GetAllParamCustData
5555 * Gets all custom data items for the Functions
5558 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5559 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5561 ICOM_THIS( ITypeInfoImpl, iface);
5562 TLBCustData *pCData=NULL;
5563 TLBFuncDesc * pFDesc;
5564 int i;
5565 TRACE("(%p) index %d\n", This, indexFunc);
5566 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5567 pFDesc=pFDesc->next)
5569 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5570 pCustData->prgCustData =
5571 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5572 sizeof(CUSTDATAITEM));
5573 if(pCustData->prgCustData ){
5574 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5575 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5576 pCData; i++, pCData = pCData->next){
5577 pCustData->prgCustData[i].guid=pCData->guid;
5578 VariantCopy(& pCustData->prgCustData[i].varValue,
5579 & pCData->data);
5581 }else{
5582 ERR(" OUT OF MEMORY! \n");
5583 return E_OUTOFMEMORY;
5585 return S_OK;
5587 return TYPE_E_ELEMENTNOTFOUND;
5590 /* ITypeInfo2::GetAllVarCustData
5592 * Gets all custom data items for the specified Variable
5595 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5596 UINT index, CUSTDATA *pCustData)
5598 ICOM_THIS( ITypeInfoImpl, iface);
5599 TLBCustData *pCData;
5600 TLBVarDesc * pVDesc;
5601 int i;
5602 TRACE("(%p) index %d\n", This, index);
5603 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5604 pVDesc=pVDesc->next)
5606 if(pVDesc){
5607 pCustData->prgCustData =
5608 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5609 if(pCustData->prgCustData ){
5610 pCustData->cCustData=pVDesc->ctCustData;
5611 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5612 pCData = pCData->next){
5613 pCustData->prgCustData[i].guid=pCData->guid;
5614 VariantCopy(& pCustData->prgCustData[i].varValue,
5615 & pCData->data);
5617 }else{
5618 ERR(" OUT OF MEMORY! \n");
5619 return E_OUTOFMEMORY;
5621 return S_OK;
5623 return TYPE_E_ELEMENTNOTFOUND;
5626 /* ITypeInfo2::GetAllImplCustData
5628 * Gets all custom data items for the specified implementation type
5631 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5632 ITypeInfo2 * iface,
5633 UINT index,
5634 CUSTDATA *pCustData)
5636 ICOM_THIS( ITypeInfoImpl, iface);
5637 TLBCustData *pCData;
5638 TLBImplType * pRDesc;
5639 int i;
5640 TRACE("(%p) index %d\n", This, index);
5641 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5642 pRDesc=pRDesc->next)
5644 if(pRDesc){
5645 pCustData->prgCustData =
5646 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5647 if(pCustData->prgCustData ){
5648 pCustData->cCustData=pRDesc->ctCustData;
5649 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5650 pCData = pCData->next){
5651 pCustData->prgCustData[i].guid=pCData->guid;
5652 VariantCopy(& pCustData->prgCustData[i].varValue,
5653 & pCData->data);
5655 }else{
5656 ERR(" OUT OF MEMORY! \n");
5657 return E_OUTOFMEMORY;
5659 return S_OK;
5661 return TYPE_E_ELEMENTNOTFOUND;
5664 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5666 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5668 ITypeInfo_fnQueryInterface,
5669 ITypeInfo_fnAddRef,
5670 ITypeInfo_fnRelease,
5672 ITypeInfo_fnGetTypeAttr,
5673 ITypeInfo_fnGetTypeComp,
5674 ITypeInfo_fnGetFuncDesc,
5675 ITypeInfo_fnGetVarDesc,
5676 ITypeInfo_fnGetNames,
5677 ITypeInfo_fnGetRefTypeOfImplType,
5678 ITypeInfo_fnGetImplTypeFlags,
5679 ITypeInfo_fnGetIDsOfNames,
5680 ITypeInfo_fnInvoke,
5681 ITypeInfo_fnGetDocumentation,
5682 ITypeInfo_fnGetDllEntry,
5683 ITypeInfo_fnGetRefTypeInfo,
5684 ITypeInfo_fnAddressOfMember,
5685 ITypeInfo_fnCreateInstance,
5686 ITypeInfo_fnGetMops,
5687 ITypeInfo_fnGetContainingTypeLib,
5688 ITypeInfo_fnReleaseTypeAttr,
5689 ITypeInfo_fnReleaseFuncDesc,
5690 ITypeInfo_fnReleaseVarDesc,
5692 ITypeInfo2_fnGetTypeKind,
5693 ITypeInfo2_fnGetTypeFlags,
5694 ITypeInfo2_fnGetFuncIndexOfMemId,
5695 ITypeInfo2_fnGetVarIndexOfMemId,
5696 ITypeInfo2_fnGetCustData,
5697 ITypeInfo2_fnGetFuncCustData,
5698 ITypeInfo2_fnGetParamCustData,
5699 ITypeInfo2_fnGetVarCustData,
5700 ITypeInfo2_fnGetImplTypeCustData,
5701 ITypeInfo2_fnGetDocumentation2,
5702 ITypeInfo2_fnGetAllCustData,
5703 ITypeInfo2_fnGetAllFuncCustData,
5704 ITypeInfo2_fnGetAllParamCustData,
5705 ITypeInfo2_fnGetAllVarCustData,
5706 ITypeInfo2_fnGetAllImplTypeCustData,
5709 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5711 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5713 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5716 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5718 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5720 return ITypeInfo_AddRef((ITypeInfo *)This);
5723 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5725 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5727 return ITypeInfo_Release((ITypeInfo *)This);
5730 static HRESULT WINAPI ITypeComp_fnBind(
5731 ITypeComp * iface,
5732 OLECHAR * szName,
5733 unsigned long lHash,
5734 unsigned short wFlags,
5735 ITypeInfo ** ppTInfo,
5736 DESCKIND * pDescKind,
5737 BINDPTR * pBindPtr)
5739 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5740 TLBFuncDesc * pFDesc;
5741 TLBVarDesc * pVDesc;
5743 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5745 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5746 if (pFDesc->funcdesc.invkind & wFlags)
5747 if (!strcmpW(pFDesc->Name, szName)) {
5748 break;
5751 if (pFDesc)
5753 *pDescKind = DESCKIND_FUNCDESC;
5754 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5755 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5756 return S_OK;
5757 } else {
5758 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5760 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5761 if (!strcmpW(pVDesc->Name, szName)) {
5762 *pDescKind = DESCKIND_VARDESC;
5763 pBindPtr->lpvardesc = &pVDesc->vardesc;
5764 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5765 return S_OK;
5770 /* not found, look for it in inherited interfaces */
5771 if (This->TypeAttr.cImplTypes &&
5772 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
5773 /* recursive search */
5774 ITypeInfo *pTInfo;
5775 ITypeComp *pTComp;
5776 HRESULT hr;
5777 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5778 if (SUCCEEDED(hr))
5780 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5781 ITypeInfo_Release(pTInfo);
5783 if (SUCCEEDED(hr))
5785 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5786 ITypeComp_Release(pTComp);
5787 return hr;
5789 WARN("Could not search inherited interface!\n");
5791 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5792 *pDescKind = DESCKIND_NONE;
5793 pBindPtr->lpfuncdesc = NULL;
5794 *ppTInfo = NULL;
5795 return DISP_E_MEMBERNOTFOUND;
5798 static HRESULT WINAPI ITypeComp_fnBindType(
5799 ITypeComp * iface,
5800 OLECHAR * szName,
5801 unsigned long lHash,
5802 ITypeInfo ** ppTInfo,
5803 ITypeComp ** ppTComp)
5805 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5807 /* strange behaviour (does nothing) but like the
5808 * original */
5810 if (!ppTInfo || !ppTComp)
5811 return E_POINTER;
5813 *ppTInfo = NULL;
5814 *ppTComp = NULL;
5816 return S_OK;
5819 static ICOM_VTABLE(ITypeComp) tcompvt =
5821 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5823 ITypeComp_fnQueryInterface,
5824 ITypeComp_fnAddRef,
5825 ITypeComp_fnRelease,
5827 ITypeComp_fnBind,
5828 ITypeComp_fnBindType