Added LGPL standard comment, and copyright notices where necessary.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob2c3fb6f7301556094ff807464e2c2ce87ae84188
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"
57 #include <stdlib.h>
58 #include <string.h>
59 #include <stdio.h>
60 #include <ctype.h>
62 #include "winerror.h"
63 #include "winnls.h" /* for PRIMARYLANGID */
64 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
65 #include "winuser.h"
67 #include "wine/unicode.h"
68 #include "wine/obj_base.h"
69 #include "heap.h"
70 #include "ole2disp.h"
71 #include "typelib.h"
72 #include "wine/debug.h"
73 #include "ntddk.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78 /****************************************************************************
79 * QueryPathOfRegTypeLib [TYPELIB.14]
81 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
82 * RETURNS
83 * path of typelib
85 HRESULT WINAPI
86 QueryPathOfRegTypeLib16(
87 REFGUID guid, /* [in] referenced guid */
88 WORD wMaj, /* [in] major version */
89 WORD wMin, /* [in] minor version */
90 LCID lcid, /* [in] locale id */
91 LPBSTR16 path /* [out] path of typelib */
92 ) {
93 char xguid[80];
94 char typelibkey[100],pathname[260];
95 DWORD plen;
97 TRACE("\n");
99 if (HIWORD(guid)) {
100 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
101 guid->Data1, guid->Data2, guid->Data3,
102 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
103 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
104 wMaj,wMin,lcid);
105 } else {
106 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
107 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
108 return E_FAIL;
110 plen = sizeof(pathname);
111 if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
112 /* try again without lang specific id */
113 if (SUBLANGID(lcid))
114 return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
115 FIXME("key %s not found\n",typelibkey);
116 return E_FAIL;
118 *path = SysAllocString16(pathname);
119 return S_OK;
122 /****************************************************************************
123 * QueryPathOfRegTypeLib [OLEAUT32.164]
124 * RETURNS
125 * path of typelib
127 HRESULT WINAPI
128 QueryPathOfRegTypeLib(
129 REFGUID guid, /* [in] referenced guid */
130 WORD wMaj, /* [in] major version */
131 WORD wMin, /* [in] minor version */
132 LCID lcid, /* [in] locale id */
133 LPBSTR path ) /* [out] path of typelib */
135 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
136 string termination character on output strings */
138 HRESULT hr = E_FAIL;
140 DWORD dwPathLen = _MAX_PATH;
141 LCID myLCID = lcid;
143 char szXGUID[80];
144 char szTypeLibKey[100];
145 char szPath[dwPathLen];
147 if ( !HIWORD(guid) )
149 sprintf(szXGUID,
150 "<guid 0x%08lx>",
151 (DWORD) guid);
153 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
154 return E_FAIL;
157 while (hr != S_OK)
159 sprintf(szTypeLibKey,
160 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
161 guid->Data1, guid->Data2, guid->Data3,
162 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
163 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
164 wMaj,
165 wMin,
166 myLCID);
168 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
170 if (!lcid)
171 break;
172 else if (myLCID == lcid)
174 /* try with sub-langid */
175 myLCID = SUBLANGID(lcid);
177 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
179 /* try with system langid */
180 myLCID = 0;
182 else
184 break;
187 else
189 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
190 BSTR bstrPath = SysAllocStringLen(NULL,len);
192 MultiByteToWideChar(CP_ACP,
193 MB_PRECOMPOSED,
194 szPath,
195 dwPathLen,
196 bstrPath,
197 len);
198 *path = bstrPath;
199 hr = S_OK;
203 if (hr != S_OK)
204 TRACE_(typelib)("%s not found\n", szTypeLibKey);
206 return hr;
209 /******************************************************************************
210 * CreateTypeLib [OLEAUT32.160] creates a typelib
212 * RETURNS
213 * Success: S_OK
214 * Failure: Status
216 HRESULT WINAPI CreateTypeLib(
217 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
219 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
220 return E_FAIL;
222 /******************************************************************************
223 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
224 * NOTES
225 * Docs: OLECHAR FAR* szFile
226 * Docs: iTypeLib FAR* FAR* pptLib
228 * RETURNS
229 * Success: S_OK
230 * Failure: Status
232 HRESULT WINAPI LoadTypeLib16(
233 LPOLESTR szFile, /* [in] Name of file to load from */
234 ITypeLib** pptLib) /* [out] Pointer to pointer to loaded type library */
236 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
238 if (pptLib!=0)
239 *pptLib=0;
241 return E_FAIL;
244 /******************************************************************************
245 * LoadTypeLib [OLEAUT32.161]
246 * Loads and registers a type library
247 * NOTES
248 * Docs: OLECHAR FAR* szFile
249 * Docs: iTypeLib FAR* FAR* pptLib
251 * RETURNS
252 * Success: S_OK
253 * Failure: Status
255 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
257 HRESULT WINAPI LoadTypeLib(
258 const OLECHAR *szFile,/* [in] Name of file to load from */
259 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
261 TRACE("\n");
262 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
265 /******************************************************************************
266 * LoadTypeLibEx [OLEAUT32.183]
267 * Loads and optionally registers a type library
269 * RETURNS
270 * Success: S_OK
271 * Failure: Status
273 HRESULT WINAPI LoadTypeLibEx(
274 LPCOLESTR szFile, /* [in] Name of file to load from */
275 REGKIND regkind, /* [in] Specify kind of registration */
276 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
278 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
279 WCHAR *pIndexStr;
280 HRESULT res;
281 INT index = 1;
282 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
284 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
285 NULL)) {
287 /* Look for a trailing '\\' followed by an index */
288 pIndexStr = strrchrW(szFile, '\\');
289 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
290 index = wcstol(pIndexStr, NULL, 10);
291 memcpy(szFileCopy, szFile,
292 (pIndexStr - szFile - 1) * sizeof(WCHAR));
293 szFileCopy[pIndexStr - szFile - 1] = '\0';
294 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
295 szPath,NULL))
296 return TYPE_E_CANTLOADLIBRARY;
297 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
298 return TYPE_E_CANTLOADLIBRARY;
299 } else
300 return TYPE_E_CANTLOADLIBRARY;
303 TRACE("File %s index %d\n", debugstr_w(szPath), index);
305 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
307 if (SUCCEEDED(res))
308 switch(regkind)
310 case REGKIND_DEFAULT:
311 /* FIXME: is this correct? */
312 if (!szFile || !szFile[0] ||
313 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
314 break;
315 /* else fall-through */
316 case REGKIND_REGISTER:
317 /* FIXME: Help path? */
318 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
320 IUnknown_Release(*pptLib);
321 *pptLib = 0;
323 break;
324 case REGKIND_NONE:
325 break;
328 TRACE(" returns %08lx\n",res);
329 return res;
332 /******************************************************************************
333 * LoadRegTypeLib [OLEAUT32.162]
335 HRESULT WINAPI LoadRegTypeLib(
336 REFGUID rguid, /* [in] referenced guid */
337 WORD wVerMajor, /* [in] major version */
338 WORD wVerMinor, /* [in] minor version */
339 LCID lcid, /* [in] locale id */
340 ITypeLib **ppTLib) /* [out] path of typelib */
342 BSTR bstr=NULL;
343 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
345 if(SUCCEEDED(res))
347 res= LoadTypeLib(bstr, ppTLib);
348 SysFreeString(bstr);
351 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
353 return res;
357 /******************************************************************************
358 * RegisterTypeLib [OLEAUT32.163]
359 * Adds information about a type library to the System Registry
360 * NOTES
361 * Docs: ITypeLib FAR * ptlib
362 * Docs: OLECHAR FAR* szFullPath
363 * Docs: OLECHAR FAR* szHelpDir
365 * RETURNS
366 * Success: S_OK
367 * Failure: Status
369 HRESULT WINAPI RegisterTypeLib(
370 ITypeLib * ptlib, /* [in] Pointer to the library*/
371 OLECHAR * szFullPath, /* [in] full Path of the library*/
372 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
373 may be NULL*/
375 HRESULT res;
376 TLIBATTR *attr;
377 OLECHAR guid[80];
378 LPSTR guidA;
379 CHAR keyName[120];
380 HKEY key, subKey;
381 UINT types, tidx;
382 TYPEKIND kind;
383 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
385 if (ptlib == NULL || szFullPath == NULL)
386 return E_INVALIDARG;
388 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
389 return E_FAIL;
391 StringFromGUID2(&attr->guid, guid, 80);
392 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
393 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
394 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
395 HeapFree(GetProcessHeap(), 0, guidA);
397 res = S_OK;
398 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
399 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
401 LPOLESTR doc;
403 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
405 if (RegSetValueExW(key, NULL, 0, REG_SZ,
406 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
407 res = E_FAIL;
409 SysFreeString(doc);
411 else
412 res = E_FAIL;
414 /* FIXME: This *seems* to be 0 always, not sure though */
415 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
416 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
418 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
419 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
420 res = E_FAIL;
422 RegCloseKey(subKey);
424 else
425 res = E_FAIL;
427 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
428 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
430 CHAR buf[20];
431 /* FIXME: is %u correct? */
432 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
433 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
434 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
435 res = E_FAIL;
437 RegCloseKey(key);
439 else
440 res = E_FAIL;
442 /* register OLE Automation-compatible interfaces for this typelib */
443 types = ITypeLib_GetTypeInfoCount(ptlib);
444 for (tidx=0; tidx<types; tidx++) {
445 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
446 LPOLESTR name = NULL;
447 ITypeInfo *tinfo = NULL;
448 BOOL stop = FALSE;
449 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
450 switch (kind) {
451 case TKIND_INTERFACE:
452 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
453 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
454 break;
455 case TKIND_DISPATCH:
456 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
457 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
458 break;
459 case TKIND_COCLASS:
460 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
461 /* coclasses should probably not be registered? */
462 break;
463 default:
464 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
465 break;
467 if (tinfo) {
468 TYPEATTR *tattr = NULL;
469 ITypeInfo_GetTypeAttr(tinfo, &tattr);
470 if (tattr) {
471 TRACE_(typelib)("guid=%s, flags=%04x\n",
472 debugstr_guid(&tattr->guid),
473 tattr->wTypeFlags);
474 if (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION) {
475 /* register interface<->typelib coupling */
476 StringFromGUID2(&tattr->guid, guid, 80);
477 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
478 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
479 HeapFree(GetProcessHeap(), 0, guidA);
481 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
482 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
483 if (name)
484 RegSetValueExW(key, NULL, 0, REG_SZ,
485 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
487 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
488 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
489 RegSetValueExA(subKey, NULL, 0, REG_SZ,
490 PSOA, strlen(PSOA));
491 RegCloseKey(subKey);
493 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
494 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
495 RegSetValueExA(subKey, NULL, 0, REG_SZ,
496 PSOA, strlen(PSOA));
497 RegCloseKey(subKey);
500 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
501 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
502 CHAR ver[32];
503 StringFromGUID2(&attr->guid, guid, 80);
504 snprintf(ver, sizeof(ver), "%x.%x",
505 attr->wMajorVerNum, attr->wMinorVerNum);
506 RegSetValueExW(subKey, NULL, 0, REG_SZ,
507 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
508 RegSetValueExA(subKey, "Version", 0, REG_SZ,
509 ver, lstrlenA(ver));
510 RegCloseKey(subKey);
512 RegCloseKey(key);
515 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
517 ITypeInfo_Release(tinfo);
519 SysFreeString(name);
520 if (stop) break;
524 ITypeLib_ReleaseTLibAttr(ptlib, attr);
526 return res;
530 /******************************************************************************
531 * UnRegisterTypeLib [OLEAUT32.186]
532 * Removes information about a type library from the System Registry
533 * NOTES
535 * RETURNS
536 * Success: S_OK
537 * Failure: Status
539 HRESULT WINAPI UnRegisterTypeLib(
540 REFGUID libid, /* [in] Guid of the library */
541 WORD wVerMajor, /* [in] major version */
542 WORD wVerMinor, /* [in] minor version */
543 LCID lcid, /* [in] locale id */
544 SYSKIND syskind)
546 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
547 return S_OK; /* FIXME: pretend everything is OK */
550 /****************************************************************************
551 * OaBuildVersion (TYPELIB.15)
553 * known TYPELIB.DLL versions:
555 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
556 * OLE 2.02 1993-94 02 3002
557 * OLE 2.03 23 730
558 * OLE 2.03 03 3025
559 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
560 * OLE 2.1 NT 1993-95 ?? ???
561 * OLE 2.3.1 W95 23 700
562 * OLE2 4.0 NT4SP6 1993-98 40 4277
564 DWORD WINAPI OaBuildVersion16(void)
566 /* FIXME: I'd like to return the highest currently known version value
567 * in case the user didn't force a --winver, but I don't know how
568 * to retrieve the "versionForced" info from misc/version.c :(
569 * (this would be useful in other places, too) */
570 FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
571 switch(GetVersion() & 0x8000ffff) /* mask off build number */
573 case 0x80000a03: /* WIN31 */
574 return MAKELONG(3027, 3); /* WfW 3.11 */
575 case 0x80000004: /* WIN95 */
576 return MAKELONG(700, 23); /* Win95A */
577 case 0x80000a04: /* WIN98 */
578 return MAKELONG(3024, 10); /* W98 SE */
579 case 0x00000004: /* NT4 */
580 return MAKELONG(4277, 40); /* NT4 SP6 */
581 default:
582 FIXME("Version value not known yet. Please investigate it!\n");
583 return 0;
587 /* for better debugging info leave the static out for the time being */
588 #define static
590 /*======================= ITypeLib implementation =======================*/
592 typedef struct tagTLBCustData
594 GUID guid;
595 VARIANT data;
596 struct tagTLBCustData* next;
597 } TLBCustData;
599 /* data structure for import typelibs */
600 typedef struct tagTLBImpLib
602 int offset; /* offset in the file (MSFT)
603 offset in nametable (SLTG)
604 just used to identify library while reading
605 data from file */
606 GUID guid; /* libid */
607 BSTR name; /* name */
609 LCID lcid; /* lcid of imported typelib */
611 WORD wVersionMajor; /* major version number */
612 WORD wVersionMinor; /* minor version number */
614 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
615 NULL if not yet loaded */
616 struct tagTLBImpLib * next;
617 } TLBImpLib;
619 /* internal ITypeLib data */
620 typedef struct tagITypeLibImpl
622 ICOM_VFIELD(ITypeLib2);
623 UINT ref;
624 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
626 /* strings can be stored in tlb as multibyte strings BUT they are *always*
627 * exported to the application as a UNICODE string.
629 BSTR Name;
630 BSTR DocString;
631 BSTR HelpFile;
632 BSTR HelpStringDll;
633 unsigned long dwHelpContext;
634 int TypeInfoCount; /* nr of typeinfo's in librarry */
635 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
636 int ctCustData; /* number of items in cust data list */
637 TLBCustData * pCustData; /* linked list to cust data */
638 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
639 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
640 libary. Only used while read MSFT
641 typelibs */
642 } ITypeLibImpl;
644 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
646 /* ITypeLib methods */
647 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
648 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
650 /*======================= ITypeInfo implementation =======================*/
652 /* data for refernced types */
653 typedef struct tagTLBRefType
655 INT index; /* Type index for internal ref or for external ref
656 it the format is SLTG. -2 indicates to
657 use guid */
659 GUID guid; /* guid of the referenced type */
660 /* if index == TLB_REF_USE_GUID */
662 HREFTYPE reference; /* The href of this ref */
663 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
664 TLB_REF_INTERNAL for internal refs
665 TLB_REF_NOT_FOUND for broken refs */
667 struct tagTLBRefType * next;
668 } TLBRefType;
670 #define TLB_REF_USE_GUID -2
672 #define TLB_REF_INTERNAL (void*)-2
673 #define TLB_REF_NOT_FOUND (void*)-1
675 /* internal Parameter data */
676 typedef struct tagTLBParDesc
678 BSTR Name;
679 int ctCustData;
680 TLBCustData * pCustData; /* linked list to cust data */
681 } TLBParDesc;
683 /* internal Function data */
684 typedef struct tagTLBFuncDesc
686 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
687 BSTR Name; /* the name of this function */
688 TLBParDesc *pParamDesc; /* array with param names and custom data */
689 int helpcontext;
690 int HelpStringContext;
691 BSTR HelpString;
692 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
693 int ctCustData;
694 TLBCustData * pCustData; /* linked list to cust data; */
695 struct tagTLBFuncDesc * next;
696 } TLBFuncDesc;
698 /* internal Variable data */
699 typedef struct tagTLBVarDesc
701 VARDESC vardesc; /* lots of info on the variable and its attributes. */
702 BSTR Name; /* the name of this variable */
703 int HelpContext;
704 int HelpStringContext; /* FIXME: where? */
705 BSTR HelpString;
706 int ctCustData;
707 TLBCustData * pCustData;/* linked list to cust data; */
708 struct tagTLBVarDesc * next;
709 } TLBVarDesc;
711 /* internal implemented interface data */
712 typedef struct tagTLBImplType
714 HREFTYPE hRef; /* hRef of interface */
715 int implflags; /* IMPLFLAG_*s */
716 int ctCustData;
717 TLBCustData * pCustData;/* linked list to custom data; */
718 struct tagTLBImplType *next;
719 } TLBImplType;
721 /* internal TypeInfo data */
722 typedef struct tagITypeInfoImpl
724 ICOM_VFIELD(ITypeInfo2);
725 UINT ref;
726 TYPEATTR TypeAttr ; /* _lots_ of type information. */
727 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
728 int index; /* index in this typelib; */
729 /* type libs seem to store the doc strings in ascii
730 * so why should we do it in unicode?
732 BSTR Name;
733 BSTR DocString;
734 unsigned long dwHelpContext;
735 unsigned long dwHelpStringContext;
737 /* functions */
738 TLBFuncDesc * funclist; /* linked list with function descriptions */
740 /* variables */
741 TLBVarDesc * varlist; /* linked list with variable descriptions */
743 /* Implemented Interfaces */
744 TLBImplType * impltypelist;
746 TLBRefType * reflist;
747 int ctCustData;
748 TLBCustData * pCustData; /* linked list to cust data; */
749 struct tagITypeInfoImpl * next;
750 } ITypeInfoImpl;
752 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
754 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
756 typedef struct tagTLBContext
758 unsigned int oStart; /* start of TLB in file */
759 unsigned int pos; /* current pos */
760 unsigned int length; /* total length */
761 void *mapping; /* memory mapping */
762 MSFT_SegDir * pTblDir;
763 ITypeLibImpl* pLibInfo;
764 } TLBContext;
767 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
770 debug
772 static void dump_VarType(VARTYPE vt,char *szVarType) {
773 /* FIXME : we could have better trace here, depending on the VARTYPE
774 * of the variant
776 if (vt & VT_RESERVED)
777 szVarType += strlen(strcpy(szVarType, "reserved | "));
778 if (vt & VT_BYREF)
779 szVarType += strlen(strcpy(szVarType, "ref to "));
780 if (vt & VT_ARRAY)
781 szVarType += strlen(strcpy(szVarType, "array of "));
782 if (vt & VT_VECTOR)
783 szVarType += strlen(strcpy(szVarType, "vector of "));
784 switch(vt & VT_TYPEMASK) {
785 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
786 case VT_I2: sprintf(szVarType, "VT_I2"); break;
787 case VT_I4: sprintf(szVarType, "VT_I4"); break;
788 case VT_R4: sprintf(szVarType, "VT_R4"); break;
789 case VT_R8: sprintf(szVarType, "VT_R8"); break;
790 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
791 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
792 case VT_CY: sprintf(szVarType, "VT_CY"); break;
793 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
794 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
795 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
796 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
797 case VT_I1: sprintf(szVarType, "VT_I1"); break;
798 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
799 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
800 case VT_INT: sprintf(szVarType, "VT_INT"); break;
801 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
802 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
803 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
804 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
805 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
809 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
810 if (pTD->vt & VT_RESERVED)
811 szVarType += strlen(strcpy(szVarType, "reserved | "));
812 if (pTD->vt & VT_BYREF)
813 szVarType += strlen(strcpy(szVarType, "ref to "));
814 if (pTD->vt & VT_ARRAY)
815 szVarType += strlen(strcpy(szVarType, "array of "));
816 if (pTD->vt & VT_VECTOR)
817 szVarType += strlen(strcpy(szVarType, "vector of "));
818 switch(pTD->vt & VT_TYPEMASK) {
819 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
820 case VT_I2: sprintf(szVarType, "VT_I2"); break;
821 case VT_I4: sprintf(szVarType, "VT_I4"); break;
822 case VT_R4: sprintf(szVarType, "VT_R4"); break;
823 case VT_R8: sprintf(szVarType, "VT_R8"); break;
824 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
825 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
826 case VT_CY: sprintf(szVarType, "VT_CY"); break;
827 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
828 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
829 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
830 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
831 case VT_I1: sprintf(szVarType, "VT_I1"); break;
832 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
833 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
834 case VT_INT: sprintf(szVarType, "VT_INT"); break;
835 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
836 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
837 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
838 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
839 pTD->u.hreftype); break;
840 case VT_PTR: sprintf(szVarType, "ptr to ");
841 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
842 break;
843 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
844 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
845 break;
846 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
847 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
848 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
849 break;
851 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
855 static void dump_ELEMDESC(ELEMDESC *edesc) {
856 char buf[200];
857 dump_TypeDesc(&edesc->tdesc,buf);
858 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
859 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
860 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
862 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
863 int i;
864 MESSAGE("memid is %08lx\n",funcdesc->memid);
865 for (i=0;i<funcdesc->cParams;i++) {
866 MESSAGE("Param %d:\n",i);
867 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
869 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
870 switch (funcdesc->funckind) {
871 case FUNC_VIRTUAL: MESSAGE("virtual");break;
872 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
873 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
874 case FUNC_STATIC: MESSAGE("static");break;
875 case FUNC_DISPATCH: MESSAGE("dispatch");break;
876 default: MESSAGE("unknown");break;
878 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
879 switch (funcdesc->invkind) {
880 case INVOKE_FUNC: MESSAGE("func");break;
881 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
882 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
883 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
885 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
886 switch (funcdesc->callconv) {
887 case CC_CDECL: MESSAGE("cdecl");break;
888 case CC_PASCAL: MESSAGE("pascal");break;
889 case CC_STDCALL: MESSAGE("stdcall");break;
890 case CC_SYSCALL: MESSAGE("syscall");break;
891 default:break;
893 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
894 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
895 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
897 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
899 int i;
900 if (!TRACE_ON(typelib))
901 return;
902 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
903 for (i=0;i<pfd->funcdesc.cParams;i++)
904 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
907 dump_FUNCDESC(&(pfd->funcdesc));
909 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
910 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
912 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
914 while (pfd)
916 dump_TLBFuncDescOne(pfd);
917 pfd = pfd->next;
920 static void dump_TLBVarDesc(TLBVarDesc * pvd)
922 while (pvd)
924 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
925 pvd = pvd->next;
929 static void dump_TLBImpLib(TLBImpLib *import)
931 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
932 debugstr_w(import->name));
933 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
934 import->wVersionMinor, import->lcid, import->offset);
937 static void dump_TLBRefType(TLBRefType * prt)
939 while (prt)
941 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
942 if(prt->index == -1)
943 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
944 else
945 TRACE_(typelib)("type no: %d\n", prt->index);
947 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
948 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
949 TRACE_(typelib)("in lib\n");
950 dump_TLBImpLib(prt->pImpTLInfo);
952 prt = prt->next;
956 static void dump_TLBImplType(TLBImplType * impl)
958 while (impl) {
959 TRACE_(typelib)(
960 "implementing/inheriting interface hRef = %lx implflags %x\n",
961 impl->hRef, impl->implflags);
962 impl = impl->next;
966 static void dump_Variant(VARIANT * pvar)
968 char szVarType[32];
969 LPVOID ref;
971 TRACE("(%p)\n", pvar);
973 if (!pvar) return;
975 ZeroMemory(szVarType, sizeof(szVarType));
977 /* FIXME : we could have better trace here, depending on the VARTYPE
978 * of the variant
980 dump_VarType(V_VT(pvar),szVarType);
982 TRACE("VARTYPE: %s\n", szVarType);
984 if (V_VT(pvar) & VT_BYREF) {
985 ref = V_UNION(pvar, byref);
986 TRACE("%p\n", ref);
988 else ref = &V_UNION(pvar, cVal);
990 if (V_VT(pvar) & VT_ARRAY) {
991 /* FIXME */
992 return;
994 if (V_VT(pvar) & VT_VECTOR) {
995 /* FIXME */
996 return;
999 switch (V_VT(pvar))
1001 case VT_I2:
1002 TRACE("%d\n", *(short*)ref);
1003 break;
1005 case VT_I4:
1006 TRACE("%d\n", *(INT*)ref);
1007 break;
1009 case VT_R4:
1010 TRACE("%3.3e\n", *(float*)ref);
1011 break;
1013 case VT_R8:
1014 TRACE("%3.3e\n", *(double*)ref);
1015 break;
1017 case VT_BOOL:
1018 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1019 break;
1021 case VT_BSTR:
1022 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1023 break;
1025 case VT_UNKNOWN:
1026 case VT_DISPATCH:
1027 TRACE("%p\n", *(LPVOID*)ref);
1028 break;
1030 case VT_VARIANT:
1031 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1032 break;
1034 default:
1035 TRACE("(?)%ld\n", *(long*)ref);
1036 break;
1040 static void dump_DispParms(DISPPARAMS * pdp)
1042 int index = 0;
1044 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1046 while (index < pdp->cArgs)
1048 dump_Variant( &pdp->rgvarg[index] );
1049 ++index;
1053 static char * typekind_desc[] =
1055 "TKIND_ENUM",
1056 "TKIND_RECORD",
1057 "TKIND_MODULE",
1058 "TKIND_INTERFACE",
1059 "TKIND_DISPATCH",
1060 "TKIND_COCLASS",
1061 "TKIND_ALIAS",
1062 "TKIND_UNION",
1063 "TKIND_MAX"
1066 static void dump_TypeInfo(ITypeInfoImpl * pty)
1068 TRACE("%p ref=%u\n", pty, pty->ref);
1069 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1070 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1071 TRACE("fct:%u var:%u impl:%u\n",
1072 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1073 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1074 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1075 dump_TLBFuncDesc(pty->funclist);
1076 dump_TLBVarDesc(pty->varlist);
1077 dump_TLBImplType(pty->impltypelist);
1080 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1082 /* VT_LPWSTR is largest type that */
1083 /* may appear in type description*/
1084 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1085 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1086 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1087 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1088 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1089 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1090 {{0},30},{{0},31}
1093 static void TLB_abort()
1095 DebugBreak();
1097 static void * TLB_Alloc(unsigned size)
1099 void * ret;
1100 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1101 /* FIXME */
1102 ERR("cannot allocate memory\n");
1104 return ret;
1107 static void TLB_Free(void * ptr)
1109 HeapFree(GetProcessHeap(), 0, ptr);
1113 /**********************************************************************
1115 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1117 /* read function */
1118 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1120 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1121 pcx->pos, count, pcx->oStart, pcx->length, where);
1123 if (where != DO_NOT_SEEK)
1125 where += pcx->oStart;
1126 if (where > pcx->length)
1128 /* FIXME */
1129 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1130 TLB_abort();
1132 pcx->pos = where;
1134 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1135 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1136 pcx->pos += count;
1137 return count;
1140 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1142 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1144 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1145 memset(pGuid,0, sizeof(GUID));
1146 return;
1148 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1151 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1153 char * name;
1154 MSFT_NameIntro niName;
1155 int lengthInChars;
1156 WCHAR* pwstring = NULL;
1157 BSTR bstrName = NULL;
1159 MSFT_Read(&niName, sizeof(niName), pcx,
1160 pcx->pTblDir->pNametab.offset+offset);
1161 niName.namelen &= 0xFF; /* FIXME: correct ? */
1162 name=TLB_Alloc((niName.namelen & 0xff) +1);
1163 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1164 name[niName.namelen & 0xff]='\0';
1166 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1167 name, -1, NULL, 0);
1169 /* no invalid characters in string */
1170 if (lengthInChars)
1172 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1174 /* don't check for invalid character since this has been done previously */
1175 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1177 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1178 lengthInChars = SysStringLen(bstrName);
1179 HeapFree(GetProcessHeap(), 0, pwstring);
1182 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1183 return bstrName;
1186 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1188 char * string;
1189 INT16 length;
1190 int lengthInChars;
1191 BSTR bstr = NULL;
1193 if(offset<0) return NULL;
1194 MSFT_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1195 if(length <= 0) return 0;
1196 string=TLB_Alloc(length +1);
1197 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1198 string[length]='\0';
1200 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1201 string, -1, NULL, 0);
1203 /* no invalid characters in string */
1204 if (lengthInChars)
1206 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1208 /* don't check for invalid character since this has been done previously */
1209 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1211 bstr = SysAllocStringLen(pwstring, lengthInChars);
1212 lengthInChars = SysStringLen(bstr);
1213 HeapFree(GetProcessHeap(), 0, pwstring);
1216 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1217 return bstr;
1220 * read a value and fill a VARIANT structure
1222 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1224 int size;
1226 TRACE_(typelib)("\n");
1228 if(offset <0) { /* data are packed in here */
1229 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1230 V_UNION(pVar, iVal) = offset & 0xffff;
1231 return;
1233 MSFT_Read(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1234 pcx->pTblDir->pCustData.offset + offset );
1235 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1236 switch (V_VT(pVar)){
1237 case VT_EMPTY: /* FIXME: is this right? */
1238 case VT_NULL: /* FIXME: is this right? */
1239 case VT_I2 : /* this should not happen */
1240 case VT_I4 :
1241 case VT_R4 :
1242 case VT_ERROR :
1243 case VT_BOOL :
1244 case VT_I1 :
1245 case VT_UI1 :
1246 case VT_UI2 :
1247 case VT_UI4 :
1248 case VT_INT :
1249 case VT_UINT :
1250 case VT_VOID : /* FIXME: is this right? */
1251 case VT_HRESULT :
1252 size=4; break;
1253 case VT_R8 :
1254 case VT_CY :
1255 case VT_DATE :
1256 case VT_I8 :
1257 case VT_UI8 :
1258 case VT_DECIMAL : /* FIXME: is this right? */
1259 case VT_FILETIME :
1260 size=8;break;
1261 /* pointer types with known behaviour */
1262 case VT_BSTR :{
1263 char * ptr;
1264 MSFT_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1265 if(size <= 0) {
1266 FIXME("BSTR length = %d?\n", size);
1267 } else {
1268 ptr=TLB_Alloc(size);/* allocate temp buffer */
1269 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1270 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1271 /* FIXME: do we need a AtoW conversion here? */
1272 V_UNION(pVar, bstrVal[size])=L'\0';
1273 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1274 TLB_Free(ptr);
1277 size=-4; break;
1278 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1279 case VT_DISPATCH :
1280 case VT_VARIANT :
1281 case VT_UNKNOWN :
1282 case VT_PTR :
1283 case VT_SAFEARRAY :
1284 case VT_CARRAY :
1285 case VT_USERDEFINED :
1286 case VT_LPSTR :
1287 case VT_LPWSTR :
1288 case VT_BLOB :
1289 case VT_STREAM :
1290 case VT_STORAGE :
1291 case VT_STREAMED_OBJECT :
1292 case VT_STORED_OBJECT :
1293 case VT_BLOB_OBJECT :
1294 case VT_CF :
1295 case VT_CLSID :
1296 default:
1297 size=0;
1298 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1299 V_VT(pVar));
1302 if(size>0) /* (big|small) endian correct? */
1303 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1304 return;
1307 * create a linked list with custom data
1309 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1311 MSFT_CDGuid entry;
1312 TLBCustData* pNew;
1313 int count=0;
1315 TRACE_(typelib)("\n");
1317 while(offset >=0){
1318 count++;
1319 pNew=TLB_Alloc(sizeof(TLBCustData));
1320 MSFT_Read(&entry, sizeof(entry), pcx,
1321 pcx->pTblDir->pCDGuids.offset+offset);
1322 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1323 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1324 /* add new custom data at head of the list */
1325 pNew->next=*ppCustData;
1326 *ppCustData=pNew;
1327 offset = entry.next;
1329 return count;
1332 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1333 ITypeInfoImpl *pTI)
1335 if(type <0)
1336 pTd->vt=type & VT_TYPEMASK;
1337 else
1338 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1340 if(pTd->vt == VT_USERDEFINED)
1341 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1343 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1346 static void
1347 MSFT_DoFuncs(TLBContext* pcx,
1348 ITypeInfoImpl* pTI,
1349 int cFuncs,
1350 int cVars,
1351 int offset,
1352 TLBFuncDesc** pptfd)
1355 * member information is stored in a data structure at offset
1356 * indicated by the memoffset field of the typeinfo structure
1357 * There are several distinctive parts.
1358 * the first part starts with a field that holds the total length
1359 * of this (first) part excluding this field. Then follow the records,
1360 * for each member there is one record.
1362 * First entry is always the length of the record (excluding this
1363 * length word).
1364 * Rest of the record depends on the type of the member. If there is
1365 * a field indicating the member type (function variable intereface etc)
1366 * I have not found it yet. At this time we depend on the information
1367 * in the type info and the usual order how things are stored.
1369 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1370 * for each member;
1372 * Third is a equal sized array with file offsets to the name entry
1373 * of each member.
1375 * Forth and last (?) part is an array with offsets to the records in the
1376 * first part of this file segment.
1379 int infolen, nameoffset, reclength, nrattributes, i;
1380 int recoffset = offset + sizeof(INT);
1382 char recbuf[512];
1383 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1385 TRACE_(typelib)("\n");
1387 MSFT_Read(&infolen, sizeof(INT), pcx, offset);
1389 for ( i = 0; i < cFuncs ; i++ )
1391 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1393 /* name, eventually add to a hash table */
1394 MSFT_Read(&nameoffset,
1395 sizeof(INT),
1396 pcx,
1397 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1399 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1401 /* read the function information record */
1402 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1404 reclength &= 0x1ff;
1406 MSFT_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1408 /* do the attributes */
1409 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1410 / sizeof(int);
1412 if ( nrattributes > 0 )
1414 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1416 if ( nrattributes > 1 )
1418 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1419 pFuncRec->OptAttr[1]) ;
1421 if ( nrattributes > 2 )
1423 if ( pFuncRec->FKCCIC & 0x2000 )
1425 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1427 else
1429 (*pptfd)->Entry = MSFT_ReadString(pcx,
1430 pFuncRec->OptAttr[2]);
1432 if( nrattributes > 5 )
1434 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1436 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1438 MSFT_CustData(pcx,
1439 pFuncRec->OptAttr[6],
1440 &(*pptfd)->pCustData);
1447 /* fill the FuncDesc Structure */
1448 MSFT_Read( & (*pptfd)->funcdesc.memid,
1449 sizeof(INT), pcx,
1450 offset + infolen + ( i + 1) * sizeof(INT));
1452 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1453 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1454 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1455 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1456 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1457 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1458 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1460 MSFT_GetTdesc(pcx,
1461 pFuncRec->DataType,
1462 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1463 pTI);
1465 /* do the parameters/arguments */
1466 if(pFuncRec->nrargs)
1468 int j = 0;
1469 MSFT_ParameterInfo paraminfo;
1471 (*pptfd)->funcdesc.lprgelemdescParam =
1472 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1474 (*pptfd)->pParamDesc =
1475 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1477 MSFT_Read(&paraminfo,
1478 sizeof(paraminfo),
1479 pcx,
1480 recoffset + reclength -
1481 pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1483 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1485 TYPEDESC* lpArgTypeDesc = 0;
1487 MSFT_GetTdesc(pcx,
1488 paraminfo.DataType,
1489 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1490 pTI);
1492 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1494 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1496 /* SEEK value = jump to offset,
1497 * from there jump to the end of record,
1498 * go back by (j-1) arguments
1500 MSFT_Read( &paraminfo ,
1501 sizeof(MSFT_ParameterInfo), pcx,
1502 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1503 * sizeof(MSFT_ParameterInfo)));
1504 lpArgTypeDesc =
1505 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1507 while ( lpArgTypeDesc != NULL )
1509 switch ( lpArgTypeDesc->vt )
1511 case VT_PTR:
1512 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1513 break;
1515 case VT_CARRAY:
1516 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1517 break;
1519 case VT_USERDEFINED:
1520 MSFT_DoRefType(pcx, pTI,
1521 lpArgTypeDesc->u.hreftype);
1523 lpArgTypeDesc = NULL;
1524 break;
1526 default:
1527 lpArgTypeDesc = NULL;
1533 /* parameter is the return value! */
1534 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1536 TYPEDESC* lpArgTypeDesc;
1538 (*pptfd)->funcdesc.elemdescFunc =
1539 (*pptfd)->funcdesc.lprgelemdescParam[j];
1541 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1543 while ( lpArgTypeDesc != NULL )
1545 switch ( lpArgTypeDesc->vt )
1547 case VT_PTR:
1548 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1549 break;
1550 case VT_CARRAY:
1551 lpArgTypeDesc =
1552 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1554 break;
1556 case VT_USERDEFINED:
1557 MSFT_DoRefType(pcx,
1558 pTI,
1559 lpArgTypeDesc->u.hreftype);
1561 lpArgTypeDesc = NULL;
1562 break;
1564 default:
1565 lpArgTypeDesc = NULL;
1570 /* second time around */
1571 for(j=0;j<pFuncRec->nrargs;j++)
1573 /* name */
1574 (*pptfd)->pParamDesc[j].Name =
1575 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1577 /* default value */
1578 if ( (PARAMFLAG_FHASDEFAULT &
1579 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1580 ((pFuncRec->FKCCIC) & 0x1000) )
1582 INT* pInt = (INT *)((char *)pFuncRec +
1583 reclength -
1584 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1586 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1588 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1589 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1591 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1592 pInt[j], pcx);
1594 /* custom info */
1595 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1597 MSFT_CustData(pcx,
1598 pFuncRec->OptAttr[7+j],
1599 &(*pptfd)->pParamDesc[j].pCustData);
1604 /* scode is not used: archaic win16 stuff FIXME: right? */
1605 (*pptfd)->funcdesc.cScodes = 0 ;
1606 (*pptfd)->funcdesc.lprgscode = NULL ;
1608 pptfd = & ((*pptfd)->next);
1609 recoffset += reclength;
1612 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1613 int cVars, int offset, TLBVarDesc ** pptvd)
1615 int infolen, nameoffset, reclength;
1616 char recbuf[256];
1617 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1618 int i;
1619 int recoffset;
1621 TRACE_(typelib)("\n");
1623 MSFT_Read(&infolen,sizeof(INT), pcx, offset);
1624 MSFT_Read(&recoffset,sizeof(INT), pcx, offset + infolen +
1625 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1626 recoffset += offset+sizeof(INT);
1627 for(i=0;i<cVars;i++){
1628 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1629 /* name, eventually add to a hash table */
1630 MSFT_Read(&nameoffset, sizeof(INT), pcx,
1631 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1632 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1633 /* read the variable information record */
1634 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1635 reclength &=0xff;
1636 MSFT_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1637 /* Optional data */
1638 if(reclength >(6*sizeof(INT)) )
1639 (*pptvd)->HelpContext=pVarRec->HelpContext;
1640 if(reclength >(7*sizeof(INT)) )
1641 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1642 if(reclength >(8*sizeof(INT)) )
1643 if(reclength >(9*sizeof(INT)) )
1644 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1645 /* fill the VarDesc Structure */
1646 MSFT_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1647 offset + infolen + ( i + 1) * sizeof(INT));
1648 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1649 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1650 MSFT_GetTdesc(pcx, pVarRec->DataType,
1651 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1652 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1653 if(pVarRec->VarKind == VAR_CONST ){
1654 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1655 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1656 pVarRec->OffsValue, pcx);
1657 } else
1658 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1659 pptvd=&((*pptvd)->next);
1660 recoffset += reclength;
1663 /* fill in data for a hreftype (offset). When the refernced type is contained
1664 * in the typelib, it's just an (file) offset in the type info base dir.
1665 * If comes from import, it's an offset+1 in the ImpInfo table
1666 * */
1667 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1668 int offset)
1670 int j;
1671 TLBRefType **ppRefType = &pTI->reflist;
1673 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1675 while(*ppRefType) {
1676 if((*ppRefType)->reference == offset)
1677 return;
1678 ppRefType = &(*ppRefType)->next;
1681 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1682 sizeof(**ppRefType));
1684 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1685 /* external typelib */
1686 MSFT_ImpInfo impinfo;
1687 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1689 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1691 MSFT_Read(&impinfo, sizeof(impinfo), pcx,
1692 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1693 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1694 if(pImpLib->offset==impinfo.oImpFile) break;
1695 pImpLib=pImpLib->next;
1697 if(pImpLib){
1698 (*ppRefType)->reference=offset;
1699 (*ppRefType)->pImpTLInfo = pImpLib;
1700 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1701 (*ppRefType)->index = TLB_REF_USE_GUID;
1702 }else{
1703 ERR("Cannot find a reference\n");
1704 (*ppRefType)->reference=-1;
1705 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1707 }else{
1708 /* in this typelib */
1709 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1710 (*ppRefType)->reference=offset;
1711 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1715 /* process Implemented Interfaces of a com class */
1716 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1717 int offset)
1719 int i;
1720 MSFT_RefRecord refrec;
1721 TLBImplType **ppImpl = &pTI->impltypelist;
1723 TRACE_(typelib)("\n");
1725 for(i=0;i<count;i++){
1726 if(offset<0) break; /* paranoia */
1727 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1728 MSFT_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1729 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1730 (*ppImpl)->hRef = refrec.reftype;
1731 (*ppImpl)->implflags=refrec.flags;
1732 (*ppImpl)->ctCustData=
1733 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1734 offset=refrec.onext;
1735 ppImpl=&((*ppImpl)->next);
1739 * process a typeinfo record
1741 ITypeInfoImpl * MSFT_DoTypeInfo(
1742 TLBContext *pcx,
1743 int count,
1744 ITypeLibImpl * pLibInfo)
1746 MSFT_TypeInfoBase tiBase;
1747 ITypeInfoImpl *ptiRet;
1749 TRACE_(typelib)("count=%u\n", count);
1751 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1752 MSFT_Read(&tiBase, sizeof(tiBase) ,pcx ,
1753 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1754 /* this is where we are coming from */
1755 ptiRet->pTypeLib = pLibInfo;
1756 ITypeLib2_AddRef((ITypeLib2 *)pLibInfo);
1757 ptiRet->index=count;
1758 /* fill in the typeattr fields */
1759 FIXME("Assign constructor/destructor memid\n");
1761 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1762 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1763 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1764 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1765 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1766 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1767 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1768 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1769 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1770 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1771 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1772 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1773 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1774 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1775 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1776 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1777 MSFT_GetTdesc(pcx, tiBase.datatype1,
1778 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1780 /* FIXME: */
1781 /* IDLDESC idldescType; *//* never saw this one != zero */
1783 /* name, eventually add to a hash table */
1784 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1785 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1786 /* help info */
1787 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1788 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1789 ptiRet->dwHelpContext=tiBase.helpcontext;
1790 /* note: InfoType's Help file and HelpStringDll come from the containing
1791 * library. Further HelpString and Docstring appear to be the same thing :(
1793 /* functions */
1794 if(ptiRet->TypeAttr.cFuncs >0 )
1795 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1796 ptiRet->TypeAttr.cVars,
1797 tiBase.memoffset, & ptiRet->funclist);
1798 /* variables */
1799 if(ptiRet->TypeAttr.cVars >0 )
1800 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1801 ptiRet->TypeAttr.cVars,
1802 tiBase.memoffset, & ptiRet->varlist);
1803 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1804 switch(ptiRet->TypeAttr.typekind)
1806 case TKIND_COCLASS:
1807 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1808 tiBase.datatype1);
1809 break;
1810 case TKIND_DISPATCH:
1811 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1813 if (tiBase.datatype1 != -1)
1815 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1816 ptiRet->impltypelist->hRef = tiBase.datatype1;
1818 else
1819 { /* FIXME: This is a really bad hack to add IDispatch */
1820 char* szStdOle = "stdole2.tlb\0";
1821 int nStdOleLen = strlen(szStdOle);
1822 TLBRefType **ppRef = &ptiRet->reflist;
1824 while(*ppRef) {
1825 if((*ppRef)->reference == -1)
1826 break;
1827 ppRef = &(*ppRef)->next;
1829 if(!*ppRef) {
1830 *ppRef = TLB_Alloc(sizeof(**ppRef));
1831 (*ppRef)->guid = IID_IDispatch;
1832 (*ppRef)->reference = -1;
1833 (*ppRef)->index = TLB_REF_USE_GUID;
1834 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1835 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1836 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1837 nStdOleLen + 1);
1839 MultiByteToWideChar(CP_ACP,
1840 MB_PRECOMPOSED,
1841 szStdOle,
1843 (*ppRef)->pImpTLInfo->name,
1844 SysStringLen((*ppRef)->pImpTLInfo->name));
1846 (*ppRef)->pImpTLInfo->lcid = 0;
1847 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1848 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1851 break;
1852 default:
1853 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1854 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1855 ptiRet->impltypelist->hRef = tiBase.datatype1;
1856 break;
1859 ptiRet->ctCustData=
1860 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1862 TRACE_(typelib)("%s guid: %s kind:%s\n",
1863 debugstr_w(ptiRet->Name),
1864 debugstr_guid(&ptiRet->TypeAttr.guid),
1865 typekind_desc[ptiRet->TypeAttr.typekind]);
1867 return ptiRet;
1870 /****************************************************************************
1871 * TLB_ReadTypeLib
1873 * find the type of the typelib file and map the typelib resource into
1874 * the memory
1876 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1877 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1878 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1880 int ret = TYPE_E_CANTLOADLIBRARY;
1881 DWORD dwSignature = 0;
1882 HFILE hFile;
1884 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1886 *ppTypeLib = NULL;
1888 /* check the signature of the file */
1889 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1890 if (INVALID_HANDLE_VALUE != hFile)
1892 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1893 if (hMapping)
1895 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1896 if(pBase)
1898 /* retrieve file size */
1899 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1901 /* first try to load as *.tlb */
1902 dwSignature = *((DWORD*) pBase);
1903 if ( dwSignature == MSFT_SIGNATURE)
1905 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1907 else if ( dwSignature == SLTG_SIGNATURE)
1909 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1911 UnmapViewOfFile(pBase);
1913 CloseHandle(hMapping);
1915 CloseHandle(hFile);
1918 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1920 /* find the typelibrary resource*/
1921 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
1922 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1923 if (hinstDLL)
1925 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
1926 "TYPELIB");
1927 if (hrsrc)
1929 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1930 if (hGlobal)
1932 LPVOID pBase = LockResource(hGlobal);
1933 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1935 if (pBase)
1937 /* try to load as incore resource */
1938 dwSignature = *((DWORD*) pBase);
1939 if ( dwSignature == MSFT_SIGNATURE)
1941 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1943 else if ( dwSignature == SLTG_SIGNATURE)
1945 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1947 else
1949 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
1952 FreeResource( hGlobal );
1955 FreeLibrary(hinstDLL);
1959 if(*ppTypeLib)
1960 ret = S_OK;
1961 else
1962 ERR("Loading of typelib %s failed with error %ld\n",
1963 debugstr_w(pszFileName), GetLastError());
1965 return ret;
1968 /*================== ITypeLib(2) Methods ===================================*/
1970 /****************************************************************************
1971 * ITypeLib2_Constructor_MSFT
1973 * loading an MSFT typelib from an in-memory image
1975 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
1977 TLBContext cx;
1978 long lPSegDir;
1979 MSFT_Header tlbHeader;
1980 MSFT_SegDir tlbSegDir;
1981 ITypeLibImpl * pTypeLibImpl;
1983 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
1985 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
1986 if (!pTypeLibImpl) return NULL;
1988 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
1989 pTypeLibImpl->ref = 1;
1991 /* get pointer to beginning of typelib data */
1992 cx.pos = 0;
1993 cx.oStart=0;
1994 cx.mapping = pLib;
1995 cx.pLibInfo = pTypeLibImpl;
1996 cx.length = dwTLBLength;
1998 /* read header */
1999 MSFT_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2000 TRACE("header:\n");
2001 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2002 if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
2003 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2004 return NULL;
2006 /* there is a small amount of information here until the next important
2007 * part:
2008 * the segment directory . Try to calculate the amount of data */
2009 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2011 /* now read the segment directory */
2012 TRACE("read segment directory (at %ld)\n",lPSegDir);
2013 MSFT_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2014 cx.pTblDir = &tlbSegDir;
2016 /* just check two entries */
2017 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2019 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2020 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2021 return NULL;
2024 /* now fill our internal data */
2025 /* TLIBATTR fields */
2026 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2028 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2029 /* Windows seems to have zero here, is this correct? */
2030 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2031 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2032 else
2033 pTypeLibImpl->LibAttr.lcid = 0;
2035 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2036 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2037 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2038 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2040 /* name, eventually add to a hash table */
2041 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2043 /* help info */
2044 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2045 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2047 if( tlbHeader.varflags & HELPDLLFLAG)
2049 int offset;
2050 MSFT_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2051 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2054 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2056 /* custom data */
2057 if(tlbHeader.CustomDataOffset >= 0)
2059 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2062 /* fill in typedescriptions */
2063 if(tlbSegDir.pTypdescTab.length > 0)
2065 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2066 INT16 td[4];
2067 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2068 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2069 for(i=0; i<cTD; )
2071 /* FIXME: add several sanity checks here */
2072 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2073 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2075 /* FIXME: check safearray */
2076 if(td[3] < 0)
2077 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2078 else
2079 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2081 else if(td[0] == VT_CARRAY)
2083 /* array descr table here */
2084 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2086 else if(td[0] == VT_USERDEFINED)
2088 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2090 if(++i<cTD) MSFT_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
2093 /* second time around to fill the array subscript info */
2094 for(i=0;i<cTD;i++)
2096 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2097 if(tlbSegDir.pArrayDescriptions.offset>0)
2099 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2100 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2102 if(td[1]<0)
2103 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2104 else
2105 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2107 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2109 for(j = 0; j<td[2]; j++)
2111 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2112 sizeof(INT), &cx, DO_NOT_SEEK);
2113 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2114 sizeof(INT), &cx, DO_NOT_SEEK);
2117 else
2119 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2120 ERR("didn't find array description data\n");
2125 /* imported type libs */
2126 if(tlbSegDir.pImpFiles.offset>0)
2128 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2129 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2130 UINT16 size;
2132 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2134 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2135 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2136 MSFT_Read(&oGuid, sizeof(INT), &cx, offset);
2138 MSFT_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2139 MSFT_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2140 MSFT_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2141 MSFT_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2143 size >>= 2;
2144 (*ppImpLib)->name = TLB_Alloc(size+1);
2145 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2146 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2147 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2149 ppImpLib = &(*ppImpLib)->next;
2153 /* type info's */
2154 if(tlbHeader.nrtypeinfos >= 0 )
2156 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2157 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2158 int i;
2160 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2162 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2164 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2165 ppTI = &((*ppTI)->next);
2166 (pTypeLibImpl->TypeInfoCount)++;
2170 TRACE("(%p)\n", pTypeLibImpl);
2171 return (ITypeLib2*) pTypeLibImpl;
2175 static BSTR TLB_MultiByteToBSTR(char *ptr)
2177 DWORD len;
2178 WCHAR *nameW;
2179 BSTR ret;
2181 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2182 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2183 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2184 ret = SysAllocString(nameW);
2185 HeapFree(GetProcessHeap(), 0, nameW);
2186 return ret;
2189 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2191 char b[3];
2192 int i;
2193 short s;
2195 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2196 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2197 return FALSE;
2200 guid->Data4[0] = s >> 8;
2201 guid->Data4[1] = s & 0xff;
2203 b[2] = '\0';
2204 for(i = 0; i < 6; i++) {
2205 memcpy(b, str + 24 + 2 * i, 2);
2206 guid->Data4[i + 2] = strtol(b, NULL, 16);
2208 return TRUE;
2211 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2213 WORD bytelen;
2214 DWORD len;
2215 WCHAR *nameW;
2217 *pBstr = NULL;
2218 bytelen = *(WORD*)ptr;
2219 if(bytelen == 0xffff) return 2;
2220 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2221 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2222 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2223 *pBstr = SysAllocStringLen(nameW, len);
2224 HeapFree(GetProcessHeap(), 0, nameW);
2225 return bytelen + 2;
2228 static WORD SLTG_ReadStringA(char *ptr, char **str)
2230 WORD bytelen;
2232 *str = NULL;
2233 bytelen = *(WORD*)ptr;
2234 if(bytelen == 0xffff) return 2;
2235 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2236 memcpy(*str, ptr + 2, bytelen);
2237 (*str)[bytelen] = '\0';
2238 return bytelen + 2;
2241 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2243 char *ptr = pLibBlk;
2244 WORD w;
2246 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2247 FIXME("libblk magic = %04x\n", w);
2248 return 0;
2251 ptr += 6;
2252 if((w = *(WORD*)ptr) != 0xffff) {
2253 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2254 ptr += w;
2256 ptr += 2;
2258 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2260 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2262 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2263 ptr += 4;
2265 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2266 ptr += 2;
2268 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2269 ptr += 2;
2271 ptr += 4; /* skip res12 */
2273 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2274 ptr += 2;
2276 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2277 ptr += 2;
2279 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2280 ptr += 2;
2282 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2283 ptr += sizeof(GUID);
2285 return ptr - (char*)pLibBlk;
2288 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2290 BOOL done = FALSE;
2291 TYPEDESC *pTD = &pElem->tdesc;
2293 /* Handle [in/out] first */
2294 if((*pType & 0xc000) == 0xc000)
2295 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2296 else if(*pType & 0x8000)
2297 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2298 else if(*pType & 0x4000)
2299 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2300 else
2301 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2303 if(*pType & 0x2000)
2304 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2306 if(*pType & 0x80)
2307 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2309 while(!done) {
2310 if((*pType & 0xe00) == 0xe00) {
2311 pTD->vt = VT_PTR;
2312 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2313 sizeof(TYPEDESC));
2314 pTD = pTD->u.lptdesc;
2316 switch(*pType & 0x7f) {
2317 case VT_PTR:
2318 pTD->vt = VT_PTR;
2319 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2320 sizeof(TYPEDESC));
2321 pTD = pTD->u.lptdesc;
2322 break;
2324 case VT_USERDEFINED:
2325 pTD->vt = VT_USERDEFINED;
2326 pTD->u.hreftype = *(++pType) / 4;
2327 done = TRUE;
2328 break;
2330 case VT_CARRAY:
2332 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2333 array */
2335 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2337 pTD->vt = VT_CARRAY;
2338 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2339 sizeof(ARRAYDESC) +
2340 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2341 pTD->u.lpadesc->cDims = pSA->cDims;
2342 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2343 pSA->cDims * sizeof(SAFEARRAYBOUND));
2345 pTD = &pTD->u.lpadesc->tdescElem;
2346 break;
2349 case VT_SAFEARRAY:
2351 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2352 useful? */
2354 pType++;
2355 pTD->vt = VT_SAFEARRAY;
2356 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2357 sizeof(TYPEDESC));
2358 pTD = pTD->u.lptdesc;
2359 break;
2361 default:
2362 pTD->vt = *pType & 0x7f;
2363 done = TRUE;
2364 break;
2366 pType++;
2368 return pType;
2372 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2373 char *pNameTable)
2375 int ref;
2376 char *name;
2377 TLBRefType **ppRefType;
2379 if(pRef->magic != SLTG_REF_MAGIC) {
2380 FIXME("Ref magic = %x\n", pRef->magic);
2381 return;
2383 name = ( (char*)(&pRef->names) + pRef->number);
2385 ppRefType = &pTI->reflist;
2386 for(ref = 0; ref < pRef->number >> 3; ref++) {
2387 char *refname;
2388 unsigned int lib_offs, type_num;
2390 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2391 sizeof(**ppRefType));
2393 name += SLTG_ReadStringA(name, &refname);
2394 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2395 FIXME("Can't sscanf ref\n");
2396 if(lib_offs != 0xffff) {
2397 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2399 while(*import) {
2400 if((*import)->offset == lib_offs)
2401 break;
2402 import = &(*import)->next;
2404 if(!*import) {
2405 char fname[MAX_PATH+1];
2406 int len;
2408 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2409 sizeof(**import));
2410 (*import)->offset = lib_offs;
2411 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2412 &(*import)->guid);
2413 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2414 &(*import)->wVersionMajor,
2415 &(*import)->wVersionMinor,
2416 &(*import)->lcid, fname) != 4) {
2417 FIXME("can't sscanf ref %s\n",
2418 pNameTable + lib_offs + 40);
2420 len = strlen(fname);
2421 if(fname[len-1] != '#')
2422 FIXME("fname = %s\n", fname);
2423 fname[len-1] = '\0';
2424 (*import)->name = TLB_MultiByteToBSTR(fname);
2426 (*ppRefType)->pImpTLInfo = *import;
2427 } else { /* internal ref */
2428 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2430 (*ppRefType)->reference = ref;
2431 (*ppRefType)->index = type_num;
2433 HeapFree(GetProcessHeap(), 0, refname);
2434 ppRefType = &(*ppRefType)->next;
2436 if((BYTE)*name != SLTG_REF_MAGIC)
2437 FIXME("End of ref block magic = %x\n", *name);
2438 dump_TLBRefType(pTI->reflist);
2441 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2442 BOOL OneOnly)
2444 SLTG_ImplInfo *info;
2445 TLBImplType **ppImplType = &pTI->impltypelist;
2446 /* I don't really get this structure, usually it's 0x16 bytes
2447 long, but iuser.tlb contains some that are 0x18 bytes long.
2448 That's ok because we can use the next ptr to jump to the next
2449 one. But how do we know the length of the last one? The WORD
2450 at offs 0x8 might be the clue. For now I'm just assuming that
2451 the last one is the regular 0x16 bytes. */
2453 info = (SLTG_ImplInfo*)pBlk;
2454 while(1) {
2455 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2456 sizeof(**ppImplType));
2457 (*ppImplType)->hRef = info->ref;
2458 (*ppImplType)->implflags = info->impltypeflags;
2459 pTI->TypeAttr.cImplTypes++;
2460 ppImplType = &(*ppImplType)->next;
2462 if(info->next == 0xffff)
2463 break;
2464 if(OneOnly)
2465 FIXME("Interface inheriting more than one interface\n");
2466 info = (SLTG_ImplInfo*)(pBlk + info->next);
2468 info++; /* see comment at top of function */
2469 return (char*)info;
2472 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2473 char *pNameTable)
2475 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2476 SLTG_MemberHeader *pMemHeader;
2477 char *pFirstItem, *pNextItem;
2479 if(pTIHeader->href_table != 0xffffffff) {
2480 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2481 pNameTable);
2485 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2487 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2489 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2490 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2493 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2497 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2498 char *pNameTable)
2500 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2501 SLTG_MemberHeader *pMemHeader;
2502 SLTG_Function *pFunc;
2503 char *pFirstItem, *pNextItem;
2504 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2505 int num = 0;
2507 if(pTIHeader->href_table != 0xffffffff) {
2508 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2509 pNameTable);
2512 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2514 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2516 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2517 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2520 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2521 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2523 int param;
2524 WORD *pType, *pArg;
2526 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2527 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2528 FIXME("func magic = %02x\n", pFunc->magic);
2529 return NULL;
2531 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2532 sizeof(**ppFuncDesc));
2533 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2535 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2536 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2537 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2538 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2539 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2540 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2542 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2543 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2545 if(pFunc->retnextopt & 0x80)
2546 pType = &pFunc->rettype;
2547 else
2548 pType = (WORD*)(pFirstItem + pFunc->rettype);
2551 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2553 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2554 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2555 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2556 (*ppFuncDesc)->pParamDesc =
2557 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2558 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2560 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2562 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2563 char *paramName = pNameTable + *pArg;
2564 BOOL HaveOffs;
2565 /* If arg type follows then paramName points to the 2nd
2566 letter of the name, else the next WORD is an offset to
2567 the arg type and paramName points to the first letter.
2568 So let's take one char off paramName and see if we're
2569 pointing at an alpha-numeric char. However if *pArg is
2570 0xffff or 0xfffe then the param has no name, the former
2571 meaning that the next WORD is the type, the latter
2572 meaning the the next WORD is an offset to the type. */
2574 HaveOffs = FALSE;
2575 if(*pArg == 0xffff)
2576 paramName = NULL;
2577 else if(*pArg == 0xfffe) {
2578 paramName = NULL;
2579 HaveOffs = TRUE;
2581 else if(!isalnum(*(paramName-1)))
2582 HaveOffs = TRUE;
2584 pArg++;
2586 if(HaveOffs) { /* the next word is an offset to type */
2587 pType = (WORD*)(pFirstItem + *pArg);
2588 SLTG_DoType(pType, pFirstItem,
2589 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2590 pArg++;
2591 } else {
2592 if(paramName)
2593 paramName--;
2594 pArg = SLTG_DoType(pArg, pFirstItem,
2595 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2598 /* Are we an optional param ? */
2599 if((*ppFuncDesc)->funcdesc.cParams - param <=
2600 (*ppFuncDesc)->funcdesc.cParamsOpt)
2601 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2603 if(paramName) {
2604 (*ppFuncDesc)->pParamDesc[param].Name =
2605 TLB_MultiByteToBSTR(paramName);
2609 ppFuncDesc = &((*ppFuncDesc)->next);
2610 if(pFunc->next == 0xffff) break;
2612 pTI->TypeAttr.cFuncs = num;
2613 dump_TLBFuncDesc(pTI->funclist);
2614 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2617 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2618 char *pNameTable)
2620 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2621 SLTG_MemberHeader *pMemHeader;
2622 SLTG_RecordItem *pItem;
2623 char *pFirstItem;
2624 TLBVarDesc **ppVarDesc = &pTI->varlist;
2625 int num = 0;
2626 WORD *pType;
2627 char buf[300];
2629 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2631 pFirstItem = (char*)(pMemHeader + 1);
2632 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2633 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2634 if(pItem->magic != SLTG_RECORD_MAGIC) {
2635 FIXME("record magic = %02x\n", pItem->magic);
2636 return NULL;
2638 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2639 sizeof(**ppVarDesc));
2640 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2641 (*ppVarDesc)->vardesc.memid = pItem->memid;
2642 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2643 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2645 if(pItem->typepos == 0x02)
2646 pType = &pItem->type;
2647 else if(pItem->typepos == 0x00)
2648 pType = (WORD*)(pFirstItem + pItem->type);
2649 else {
2650 FIXME("typepos = %02x\n", pItem->typepos);
2651 break;
2654 SLTG_DoType(pType, pFirstItem,
2655 &(*ppVarDesc)->vardesc.elemdescVar);
2657 /* FIXME("helpcontext, helpstring\n"); */
2659 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2661 ppVarDesc = &((*ppVarDesc)->next);
2662 if(pItem->next == 0xffff) break;
2664 pTI->TypeAttr.cVars = num;
2665 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2668 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2669 char *pNameTable)
2671 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2672 SLTG_MemberHeader *pMemHeader;
2673 SLTG_EnumItem *pItem;
2674 char *pFirstItem;
2675 TLBVarDesc **ppVarDesc = &pTI->varlist;
2676 int num = 0;
2678 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2680 pFirstItem = (char*)(pMemHeader + 1);
2681 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2682 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2683 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2684 FIXME("enumitem magic = %04x\n", pItem->magic);
2685 return NULL;
2687 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2688 sizeof(**ppVarDesc));
2689 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2690 (*ppVarDesc)->vardesc.memid = pItem->memid;
2691 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2692 sizeof(VARIANT));
2693 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2694 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2695 *(INT*)(pItem->value + pFirstItem);
2696 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2697 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2698 /* FIXME("helpcontext, helpstring\n"); */
2700 ppVarDesc = &((*ppVarDesc)->next);
2701 if(pItem->next == 0xffff) break;
2703 pTI->TypeAttr.cVars = num;
2704 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2707 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2708 managable copy of it into this */
2709 typedef struct {
2710 WORD small_no;
2711 char *index_name;
2712 char *other_name;
2713 WORD res1a;
2714 WORD name_offs;
2715 WORD more_bytes;
2716 char *extra;
2717 WORD res20;
2718 DWORD helpcontext;
2719 WORD res26;
2720 GUID uuid;
2721 } SLTG_InternalOtherTypeInfo;
2723 /****************************************************************************
2724 * ITypeLib2_Constructor_SLTG
2726 * loading a SLTG typelib from an in-memory image
2728 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2730 ITypeLibImpl *pTypeLibImpl;
2731 SLTG_Header *pHeader;
2732 SLTG_BlkEntry *pBlkEntry;
2733 SLTG_Magic *pMagic;
2734 SLTG_Index *pIndex;
2735 SLTG_Pad9 *pPad9;
2736 LPVOID pBlk, pFirstBlk;
2737 SLTG_LibBlk *pLibBlk;
2738 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2739 char *pAfterOTIBlks = NULL;
2740 char *pNameTable, *ptr;
2741 int i;
2742 DWORD len, order;
2743 ITypeInfoImpl **ppTypeInfoImpl;
2745 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2747 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2748 if (!pTypeLibImpl) return NULL;
2750 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2751 pTypeLibImpl->ref = 1;
2753 pHeader = pLib;
2755 TRACE("header:\n");
2756 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2757 pHeader->nrOfFileBlks );
2758 if (memcmp(&pHeader->SLTG_magic, TLBMAGIC1, 4)) {
2759 FIXME("Header type magic 0x%08lx not supported.\n",
2760 pHeader->SLTG_magic);
2761 return NULL;
2764 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2765 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2767 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2768 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2770 /* Next we have a magic block */
2771 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2773 /* Let's see if we're still in sync */
2774 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2775 sizeof(SLTG_COMPOBJ_MAGIC))) {
2776 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2777 return NULL;
2779 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2780 sizeof(SLTG_DIR_MAGIC))) {
2781 FIXME("dir magic = %s\n", pMagic->dir_magic);
2782 return NULL;
2785 pIndex = (SLTG_Index*)(pMagic+1);
2787 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2789 pFirstBlk = (LPVOID)(pPad9 + 1);
2791 /* We'll set up a ptr to the main library block, which is the last one. */
2793 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2794 pBlkEntry[order].next != 0;
2795 order = pBlkEntry[order].next - 1, i++) {
2796 pBlk += pBlkEntry[order].len;
2798 pLibBlk = pBlk;
2800 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2802 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2803 interspersed */
2805 len += 0x40;
2807 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2809 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2810 sizeof(*pOtherTypeInfoBlks) *
2811 pTypeLibImpl->TypeInfoCount);
2814 ptr = (char*)pLibBlk + len;
2816 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2817 WORD w, extra;
2818 len = 0;
2820 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2822 w = *(WORD*)(ptr + 2);
2823 if(w != 0xffff) {
2824 len += w;
2825 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2826 w+1);
2827 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2828 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2830 w = *(WORD*)(ptr + 4 + len);
2831 if(w != 0xffff) {
2832 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2833 len += w;
2834 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2835 w+1);
2836 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2837 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2839 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2840 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2841 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2842 if(extra) {
2843 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2844 extra);
2845 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2846 len += extra;
2848 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2849 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2850 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2851 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2852 len += sizeof(SLTG_OtherTypeInfo);
2853 ptr += len;
2856 pAfterOTIBlks = ptr;
2858 /* Skip this WORD and get the next DWORD */
2859 len = *(DWORD*)(pAfterOTIBlks + 2);
2861 /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a
2862 magic dust and we should be pointing at the beginning of the name
2863 table */
2865 pNameTable = (char*)pLibBlk + len + 0x216;
2867 pNameTable += 2;
2869 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
2871 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
2874 /* Hopefully we now have enough ptrs set up to actually read in
2875 some TypeInfos. It's not clear which order to do them in, so
2876 I'll just follow the links along the BlkEntry chain and read
2877 them in in the order in which they're in the file */
2879 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
2881 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2882 pBlkEntry[order].next != 0;
2883 order = pBlkEntry[order].next - 1, i++) {
2885 SLTG_TypeInfoHeader *pTIHeader;
2886 SLTG_TypeInfoTail *pTITail;
2888 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
2889 pOtherTypeInfoBlks[i].index_name)) {
2890 FIXME("Index strings don't match\n");
2891 return NULL;
2894 pTIHeader = pBlk;
2895 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
2896 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
2897 return NULL;
2899 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
2900 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
2901 ITypeLib2_AddRef((ITypeLib2 *)pTypeLibImpl);
2902 (*ppTypeInfoImpl)->index = i;
2903 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
2904 pOtherTypeInfoBlks[i].name_offs +
2905 pNameTable);
2906 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
2907 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
2908 sizeof(GUID));
2909 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
2910 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
2911 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
2912 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
2913 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
2915 if((pTIHeader->typeflags1 & 7) != 2)
2916 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
2917 if(pTIHeader->typeflags3 != 2)
2918 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
2920 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2921 debugstr_w((*ppTypeInfoImpl)->Name),
2922 typekind_desc[pTIHeader->typekind],
2923 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
2924 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
2926 switch(pTIHeader->typekind) {
2927 case TKIND_ENUM:
2928 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
2929 break;
2931 case TKIND_RECORD:
2932 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
2933 break;
2935 case TKIND_INTERFACE:
2936 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
2937 break;
2939 case TKIND_COCLASS:
2940 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
2941 break;
2943 default:
2944 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
2945 pTITail = NULL;
2946 break;
2950 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
2951 but we've already set those */
2952 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
2953 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
2954 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
2956 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
2957 pBlk += pBlkEntry[order].len;
2960 if(i != pTypeLibImpl->TypeInfoCount) {
2961 FIXME("Somehow processed %d TypeInfos\n", i);
2962 return NULL;
2965 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
2966 return (ITypeLib2*)pTypeLibImpl;
2969 /* ITypeLib::QueryInterface
2971 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
2972 ITypeLib2 * iface,
2973 REFIID riid,
2974 VOID **ppvObject)
2976 ICOM_THIS( ITypeLibImpl, iface);
2978 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
2980 *ppvObject=NULL;
2981 if(IsEqualIID(riid, &IID_IUnknown) ||
2982 IsEqualIID(riid,&IID_ITypeLib)||
2983 IsEqualIID(riid,&IID_ITypeLib2))
2985 *ppvObject = This;
2988 if(*ppvObject)
2990 ITypeLib2_AddRef(iface);
2991 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
2992 return S_OK;
2994 TRACE("-- Interface: E_NOINTERFACE\n");
2995 return E_NOINTERFACE;
2998 /* ITypeLib::AddRef
3000 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3002 ICOM_THIS( ITypeLibImpl, iface);
3004 TRACE("(%p)->ref is %u\n",This, This->ref);
3006 return ++(This->ref);
3009 /* ITypeLib::Release
3011 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3013 ICOM_THIS( ITypeLibImpl, iface);
3015 --(This->ref);
3017 TRACE("(%p)->(%u)\n",This, This->ref);
3019 if (!This->ref)
3021 /* FIXME destroy child objects */
3023 TRACE(" destroying ITypeLib(%p)\n",This);
3025 if (This->Name)
3027 SysFreeString(This->Name);
3028 This->Name = NULL;
3031 if (This->DocString)
3033 SysFreeString(This->DocString);
3034 This->DocString = NULL;
3037 if (This->HelpFile)
3039 SysFreeString(This->HelpFile);
3040 This->HelpFile = NULL;
3043 if (This->HelpStringDll)
3045 SysFreeString(This->HelpStringDll);
3046 This->HelpStringDll = NULL;
3049 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3050 HeapFree(GetProcessHeap(),0,This);
3051 return 0;
3054 return This->ref;
3057 /* ITypeLib::GetTypeInfoCount
3059 * Returns the number of type descriptions in the type library
3061 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3063 ICOM_THIS( ITypeLibImpl, iface);
3064 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3065 return This->TypeInfoCount;
3068 /* ITypeLib::GetTypeInfo
3070 * retrieves the specified type description in the library.
3072 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3073 ITypeLib2 *iface,
3074 UINT index,
3075 ITypeInfo **ppTInfo)
3077 int i;
3079 ICOM_THIS( ITypeLibImpl, iface);
3080 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3082 TRACE("(%p)->(index=%d) \n", This, index);
3084 if (!ppTInfo) return E_INVALIDARG;
3086 /* search element n in list */
3087 for(i=0; i < index; i++)
3089 pTypeInfo = pTypeInfo->next;
3090 if (!pTypeInfo)
3092 TRACE("-- element not found\n");
3093 return TYPE_E_ELEMENTNOTFOUND;
3097 *ppTInfo = (ITypeInfo *) pTypeInfo;
3099 ITypeInfo_AddRef(*ppTInfo);
3100 TRACE("-- found (%p)\n",*ppTInfo);
3101 return S_OK;
3105 /* ITypeLibs::GetTypeInfoType
3107 * Retrieves the type of a type description.
3109 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3110 ITypeLib2 *iface,
3111 UINT index,
3112 TYPEKIND *pTKind)
3114 ICOM_THIS( ITypeLibImpl, iface);
3115 int i;
3116 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3118 TRACE("(%p) index %d \n",This, index);
3120 if(!pTKind) return E_INVALIDARG;
3122 /* search element n in list */
3123 for(i=0; i < index; i++)
3125 if(!pTInfo)
3127 TRACE("-- element not found\n");
3128 return TYPE_E_ELEMENTNOTFOUND;
3130 pTInfo = pTInfo->next;
3133 *pTKind = pTInfo->TypeAttr.typekind;
3134 TRACE("-- found Type (%d)\n", *pTKind);
3135 return S_OK;
3138 /* ITypeLib::GetTypeInfoOfGuid
3140 * Retrieves the type description that corresponds to the specified GUID.
3143 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3144 ITypeLib2 *iface,
3145 REFGUID guid,
3146 ITypeInfo **ppTInfo)
3148 ICOM_THIS( ITypeLibImpl, iface);
3149 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3151 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3153 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3155 /* search linked list for guid */
3156 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3158 pTypeInfo = pTypeInfo->next;
3160 if (!pTypeInfo)
3162 /* end of list reached */
3163 TRACE("-- element not found\n");
3164 return TYPE_E_ELEMENTNOTFOUND;
3168 TRACE("-- found (%p, %s)\n",
3169 pTypeInfo,
3170 debugstr_w(pTypeInfo->Name));
3172 *ppTInfo = (ITypeInfo*)pTypeInfo;
3173 ITypeInfo_AddRef(*ppTInfo);
3174 return S_OK;
3177 /* ITypeLib::GetLibAttr
3179 * Retrieves the structure that contains the library's attributes.
3182 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3183 ITypeLib2 *iface,
3184 LPTLIBATTR *ppTLibAttr)
3186 ICOM_THIS( ITypeLibImpl, iface);
3187 TRACE("(%p)\n",This);
3188 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3189 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3190 return S_OK;
3193 /* ITypeLib::GetTypeComp
3195 * Enables a client compiler to bind to a library's types, variables,
3196 * constants, and global functions.
3199 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3200 ITypeLib2 *iface,
3201 ITypeComp **ppTComp)
3203 ICOM_THIS( ITypeLibImpl, iface);
3204 FIXME("(%p): stub!\n",This);
3205 return E_NOTIMPL;
3208 /* ITypeLib::GetDocumentation
3210 * Retrieves the library's documentation string, the complete Help file name
3211 * and path, and the context identifier for the library Help topic in the Help
3212 * file.
3214 * On a successful return all non-null BSTR pointers will have been set,
3215 * possibly to NULL.
3217 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3218 ITypeLib2 *iface,
3219 INT index,
3220 BSTR *pBstrName,
3221 BSTR *pBstrDocString,
3222 DWORD *pdwHelpContext,
3223 BSTR *pBstrHelpFile)
3225 ICOM_THIS( ITypeLibImpl, iface);
3227 HRESULT result = E_INVALIDARG;
3229 ITypeInfo *pTInfo;
3232 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3233 This, index,
3234 pBstrName, pBstrDocString,
3235 pdwHelpContext, pBstrHelpFile);
3237 if(index<0)
3239 /* documentation for the typelib */
3240 if(pBstrName)
3242 if (This->Name)
3243 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3244 else
3245 *pBstrName = NULL;
3247 if(pBstrDocString)
3249 if (This->DocString)
3250 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3251 else if (This->Name)
3252 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3253 else
3254 *pBstrDocString = NULL;
3256 if(pdwHelpContext)
3258 *pdwHelpContext = This->dwHelpContext;
3260 if(pBstrHelpFile)
3262 if (This->HelpFile)
3263 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3264 else
3265 *pBstrHelpFile = NULL;
3268 result = S_OK;
3270 else
3272 /* for a typeinfo */
3273 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3275 if(SUCCEEDED(result))
3277 result = ITypeInfo_GetDocumentation(pTInfo,
3278 MEMBERID_NIL,
3279 pBstrName,
3280 pBstrDocString,
3281 pdwHelpContext, pBstrHelpFile);
3283 ITypeInfo_Release(pTInfo);
3286 return result;
3287 memerr3:
3288 if (pBstrDocString) SysFreeString (*pBstrDocString);
3289 memerr2:
3290 if (pBstrName) SysFreeString (*pBstrName);
3291 memerr1:
3292 return STG_E_INSUFFICIENTMEMORY;
3295 /* ITypeLib::IsName
3297 * Indicates whether a passed-in string contains the name of a type or member
3298 * described in the library.
3301 static HRESULT WINAPI ITypeLib2_fnIsName(
3302 ITypeLib2 *iface,
3303 LPOLESTR szNameBuf,
3304 ULONG lHashVal,
3305 BOOL *pfName)
3307 ICOM_THIS( ITypeLibImpl, iface);
3308 ITypeInfoImpl *pTInfo;
3309 TLBFuncDesc *pFInfo;
3310 TLBVarDesc *pVInfo;
3311 int i;
3312 UINT nNameBufLen = SysStringLen(szNameBuf);
3314 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3315 pfName);
3317 *pfName=TRUE;
3318 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3319 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3320 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3321 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3322 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3323 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3324 goto ITypeLib2_fnIsName_exit;
3326 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3327 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3330 *pfName=FALSE;
3332 ITypeLib2_fnIsName_exit:
3333 TRACE("(%p)slow! search for %s: %s found!\n", This,
3334 debugstr_w(szNameBuf), *pfName?"NOT":"");
3336 return S_OK;
3339 /* ITypeLib::FindName
3341 * Finds occurrences of a type description in a type library. This may be used
3342 * to quickly verify that a name exists in a type library.
3345 static HRESULT WINAPI ITypeLib2_fnFindName(
3346 ITypeLib2 *iface,
3347 LPOLESTR szNameBuf,
3348 ULONG lHashVal,
3349 ITypeInfo **ppTInfo,
3350 MEMBERID *rgMemId,
3351 UINT16 *pcFound)
3353 ICOM_THIS( ITypeLibImpl, iface);
3354 ITypeInfoImpl *pTInfo;
3355 TLBFuncDesc *pFInfo;
3356 TLBVarDesc *pVInfo;
3357 int i,j = 0;
3359 UINT nNameBufLen = SysStringLen(szNameBuf);
3361 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3362 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3363 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3364 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3365 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3366 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3367 goto ITypeLib2_fnFindName_exit;
3369 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3370 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3371 continue;
3372 ITypeLib2_fnFindName_exit:
3373 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3374 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3375 j++;
3377 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3378 This, *pcFound, debugstr_w(szNameBuf), j);
3380 *pcFound=j;
3382 return S_OK;
3385 /* ITypeLib::ReleaseTLibAttr
3387 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3390 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3391 ITypeLib2 *iface,
3392 TLIBATTR *pTLibAttr)
3394 ICOM_THIS( ITypeLibImpl, iface);
3395 TRACE("freeing (%p)\n",This);
3396 HeapFree(GetProcessHeap(),0,pTLibAttr);
3400 /* ITypeLib2::GetCustData
3402 * gets the custom data
3404 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3405 ITypeLib2 * iface,
3406 REFGUID guid,
3407 VARIANT *pVarVal)
3409 ICOM_THIS( ITypeLibImpl, iface);
3410 TLBCustData *pCData;
3412 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3414 if( IsEqualIID(guid, &pCData->guid)) break;
3417 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3419 if(pCData)
3421 VariantInit( pVarVal);
3422 VariantCopy( pVarVal, &pCData->data);
3423 return S_OK;
3425 return E_INVALIDARG; /* FIXME: correct? */
3428 /* ITypeLib2::GetLibStatistics
3430 * Returns statistics about a type library that are required for efficient
3431 * sizing of hash tables.
3434 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3435 ITypeLib2 * iface,
3436 ULONG *pcUniqueNames,
3437 ULONG *pcchUniqueNames)
3439 ICOM_THIS( ITypeLibImpl, iface);
3441 FIXME("(%p): stub!\n", This);
3443 if(pcUniqueNames) *pcUniqueNames=1;
3444 if(pcchUniqueNames) *pcchUniqueNames=1;
3445 return S_OK;
3448 /* ITypeLib2::GetDocumentation2
3450 * Retrieves the library's documentation string, the complete Help file name
3451 * and path, the localization context to use, and the context ID for the
3452 * library Help topic in the Help file.
3455 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3456 ITypeLib2 * iface,
3457 INT index,
3458 LCID lcid,
3459 BSTR *pbstrHelpString,
3460 DWORD *pdwHelpStringContext,
3461 BSTR *pbstrHelpStringDll)
3463 ICOM_THIS( ITypeLibImpl, iface);
3464 HRESULT result;
3465 ITypeInfo *pTInfo;
3467 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3469 /* the help string should be obtained from the helpstringdll,
3470 * using the _DLLGetDocumentation function, based on the supplied
3471 * lcid. Nice to do sometime...
3473 if(index<0)
3475 /* documentation for the typelib */
3476 if(pbstrHelpString)
3477 *pbstrHelpString=SysAllocString(This->DocString);
3478 if(pdwHelpStringContext)
3479 *pdwHelpStringContext=This->dwHelpContext;
3480 if(pbstrHelpStringDll)
3481 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3483 result = S_OK;
3485 else
3487 /* for a typeinfo */
3488 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3490 if(SUCCEEDED(result))
3492 ITypeInfo2 * pTInfo2;
3493 result = ITypeInfo_QueryInterface(pTInfo,
3494 &IID_ITypeInfo2,
3495 (LPVOID*) &pTInfo2);
3497 if(SUCCEEDED(result))
3499 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3500 MEMBERID_NIL,
3501 lcid,
3502 pbstrHelpString,
3503 pdwHelpStringContext,
3504 pbstrHelpStringDll);
3506 ITypeInfo2_Release(pTInfo2);
3509 ITypeInfo_Release(pTInfo);
3512 return result;
3515 /* ITypeLib2::GetAllCustData
3517 * Gets all custom data items for the library.
3520 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3521 ITypeLib2 * iface,
3522 CUSTDATA *pCustData)
3524 ICOM_THIS( ITypeLibImpl, iface);
3525 TLBCustData *pCData;
3526 int i;
3527 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3528 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3529 if(pCustData->prgCustData ){
3530 pCustData->cCustData=This->ctCustData;
3531 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3532 pCustData->prgCustData[i].guid=pCData->guid;
3533 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3535 }else{
3536 ERR(" OUT OF MEMORY! \n");
3537 return E_OUTOFMEMORY;
3539 return S_OK;
3542 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3543 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3544 ITypeLib2_fnQueryInterface,
3545 ITypeLib2_fnAddRef,
3546 ITypeLib2_fnRelease,
3547 ITypeLib2_fnGetTypeInfoCount,
3548 ITypeLib2_fnGetTypeInfo,
3549 ITypeLib2_fnGetTypeInfoType,
3550 ITypeLib2_fnGetTypeInfoOfGuid,
3551 ITypeLib2_fnGetLibAttr,
3552 ITypeLib2_fnGetTypeComp,
3553 ITypeLib2_fnGetDocumentation,
3554 ITypeLib2_fnIsName,
3555 ITypeLib2_fnFindName,
3556 ITypeLib2_fnReleaseTLibAttr,
3558 ITypeLib2_fnGetCustData,
3559 ITypeLib2_fnGetLibStatistics,
3560 ITypeLib2_fnGetDocumentation2,
3561 ITypeLib2_fnGetAllCustData
3564 /*================== ITypeInfo(2) Methods ===================================*/
3565 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3567 ITypeInfoImpl * pTypeInfoImpl;
3569 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3570 if (pTypeInfoImpl)
3572 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3573 pTypeInfoImpl->ref=1;
3575 TRACE("(%p)\n", pTypeInfoImpl);
3576 return (ITypeInfo2*) pTypeInfoImpl;
3579 /* ITypeInfo::QueryInterface
3581 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3582 ITypeInfo2 *iface,
3583 REFIID riid,
3584 VOID **ppvObject)
3586 ICOM_THIS( ITypeLibImpl, iface);
3588 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3590 *ppvObject=NULL;
3591 if(IsEqualIID(riid, &IID_IUnknown) ||
3592 IsEqualIID(riid,&IID_ITypeInfo)||
3593 IsEqualIID(riid,&IID_ITypeInfo2))
3594 *ppvObject = This;
3596 if(*ppvObject){
3597 ITypeInfo_AddRef(iface);
3598 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3599 return S_OK;
3601 TRACE("-- Interface: E_NOINTERFACE\n");
3602 return E_NOINTERFACE;
3605 /* ITypeInfo::AddRef
3607 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3609 ICOM_THIS( ITypeInfoImpl, iface);
3611 ++(This->ref);
3613 TRACE("(%p)->ref is %u\n",This, This->ref);
3614 return This->ref;
3617 /* ITypeInfo::Release
3619 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3621 ICOM_THIS( ITypeInfoImpl, iface);
3623 --(This->ref);
3625 TRACE("(%p)->(%u)\n",This, This->ref);
3627 if (!This->ref)
3629 FIXME("destroy child objects\n");
3631 TRACE("destroying ITypeInfo(%p)\n",This);
3632 if (This->Name)
3634 SysFreeString(This->Name);
3635 This->Name = 0;
3638 if (This->DocString)
3640 SysFreeString(This->DocString);
3641 This->DocString = 0;
3644 if (This->next)
3646 ITypeInfo_Release((ITypeInfo*)This->next);
3649 HeapFree(GetProcessHeap(),0,This);
3650 return 0;
3652 return This->ref;
3655 /* ITypeInfo::GetTypeAttr
3657 * Retrieves a TYPEATTR structure that contains the attributes of the type
3658 * description.
3661 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3662 LPTYPEATTR *ppTypeAttr)
3664 ICOM_THIS( ITypeInfoImpl, iface);
3665 TRACE("(%p)\n",This);
3666 /* FIXME: must do a copy here */
3667 *ppTypeAttr=&This->TypeAttr;
3668 return S_OK;
3671 /* ITypeInfo::GetTypeComp
3673 * Retrieves the ITypeComp interface for the type description, which enables a
3674 * client compiler to bind to the type description's members.
3677 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3678 ITypeComp * *ppTComp)
3680 ICOM_THIS( ITypeInfoImpl, iface);
3681 FIXME("(%p) stub!\n", This);
3682 return S_OK;
3685 /* ITypeInfo::GetFuncDesc
3687 * Retrieves the FUNCDESC structure that contains information about a
3688 * specified function.
3691 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3692 LPFUNCDESC *ppFuncDesc)
3694 ICOM_THIS( ITypeInfoImpl, iface);
3695 int i;
3696 TLBFuncDesc * pFDesc;
3697 TRACE("(%p) index %d\n", This, index);
3698 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3700 if(pFDesc){
3701 /* FIXME: must do a copy here */
3702 *ppFuncDesc=&pFDesc->funcdesc;
3703 return S_OK;
3705 return E_INVALIDARG;
3708 /* ITypeInfo::GetVarDesc
3710 * Retrieves a VARDESC structure that describes the specified variable.
3713 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3714 LPVARDESC *ppVarDesc)
3716 ICOM_THIS( ITypeInfoImpl, iface);
3717 int i;
3718 TLBVarDesc * pVDesc;
3719 TRACE("(%p) index %d\n", This, index);
3720 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3722 if(pVDesc){
3723 /* FIXME: must do a copy here */
3724 *ppVarDesc=&pVDesc->vardesc;
3725 return S_OK;
3727 return E_INVALIDARG;
3730 /* ITypeInfo_GetNames
3732 * Retrieves the variable with the specified member ID (or the name of the
3733 * property or method and its parameters) that correspond to the specified
3734 * function ID.
3736 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3737 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3739 ICOM_THIS( ITypeInfoImpl, iface);
3740 TLBFuncDesc * pFDesc;
3741 TLBVarDesc * pVDesc;
3742 int i;
3743 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3744 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3745 if(pFDesc)
3747 /* function found, now return function and parameter names */
3748 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3750 if(!i)
3751 *rgBstrNames=SysAllocString(pFDesc->Name);
3752 else
3753 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3755 *pcNames=i;
3757 else
3759 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3760 if(pVDesc)
3762 *rgBstrNames=SysAllocString(pVDesc->Name);
3763 *pcNames=1;
3765 else
3767 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3769 /* recursive search */
3770 ITypeInfo *pTInfo;
3771 HRESULT result;
3772 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3773 &pTInfo);
3774 if(SUCCEEDED(result))
3776 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3777 ITypeInfo_Release(pTInfo);
3778 return result;
3780 WARN("Could not search inherited interface!\n");
3782 else
3784 WARN("no names found\n");
3786 *pcNames=0;
3787 return TYPE_E_ELEMENTNOTFOUND;
3790 return S_OK;
3794 /* ITypeInfo::GetRefTypeOfImplType
3796 * If a type description describes a COM class, it retrieves the type
3797 * description of the implemented interface types. For an interface,
3798 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3799 * if any exist.
3802 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3803 ITypeInfo2 *iface,
3804 UINT index,
3805 HREFTYPE *pRefType)
3807 ICOM_THIS( ITypeInfoImpl, iface);
3808 int(i);
3809 TLBImplType *pImpl = This->impltypelist;
3811 TRACE("(%p) index %d\n", This, index);
3812 dump_TypeInfo(This);
3814 if(index==(UINT)-1)
3816 /* only valid on dual interfaces;
3817 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3819 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3821 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3822 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3824 *pRefType = -1;
3826 else
3828 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3829 *pRefType = pImpl->hRef;
3832 else
3834 /* get element n from linked list */
3835 for(i=0; pImpl && i<index; i++)
3837 pImpl = pImpl->next;
3840 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3842 *pRefType = pImpl->hRef;
3844 TRACE("-- 0x%08lx\n", pImpl->hRef );
3847 return S_OK;
3851 /* ITypeInfo::GetImplTypeFlags
3853 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3854 * or base interface in a type description.
3856 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
3857 UINT index, INT *pImplTypeFlags)
3859 ICOM_THIS( ITypeInfoImpl, iface);
3860 int i;
3861 TLBImplType *pImpl;
3863 TRACE("(%p) index %d\n", This, index);
3864 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
3865 i++, pImpl=pImpl->next)
3867 if(i==index && pImpl){
3868 *pImplTypeFlags=pImpl->implflags;
3869 return S_OK;
3871 *pImplTypeFlags=0;
3872 return TYPE_E_ELEMENTNOTFOUND;
3875 /* GetIDsOfNames
3876 * Maps between member names and member IDs, and parameter names and
3877 * parameter IDs.
3879 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
3880 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
3882 ICOM_THIS( ITypeInfoImpl, iface);
3883 TLBFuncDesc * pFDesc;
3884 TLBVarDesc * pVDesc;
3885 HRESULT ret=S_OK;
3887 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
3888 cNames);
3889 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
3890 int i, j;
3891 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
3892 if(cNames) *pMemId=pFDesc->funcdesc.memid;
3893 for(i=1; i < cNames; i++){
3894 for(j=0; j<pFDesc->funcdesc.cParams; j++)
3895 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
3896 break;
3897 if( j<pFDesc->funcdesc.cParams)
3898 pMemId[i]=j;
3899 else
3900 ret=DISP_E_UNKNOWNNAME;
3902 return ret;
3905 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
3906 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
3907 if(cNames) *pMemId=pVDesc->vardesc.memid;
3908 return ret;
3911 /* not found, see if this is and interface with an inheritance */
3912 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
3913 This->TypeAttr.cImplTypes ){
3914 /* recursive search */
3915 ITypeInfo *pTInfo;
3916 ret=ITypeInfo_GetRefTypeInfo(iface,
3917 This->impltypelist->hRef, &pTInfo);
3918 if(SUCCEEDED(ret)){
3919 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
3920 ITypeInfo_Release(pTInfo);
3921 return ret;
3923 WARN("Could not search inherited interface!\n");
3924 } else
3925 WARN("no names found\n");
3926 return DISP_E_UNKNOWNNAME;
3929 /* ITypeInfo::Invoke
3931 * Invokes a method, or accesses a property of an object, that implements the
3932 * interface described by the type description.
3934 DWORD
3935 _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
3936 DWORD res;
3938 if (TRACE_ON(ole)) {
3939 int i;
3940 MESSAGE("Calling %p(",func);
3941 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
3942 MESSAGE(")\n");
3945 switch (callconv) {
3946 case CC_STDCALL:
3948 switch (nrargs) {
3949 case 0: {
3950 DWORD (WINAPI *xfunc)() = func;
3951 res = xfunc();
3952 break;
3954 case 1: {
3955 DWORD (WINAPI *xfunc)(DWORD) = func;
3956 res = xfunc(args[0]);
3957 break;
3959 case 2: {
3960 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
3961 res = xfunc(args[0],args[1]);
3962 break;
3964 case 3: {
3965 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
3966 res = xfunc(args[0],args[1],args[2]);
3967 break;
3969 case 4: {
3970 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD) = func;
3971 res = xfunc(args[0],args[1],args[2],args[3]);
3972 break;
3974 case 5: {
3975 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD) = func;
3976 res = xfunc(args[0],args[1],args[2],args[3],args[4]);
3977 break;
3979 case 6: {
3980 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
3981 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5]);
3982 break;
3984 case 7: {
3985 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
3986 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
3987 break;
3989 default:
3990 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
3991 res = -1;
3992 break;
3994 break;
3995 default:
3996 FIXME("unsupported calling convention %d\n",callconv);
3997 res = -1;
3998 break;
4000 TRACE("returns %08lx\n",res);
4001 return res;
4004 static HRESULT WINAPI ITypeInfo_fnInvoke(
4005 ITypeInfo2 *iface,
4006 VOID *pIUnk,
4007 MEMBERID memid,
4008 UINT16 dwFlags,
4009 DISPPARAMS *pDispParams,
4010 VARIANT *pVarResult,
4011 EXCEPINFO *pExcepInfo,
4012 UINT *pArgErr)
4014 ICOM_THIS( ITypeInfoImpl, iface);
4015 TLBFuncDesc * pFDesc;
4016 TLBVarDesc * pVDesc;
4017 int i;
4019 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4020 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4022 dump_DispParms(pDispParams);
4024 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4025 if (pFDesc->funcdesc.memid == memid) {
4026 if (pFDesc->funcdesc.invkind & dwFlags)
4027 break;
4029 if (pFDesc) {
4030 dump_TLBFuncDescOne(pFDesc);
4031 switch (pFDesc->funcdesc.funckind) {
4032 case FUNC_PUREVIRTUAL:
4033 case FUNC_VIRTUAL: {
4034 DWORD res;
4035 DWORD *args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*(pFDesc->funcdesc.cParams+1));
4036 DWORD *args2 = (DWORD*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*(pFDesc->funcdesc.cParams));
4037 args[0] = (DWORD)pIUnk;
4039 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4040 if (i<pDispParams->cArgs) {
4041 TRACE("set %d to disparg type %d vs %d\n",i,
4042 V_VT(&pDispParams->rgvarg[pDispParams->cArgs-i-1]),
4043 pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt
4045 args[i+1] = V_UNION(&pDispParams->rgvarg[pDispParams->cArgs-i-1],lVal);
4046 } else {
4047 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4048 TRACE("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4049 /*FIXME: give pointers for the rest, so propertyget works*/
4050 args[i+1] = (DWORD)&args2[i];
4052 /* If pointer to variant, pass reference to variant
4053 * in result variant array.
4055 if ((tdesc->vt == VT_PTR) &&
4056 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4057 pVarResult
4059 args[i+1] = (DWORD)(pVarResult+(i-pDispParams->cArgs));
4062 if (pFDesc->funcdesc.cParamsOpt)
4063 FIXME("Does not support optional parameters (%d)\n",
4064 pFDesc->funcdesc.cParamsOpt
4067 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4068 pFDesc->funcdesc.callconv,
4069 pFDesc->funcdesc.cParams+1,
4070 args
4072 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4073 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4074 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4075 /* If we are a pointer to a variant, we are done already */
4076 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4077 continue;
4079 VariantInit(&pVarResult[i]);
4080 V_UNION(pVarResult+i,intVal) = args2[i+pDispParams->cArgs];
4082 if (tdesc->vt == VT_PTR)
4083 tdesc = tdesc->u.lptdesc;
4084 V_VT(pVarResult+i) = tdesc->vt;
4086 /* HACK: VB5 likes this.
4087 * I do not know why. There is 1 example in MSDN which uses
4088 * this which appears broken (mixes int vals and
4089 * IDispatch*.).
4091 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4092 V_VT(pVarResult+i) = VT_DISPATCH;
4093 TRACE("storing into variant: [%d]\n", i);
4094 dump_Variant(pVarResult+i);
4097 HeapFree(GetProcessHeap(),0,args2);
4098 HeapFree(GetProcessHeap(),0,args);
4099 return S_OK;
4101 case FUNC_DISPATCH: {
4102 IDispatch *disp;
4103 HRESULT hr;
4105 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4106 if (hr) {
4107 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4108 return hr;
4110 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4111 hr = IDispatch_Invoke(
4112 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4113 pVarResult,pExcepInfo,pArgErr
4115 if (hr)
4116 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4117 IDispatch_Release(disp);
4118 return hr;
4120 default:
4121 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4122 return E_FAIL;
4124 } else {
4125 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4126 if (pVDesc->vardesc.memid == memid) {
4127 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4128 dump_TLBVarDesc(pVDesc);
4129 break;
4133 /* not found, look for it in inherited interfaces */
4134 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4135 /* recursive search */
4136 ITypeInfo *pTInfo;
4137 HRESULT hr;
4138 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4139 if(SUCCEEDED(hr)){
4140 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4141 ITypeInfo_Release(pTInfo);
4142 return hr;
4144 WARN("Could not search inherited interface!\n");
4146 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4147 return DISP_E_MEMBERNOTFOUND;
4150 /* ITypeInfo::GetDocumentation
4152 * Retrieves the documentation string, the complete Help file name and path,
4153 * and the context ID for the Help topic for a specified type description.
4155 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4156 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4157 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4159 ICOM_THIS( ITypeInfoImpl, iface);
4160 TLBFuncDesc * pFDesc;
4161 TLBVarDesc * pVDesc;
4162 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4163 " HelpContext(%p) HelpFile(%p)\n",
4164 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4165 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4166 if(pBstrName)
4167 *pBstrName=SysAllocString(This->Name);
4168 if(pBstrDocString)
4169 *pBstrDocString=SysAllocString(This->DocString);
4170 if(pdwHelpContext)
4171 *pdwHelpContext=This->dwHelpContext;
4172 if(pBstrHelpFile)
4173 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4174 return S_OK;
4175 }else {/* for a member */
4176 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4177 if(pFDesc->funcdesc.memid==memid){
4178 if(pBstrName)
4179 *pBstrName = SysAllocString(pFDesc->Name);
4180 if(pBstrDocString)
4181 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4182 if(pdwHelpContext)
4183 *pdwHelpContext=pFDesc->helpcontext;
4184 return S_OK;
4186 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4187 if(pVDesc->vardesc.memid==memid){
4188 FIXME("Not implemented\n");
4189 return S_OK;
4192 return TYPE_E_ELEMENTNOTFOUND;
4195 /* ITypeInfo::GetDllEntry
4197 * Retrieves a description or specification of an entry point for a function
4198 * in a DLL.
4200 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4201 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4202 WORD *pwOrdinal)
4204 ICOM_THIS( ITypeInfoImpl, iface);
4205 FIXME("(%p) stub!\n", This);
4206 return E_FAIL;
4209 /* ITypeInfo::GetRefTypeInfo
4211 * If a type description references other type descriptions, it retrieves
4212 * the referenced type descriptions.
4214 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4215 ITypeInfo2 *iface,
4216 HREFTYPE hRefType,
4217 ITypeInfo **ppTInfo)
4219 ICOM_THIS( ITypeInfoImpl, iface);
4220 HRESULT result = E_FAIL;
4223 if (hRefType == -1 &&
4224 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4225 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4227 /* when we meet a DUAL dispinterface, we must create the interface
4228 * version of it.
4230 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4233 /* the interface version contains the same information as the dispinterface
4234 * copy the contents of the structs.
4236 *pTypeInfoImpl = *This;
4237 pTypeInfoImpl->ref = 1;
4239 /* change the type to interface */
4240 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4242 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4244 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4246 result = S_OK;
4248 } else {
4249 TLBRefType *pRefType;
4250 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4251 if(pRefType->reference == hRefType)
4252 break;
4254 if(!pRefType)
4255 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4256 if(pRefType && hRefType != -1) {
4257 ITypeLib *pTLib = NULL;
4259 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4260 int Index;
4261 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4262 } else {
4263 if(pRefType->pImpTLInfo->pImpTypeLib) {
4264 TRACE("typeinfo in imported typelib that is already loaded\n");
4265 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4266 ITypeLib2_AddRef((ITypeLib*) pTLib);
4267 result = S_OK;
4268 } else {
4269 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4270 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4271 pRefType->pImpTLInfo->wVersionMajor,
4272 pRefType->pImpTLInfo->wVersionMinor,
4273 pRefType->pImpTLInfo->lcid,
4274 &pTLib);
4276 if(!SUCCEEDED(result)) {
4277 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4278 result=LoadTypeLib(libnam, &pTLib);
4279 SysFreeString(libnam);
4281 if(SUCCEEDED(result)) {
4282 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4283 ITypeLib2_AddRef(pTLib);
4287 if(SUCCEEDED(result)) {
4288 if(pRefType->index == TLB_REF_USE_GUID)
4289 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4290 &pRefType->guid,
4291 ppTInfo);
4292 else
4293 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4294 ppTInfo);
4296 if (pTLib != NULL)
4297 ITypeLib2_Release(pTLib);
4301 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4302 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4303 return result;
4306 /* ITypeInfo::AddressOfMember
4308 * Retrieves the addresses of static functions or variables, such as those
4309 * defined in a DLL.
4311 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4312 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4314 ICOM_THIS( ITypeInfoImpl, iface);
4315 FIXME("(%p) stub!\n", This);
4316 return S_OK;
4319 /* ITypeInfo::CreateInstance
4321 * Creates a new instance of a type that describes a component object class
4322 * (coclass).
4324 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4325 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4327 ICOM_THIS( ITypeInfoImpl, iface);
4328 FIXME("(%p) stub!\n", This);
4329 return S_OK;
4332 /* ITypeInfo::GetMops
4334 * Retrieves marshaling information.
4336 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4337 BSTR *pBstrMops)
4339 ICOM_THIS( ITypeInfoImpl, iface);
4340 FIXME("(%p) stub!\n", This);
4341 return S_OK;
4344 /* ITypeInfo::GetContainingTypeLib
4346 * Retrieves the containing type library and the index of the type description
4347 * within that type library.
4349 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4350 ITypeLib * *ppTLib, UINT *pIndex)
4352 ICOM_THIS( ITypeInfoImpl, iface);
4353 if (!pIndex)
4354 return E_INVALIDARG;
4355 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4356 *pIndex=This->index;
4357 ITypeLib2_AddRef(*ppTLib);
4358 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4359 return S_OK;
4362 /* ITypeInfo::ReleaseTypeAttr
4364 * Releases a TYPEATTR previously returned by GetTypeAttr.
4367 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4368 TYPEATTR* pTypeAttr)
4370 ICOM_THIS( ITypeInfoImpl, iface);
4371 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4372 return S_OK;
4375 /* ITypeInfo::ReleaseFuncDesc
4377 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4379 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4380 ITypeInfo2 *iface,
4381 FUNCDESC *pFuncDesc)
4383 ICOM_THIS( ITypeInfoImpl, iface);
4384 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4385 return S_OK;
4388 /* ITypeInfo::ReleaseVarDesc
4390 * Releases a VARDESC previously returned by GetVarDesc.
4392 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4393 VARDESC *pVarDesc)
4395 ICOM_THIS( ITypeInfoImpl, iface);
4396 TRACE("(%p)->(%p)\n", This, pVarDesc);
4397 return S_OK;
4400 /* ITypeInfo2::GetTypeKind
4402 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4405 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4406 TYPEKIND *pTypeKind)
4408 ICOM_THIS( ITypeInfoImpl, iface);
4409 *pTypeKind=This->TypeAttr.typekind;
4410 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4411 return S_OK;
4414 /* ITypeInfo2::GetTypeFlags
4416 * Returns the type flags without any allocations. This returns a DWORD type
4417 * flag, which expands the type flags without growing the TYPEATTR (type
4418 * attribute).
4421 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4422 UINT *pTypeFlags)
4424 ICOM_THIS( ITypeInfoImpl, iface);
4425 *pTypeFlags=This->TypeAttr.wTypeFlags;
4426 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4427 return S_OK;
4430 /* ITypeInfo2::GetFuncIndexOfMemId
4431 * Binds to a specific member based on a known DISPID, where the member name
4432 * is not known (for example, when binding to a default member).
4435 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4436 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4438 ICOM_THIS( ITypeInfoImpl, iface);
4439 TLBFuncDesc *pFuncInfo;
4440 int i;
4441 HRESULT result;
4442 /* FIXME: should check for invKind??? */
4443 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4444 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4445 if(pFuncInfo){
4446 *pFuncIndex=i;
4447 result= S_OK;
4448 }else{
4449 *pFuncIndex=0;
4450 result=E_INVALIDARG;
4452 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4453 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4454 return result;
4457 /* TypeInfo2::GetVarIndexOfMemId
4459 * Binds to a specific member based on a known DISPID, where the member name
4460 * is not known (for example, when binding to a default member).
4463 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4464 MEMBERID memid, UINT *pVarIndex)
4466 ICOM_THIS( ITypeInfoImpl, iface);
4467 TLBVarDesc *pVarInfo;
4468 int i;
4469 HRESULT result;
4470 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4471 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4473 if(pVarInfo){
4474 *pVarIndex=i;
4475 result= S_OK;
4476 }else{
4477 *pVarIndex=0;
4478 result=E_INVALIDARG;
4480 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4481 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4482 return result;
4485 /* ITypeInfo2::GetCustData
4487 * Gets the custom data
4489 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4490 ITypeInfo2 * iface,
4491 REFGUID guid,
4492 VARIANT *pVarVal)
4494 ICOM_THIS( ITypeInfoImpl, iface);
4495 TLBCustData *pCData;
4497 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4498 if( IsEqualIID(guid, &pCData->guid)) break;
4500 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4502 if(pCData)
4504 VariantInit( pVarVal);
4505 VariantCopy( pVarVal, &pCData->data);
4506 return S_OK;
4508 return E_INVALIDARG; /* FIXME: correct? */
4511 /* ITypeInfo2::GetFuncCustData
4513 * Gets the custom data
4515 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4516 ITypeInfo2 * iface,
4517 UINT index,
4518 REFGUID guid,
4519 VARIANT *pVarVal)
4521 ICOM_THIS( ITypeInfoImpl, iface);
4522 TLBCustData *pCData=NULL;
4523 TLBFuncDesc * pFDesc;
4524 int i;
4525 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4526 pFDesc=pFDesc->next);
4528 if(pFDesc)
4529 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4530 if( IsEqualIID(guid, &pCData->guid)) break;
4532 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4534 if(pCData){
4535 VariantInit( pVarVal);
4536 VariantCopy( pVarVal, &pCData->data);
4537 return S_OK;
4539 return E_INVALIDARG; /* FIXME: correct? */
4542 /* ITypeInfo2::GetParamCustData
4544 * Gets the custom data
4546 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4547 ITypeInfo2 * iface,
4548 UINT indexFunc,
4549 UINT indexParam,
4550 REFGUID guid,
4551 VARIANT *pVarVal)
4553 ICOM_THIS( ITypeInfoImpl, iface);
4554 TLBCustData *pCData=NULL;
4555 TLBFuncDesc * pFDesc;
4556 int i;
4558 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4560 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4561 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4562 pCData = pCData->next)
4563 if( IsEqualIID(guid, &pCData->guid)) break;
4565 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4567 if(pCData)
4569 VariantInit( pVarVal);
4570 VariantCopy( pVarVal, &pCData->data);
4571 return S_OK;
4573 return E_INVALIDARG; /* FIXME: correct? */
4576 /* ITypeInfo2::GetVarCustData
4578 * Gets the custom data
4580 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4581 ITypeInfo2 * iface,
4582 UINT index,
4583 REFGUID guid,
4584 VARIANT *pVarVal)
4586 ICOM_THIS( ITypeInfoImpl, iface);
4587 TLBCustData *pCData=NULL;
4588 TLBVarDesc * pVDesc;
4589 int i;
4591 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4593 if(pVDesc)
4595 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4597 if( IsEqualIID(guid, &pCData->guid)) break;
4601 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4603 if(pCData)
4605 VariantInit( pVarVal);
4606 VariantCopy( pVarVal, &pCData->data);
4607 return S_OK;
4609 return E_INVALIDARG; /* FIXME: correct? */
4612 /* ITypeInfo2::GetImplCustData
4614 * Gets the custom data
4616 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4617 ITypeInfo2 * iface,
4618 UINT index,
4619 REFGUID guid,
4620 VARIANT *pVarVal)
4622 ICOM_THIS( ITypeInfoImpl, iface);
4623 TLBCustData *pCData=NULL;
4624 TLBImplType * pRDesc;
4625 int i;
4627 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4629 if(pRDesc)
4631 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4633 if( IsEqualIID(guid, &pCData->guid)) break;
4637 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4639 if(pCData)
4641 VariantInit( pVarVal);
4642 VariantCopy( pVarVal, &pCData->data);
4643 return S_OK;
4645 return E_INVALIDARG; /* FIXME: correct? */
4648 /* ITypeInfo2::GetDocumentation2
4650 * Retrieves the documentation string, the complete Help file name and path,
4651 * the localization context to use, and the context ID for the library Help
4652 * topic in the Help file.
4655 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4656 ITypeInfo2 * iface,
4657 MEMBERID memid,
4658 LCID lcid,
4659 BSTR *pbstrHelpString,
4660 DWORD *pdwHelpStringContext,
4661 BSTR *pbstrHelpStringDll)
4663 ICOM_THIS( ITypeInfoImpl, iface);
4664 TLBFuncDesc * pFDesc;
4665 TLBVarDesc * pVDesc;
4666 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4667 "HelpStringContext(%p) HelpStringDll(%p)\n",
4668 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4669 pbstrHelpStringDll );
4670 /* the help string should be obtained from the helpstringdll,
4671 * using the _DLLGetDocumentation function, based on the supplied
4672 * lcid. Nice to do sometime...
4674 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4675 if(pbstrHelpString)
4676 *pbstrHelpString=SysAllocString(This->Name);
4677 if(pdwHelpStringContext)
4678 *pdwHelpStringContext=This->dwHelpStringContext;
4679 if(pbstrHelpStringDll)
4680 *pbstrHelpStringDll=
4681 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4682 return S_OK;
4683 }else {/* for a member */
4684 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4685 if(pFDesc->funcdesc.memid==memid){
4686 if(pbstrHelpString)
4687 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4688 if(pdwHelpStringContext)
4689 *pdwHelpStringContext=pFDesc->HelpStringContext;
4690 if(pbstrHelpStringDll)
4691 *pbstrHelpStringDll=
4692 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4693 return S_OK;
4695 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4696 if(pVDesc->vardesc.memid==memid){
4697 if(pbstrHelpString)
4698 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4699 if(pdwHelpStringContext)
4700 *pdwHelpStringContext=pVDesc->HelpStringContext;
4701 if(pbstrHelpStringDll)
4702 *pbstrHelpStringDll=
4703 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4704 return S_OK;
4707 return TYPE_E_ELEMENTNOTFOUND;
4710 /* ITypeInfo2::GetAllCustData
4712 * Gets all custom data items for the Type info.
4715 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4716 ITypeInfo2 * iface,
4717 CUSTDATA *pCustData)
4719 ICOM_THIS( ITypeInfoImpl, iface);
4720 TLBCustData *pCData;
4721 int i;
4723 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4725 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4726 if(pCustData->prgCustData ){
4727 pCustData->cCustData=This->ctCustData;
4728 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4729 pCustData->prgCustData[i].guid=pCData->guid;
4730 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4732 }else{
4733 ERR(" OUT OF MEMORY! \n");
4734 return E_OUTOFMEMORY;
4736 return S_OK;
4739 /* ITypeInfo2::GetAllFuncCustData
4741 * Gets all custom data items for the specified Function
4744 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4745 ITypeInfo2 * iface,
4746 UINT index,
4747 CUSTDATA *pCustData)
4749 ICOM_THIS( ITypeInfoImpl, iface);
4750 TLBCustData *pCData;
4751 TLBFuncDesc * pFDesc;
4752 int i;
4753 TRACE("(%p) index %d\n", This, index);
4754 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4755 pFDesc=pFDesc->next)
4757 if(pFDesc){
4758 pCustData->prgCustData =
4759 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4760 if(pCustData->prgCustData ){
4761 pCustData->cCustData=pFDesc->ctCustData;
4762 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4763 pCData = pCData->next){
4764 pCustData->prgCustData[i].guid=pCData->guid;
4765 VariantCopy(& pCustData->prgCustData[i].varValue,
4766 & pCData->data);
4768 }else{
4769 ERR(" OUT OF MEMORY! \n");
4770 return E_OUTOFMEMORY;
4772 return S_OK;
4774 return TYPE_E_ELEMENTNOTFOUND;
4777 /* ITypeInfo2::GetAllParamCustData
4779 * Gets all custom data items for the Functions
4782 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4783 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4785 ICOM_THIS( ITypeInfoImpl, iface);
4786 TLBCustData *pCData=NULL;
4787 TLBFuncDesc * pFDesc;
4788 int i;
4789 TRACE("(%p) index %d\n", This, indexFunc);
4790 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4791 pFDesc=pFDesc->next)
4793 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4794 pCustData->prgCustData =
4795 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4796 sizeof(CUSTDATAITEM));
4797 if(pCustData->prgCustData ){
4798 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
4799 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
4800 pCData; i++, pCData = pCData->next){
4801 pCustData->prgCustData[i].guid=pCData->guid;
4802 VariantCopy(& pCustData->prgCustData[i].varValue,
4803 & pCData->data);
4805 }else{
4806 ERR(" OUT OF MEMORY! \n");
4807 return E_OUTOFMEMORY;
4809 return S_OK;
4811 return TYPE_E_ELEMENTNOTFOUND;
4814 /* ITypeInfo2::GetAllVarCustData
4816 * Gets all custom data items for the specified Variable
4819 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
4820 UINT index, CUSTDATA *pCustData)
4822 ICOM_THIS( ITypeInfoImpl, iface);
4823 TLBCustData *pCData;
4824 TLBVarDesc * pVDesc;
4825 int i;
4826 TRACE("(%p) index %d\n", This, index);
4827 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
4828 pVDesc=pVDesc->next)
4830 if(pVDesc){
4831 pCustData->prgCustData =
4832 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
4833 if(pCustData->prgCustData ){
4834 pCustData->cCustData=pVDesc->ctCustData;
4835 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
4836 pCData = pCData->next){
4837 pCustData->prgCustData[i].guid=pCData->guid;
4838 VariantCopy(& pCustData->prgCustData[i].varValue,
4839 & pCData->data);
4841 }else{
4842 ERR(" OUT OF MEMORY! \n");
4843 return E_OUTOFMEMORY;
4845 return S_OK;
4847 return TYPE_E_ELEMENTNOTFOUND;
4850 /* ITypeInfo2::GetAllImplCustData
4852 * Gets all custom data items for the specified implementation type
4855 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
4856 ITypeInfo2 * iface,
4857 UINT index,
4858 CUSTDATA *pCustData)
4860 ICOM_THIS( ITypeInfoImpl, iface);
4861 TLBCustData *pCData;
4862 TLBImplType * pRDesc;
4863 int i;
4864 TRACE("(%p) index %d\n", This, index);
4865 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
4866 pRDesc=pRDesc->next)
4868 if(pRDesc){
4869 pCustData->prgCustData =
4870 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
4871 if(pCustData->prgCustData ){
4872 pCustData->cCustData=pRDesc->ctCustData;
4873 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
4874 pCData = pCData->next){
4875 pCustData->prgCustData[i].guid=pCData->guid;
4876 VariantCopy(& pCustData->prgCustData[i].varValue,
4877 & pCData->data);
4879 }else{
4880 ERR(" OUT OF MEMORY! \n");
4881 return E_OUTOFMEMORY;
4883 return S_OK;
4885 return TYPE_E_ELEMENTNOTFOUND;
4888 static ICOM_VTABLE(ITypeInfo2) tinfvt =
4890 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4892 ITypeInfo_fnQueryInterface,
4893 ITypeInfo_fnAddRef,
4894 ITypeInfo_fnRelease,
4896 ITypeInfo_fnGetTypeAttr,
4897 ITypeInfo_fnGetTypeComp,
4898 ITypeInfo_fnGetFuncDesc,
4899 ITypeInfo_fnGetVarDesc,
4900 ITypeInfo_fnGetNames,
4901 ITypeInfo_fnGetRefTypeOfImplType,
4902 ITypeInfo_fnGetImplTypeFlags,
4903 ITypeInfo_fnGetIDsOfNames,
4904 ITypeInfo_fnInvoke,
4905 ITypeInfo_fnGetDocumentation,
4906 ITypeInfo_fnGetDllEntry,
4907 ITypeInfo_fnGetRefTypeInfo,
4908 ITypeInfo_fnAddressOfMember,
4909 ITypeInfo_fnCreateInstance,
4910 ITypeInfo_fnGetMops,
4911 ITypeInfo_fnGetContainingTypeLib,
4912 ITypeInfo_fnReleaseTypeAttr,
4913 ITypeInfo_fnReleaseFuncDesc,
4914 ITypeInfo_fnReleaseVarDesc,
4916 ITypeInfo2_fnGetTypeKind,
4917 ITypeInfo2_fnGetTypeFlags,
4918 ITypeInfo2_fnGetFuncIndexOfMemId,
4919 ITypeInfo2_fnGetVarIndexOfMemId,
4920 ITypeInfo2_fnGetCustData,
4921 ITypeInfo2_fnGetFuncCustData,
4922 ITypeInfo2_fnGetParamCustData,
4923 ITypeInfo2_fnGetVarCustData,
4924 ITypeInfo2_fnGetImplTypeCustData,
4925 ITypeInfo2_fnGetDocumentation2,
4926 ITypeInfo2_fnGetAllCustData,
4927 ITypeInfo2_fnGetAllFuncCustData,
4928 ITypeInfo2_fnGetAllParamCustData,
4929 ITypeInfo2_fnGetAllVarCustData,
4930 ITypeInfo2_fnGetAllImplTypeCustData,