Implemented strtolW/strtoulW in libwine_unicode and used it to replace
[wine/testsucceed.git] / dlls / oleaut32 / typelib.c
blobb6d7894f536ee52c12a5d6e684392c112e368e5d
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"
74 WINE_DEFAULT_DEBUG_CHANNEL(ole);
75 WINE_DECLARE_DEBUG_CHANNEL(typelib);
77 /****************************************************************************
78 * QueryPathOfRegTypeLib [TYPELIB.14]
80 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
81 * RETURNS
82 * path of typelib
84 HRESULT WINAPI
85 QueryPathOfRegTypeLib16(
86 REFGUID guid, /* [in] referenced guid */
87 WORD wMaj, /* [in] major version */
88 WORD wMin, /* [in] minor version */
89 LCID lcid, /* [in] locale id */
90 LPBSTR16 path /* [out] path of typelib */
91 ) {
92 char xguid[80];
93 char typelibkey[100],pathname[260];
94 DWORD plen;
96 TRACE("\n");
98 if (HIWORD(guid)) {
99 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
100 guid->Data1, guid->Data2, guid->Data3,
101 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
102 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
103 wMaj,wMin,lcid);
104 } else {
105 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
106 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
107 return E_FAIL;
109 plen = sizeof(pathname);
110 if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
111 /* try again without lang specific id */
112 if (SUBLANGID(lcid))
113 return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
114 FIXME("key %s not found\n",typelibkey);
115 return E_FAIL;
117 *path = SysAllocString16(pathname);
118 return S_OK;
121 /****************************************************************************
122 * QueryPathOfRegTypeLib [OLEAUT32.164]
123 * RETURNS
124 * path of typelib
126 HRESULT WINAPI
127 QueryPathOfRegTypeLib(
128 REFGUID guid, /* [in] referenced guid */
129 WORD wMaj, /* [in] major version */
130 WORD wMin, /* [in] minor version */
131 LCID lcid, /* [in] locale id */
132 LPBSTR path ) /* [out] path of typelib */
134 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
135 string termination character on output strings */
137 HRESULT hr = E_FAIL;
139 LCID myLCID = lcid;
141 char szXGUID[80];
142 char szTypeLibKey[100];
143 char szPath[MAX_PATH];
144 DWORD dwPathLen = sizeof(szPath);
146 if ( !HIWORD(guid) )
148 sprintf(szXGUID,
149 "<guid 0x%08lx>",
150 (DWORD) guid);
152 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
153 return E_FAIL;
156 while (hr != S_OK)
158 sprintf(szTypeLibKey,
159 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
160 guid->Data1, guid->Data2, guid->Data3,
161 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
162 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
163 wMaj,
164 wMin,
165 myLCID);
167 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
169 if (!lcid)
170 break;
171 else if (myLCID == lcid)
173 /* try with sub-langid */
174 myLCID = SUBLANGID(lcid);
176 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
178 /* try with system langid */
179 myLCID = 0;
181 else
183 break;
186 else
188 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
189 BSTR bstrPath = SysAllocStringLen(NULL,len);
191 MultiByteToWideChar(CP_ACP,
192 MB_PRECOMPOSED,
193 szPath,
194 dwPathLen,
195 bstrPath,
196 len);
197 *path = bstrPath;
198 hr = S_OK;
202 if (hr != S_OK)
203 TRACE_(typelib)("%s not found\n", szTypeLibKey);
205 return hr;
208 /******************************************************************************
209 * CreateTypeLib [OLEAUT32.160] creates a typelib
211 * RETURNS
212 * Success: S_OK
213 * Failure: Status
215 HRESULT WINAPI CreateTypeLib(
216 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
218 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
219 return E_FAIL;
221 /******************************************************************************
222 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
223 * NOTES
224 * Docs: OLECHAR FAR* szFile
225 * Docs: iTypeLib FAR* FAR* pptLib
227 * RETURNS
228 * Success: S_OK
229 * Failure: Status
231 HRESULT WINAPI LoadTypeLib16(
232 LPOLESTR szFile, /* [in] Name of file to load from */
233 ITypeLib** pptLib) /* [out] Pointer to pointer to loaded type library */
235 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
237 if (pptLib!=0)
238 *pptLib=0;
240 return E_FAIL;
243 /******************************************************************************
244 * LoadTypeLib [OLEAUT32.161]
245 * Loads and registers a type library
246 * NOTES
247 * Docs: OLECHAR FAR* szFile
248 * Docs: iTypeLib FAR* FAR* pptLib
250 * RETURNS
251 * Success: S_OK
252 * Failure: Status
254 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
256 HRESULT WINAPI LoadTypeLib(
257 const OLECHAR *szFile,/* [in] Name of file to load from */
258 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
260 TRACE("\n");
261 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
264 /******************************************************************************
265 * LoadTypeLibEx [OLEAUT32.183]
266 * Loads and optionally registers a type library
268 * RETURNS
269 * Success: S_OK
270 * Failure: Status
272 HRESULT WINAPI LoadTypeLibEx(
273 LPCOLESTR szFile, /* [in] Name of file to load from */
274 REGKIND regkind, /* [in] Specify kind of registration */
275 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
277 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
278 WCHAR *pIndexStr;
279 HRESULT res;
280 INT index = 1;
281 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
283 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
284 NULL)) {
286 /* Look for a trailing '\\' followed by an index */
287 pIndexStr = strrchrW(szFile, '\\');
288 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
289 index = atoiW(pIndexStr);
290 memcpy(szFileCopy, szFile,
291 (pIndexStr - szFile - 1) * sizeof(WCHAR));
292 szFileCopy[pIndexStr - szFile - 1] = '\0';
293 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
294 szPath,NULL))
295 return TYPE_E_CANTLOADLIBRARY;
296 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
297 return TYPE_E_CANTLOADLIBRARY;
298 } else
299 return TYPE_E_CANTLOADLIBRARY;
302 TRACE("File %s index %d\n", debugstr_w(szPath), index);
304 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
306 if (SUCCEEDED(res))
307 switch(regkind)
309 case REGKIND_DEFAULT:
310 /* FIXME: is this correct? */
311 if (!szFile || !szFile[0] ||
312 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
313 break;
314 /* else fall-through */
315 case REGKIND_REGISTER:
316 /* FIXME: Help path? */
317 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
319 IUnknown_Release(*pptLib);
320 *pptLib = 0;
322 break;
323 case REGKIND_NONE:
324 break;
327 TRACE(" returns %08lx\n",res);
328 return res;
331 /******************************************************************************
332 * LoadRegTypeLib [OLEAUT32.162]
334 HRESULT WINAPI LoadRegTypeLib(
335 REFGUID rguid, /* [in] referenced guid */
336 WORD wVerMajor, /* [in] major version */
337 WORD wVerMinor, /* [in] minor version */
338 LCID lcid, /* [in] locale id */
339 ITypeLib **ppTLib) /* [out] path of typelib */
341 BSTR bstr=NULL;
342 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
344 if(SUCCEEDED(res))
346 res= LoadTypeLib(bstr, ppTLib);
347 SysFreeString(bstr);
350 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
352 return res;
356 /******************************************************************************
357 * RegisterTypeLib [OLEAUT32.163]
358 * Adds information about a type library to the System Registry
359 * NOTES
360 * Docs: ITypeLib FAR * ptlib
361 * Docs: OLECHAR FAR* szFullPath
362 * Docs: OLECHAR FAR* szHelpDir
364 * RETURNS
365 * Success: S_OK
366 * Failure: Status
368 HRESULT WINAPI RegisterTypeLib(
369 ITypeLib * ptlib, /* [in] Pointer to the library*/
370 OLECHAR * szFullPath, /* [in] full Path of the library*/
371 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
372 may be NULL*/
374 HRESULT res;
375 TLIBATTR *attr;
376 OLECHAR guid[80];
377 LPSTR guidA;
378 CHAR keyName[120];
379 HKEY key, subKey;
380 UINT types, tidx;
381 TYPEKIND kind;
382 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
384 if (ptlib == NULL || szFullPath == NULL)
385 return E_INVALIDARG;
387 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
388 return E_FAIL;
390 StringFromGUID2(&attr->guid, guid, 80);
391 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
392 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
393 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
394 HeapFree(GetProcessHeap(), 0, guidA);
396 res = S_OK;
397 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
398 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
400 LPOLESTR doc;
402 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
404 if (RegSetValueExW(key, NULL, 0, REG_SZ,
405 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
406 res = E_FAIL;
408 SysFreeString(doc);
410 else
411 res = E_FAIL;
413 /* FIXME: This *seems* to be 0 always, not sure though */
414 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
415 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
417 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
418 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
419 res = E_FAIL;
421 RegCloseKey(subKey);
423 else
424 res = E_FAIL;
426 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
427 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
429 CHAR buf[20];
430 /* FIXME: is %u correct? */
431 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
432 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
433 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
434 res = E_FAIL;
436 RegCloseKey(key);
438 else
439 res = E_FAIL;
441 /* register OLE Automation-compatible interfaces for this typelib */
442 types = ITypeLib_GetTypeInfoCount(ptlib);
443 for (tidx=0; tidx<types; tidx++) {
444 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
445 LPOLESTR name = NULL;
446 ITypeInfo *tinfo = NULL;
447 BOOL stop = FALSE;
448 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
449 switch (kind) {
450 case TKIND_INTERFACE:
451 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
452 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
453 break;
454 case TKIND_DISPATCH:
455 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
456 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
457 break;
458 case TKIND_COCLASS:
459 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
460 /* coclasses should probably not be registered? */
461 break;
462 default:
463 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
464 break;
466 if (tinfo) {
467 TYPEATTR *tattr = NULL;
468 ITypeInfo_GetTypeAttr(tinfo, &tattr);
469 if (tattr) {
470 TRACE_(typelib)("guid=%s, flags=%04x (",
471 debugstr_guid(&tattr->guid),
472 tattr->wTypeFlags);
473 if (TRACE_ON(typelib)) {
474 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
475 XX(FAPPOBJECT);
476 XX(FCANCREATE);
477 XX(FLICENSED);
478 XX(FPREDECLID);
479 XX(FHIDDEN);
480 XX(FCONTROL);
481 XX(FDUAL);
482 XX(FNONEXTENSIBLE);
483 XX(FOLEAUTOMATION);
484 XX(FRESTRICTED);
485 XX(FAGGREGATABLE);
486 XX(FREPLACEABLE);
487 XX(FDISPATCHABLE);
488 XX(FREVERSEBIND);
489 XX(FPROXY);
490 #undef XX
491 MESSAGE("\n");
494 * FIXME: The 1 is just here until we implement rpcrt4
495 * stub/proxy handling. Until then it helps IShield
496 * v6 to work.
498 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
500 /* register interface<->typelib coupling */
501 StringFromGUID2(&tattr->guid, guid, 80);
502 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
503 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
504 HeapFree(GetProcessHeap(), 0, guidA);
506 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
507 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
508 if (name)
509 RegSetValueExW(key, NULL, 0, REG_SZ,
510 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
512 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
513 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
514 RegSetValueExA(subKey, NULL, 0, REG_SZ,
515 PSOA, strlen(PSOA));
516 RegCloseKey(subKey);
518 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
519 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
520 RegSetValueExA(subKey, NULL, 0, REG_SZ,
521 PSOA, strlen(PSOA));
522 RegCloseKey(subKey);
525 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
526 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
527 CHAR ver[32];
528 StringFromGUID2(&attr->guid, guid, 80);
529 snprintf(ver, sizeof(ver), "%x.%x",
530 attr->wMajorVerNum, attr->wMinorVerNum);
531 RegSetValueExW(subKey, NULL, 0, REG_SZ,
532 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
533 RegSetValueExA(subKey, "Version", 0, REG_SZ,
534 ver, lstrlenA(ver));
535 RegCloseKey(subKey);
537 RegCloseKey(key);
540 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
542 ITypeInfo_Release(tinfo);
544 SysFreeString(name);
545 if (stop) break;
549 ITypeLib_ReleaseTLibAttr(ptlib, attr);
551 return res;
555 /******************************************************************************
556 * UnRegisterTypeLib [OLEAUT32.186]
557 * Removes information about a type library from the System Registry
558 * NOTES
560 * RETURNS
561 * Success: S_OK
562 * Failure: Status
564 HRESULT WINAPI UnRegisterTypeLib(
565 REFGUID libid, /* [in] Guid of the library */
566 WORD wVerMajor, /* [in] major version */
567 WORD wVerMinor, /* [in] minor version */
568 LCID lcid, /* [in] locale id */
569 SYSKIND syskind)
571 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
572 return S_OK; /* FIXME: pretend everything is OK */
575 /****************************************************************************
576 * OaBuildVersion (TYPELIB.15)
578 * known TYPELIB.DLL versions:
580 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
581 * OLE 2.02 1993-94 02 3002
582 * OLE 2.03 23 730
583 * OLE 2.03 03 3025
584 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
585 * OLE 2.1 NT 1993-95 ?? ???
586 * OLE 2.3.1 W95 23 700
587 * OLE2 4.0 NT4SP6 1993-98 40 4277
589 DWORD WINAPI OaBuildVersion16(void)
591 /* FIXME: I'd like to return the highest currently known version value
592 * in case the user didn't force a --winver, but I don't know how
593 * to retrieve the "versionForced" info from misc/version.c :(
594 * (this would be useful in other places, too) */
595 FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
596 switch(GetVersion() & 0x8000ffff) /* mask off build number */
598 case 0x80000a03: /* WIN31 */
599 return MAKELONG(3027, 3); /* WfW 3.11 */
600 case 0x80000004: /* WIN95 */
601 return MAKELONG(700, 23); /* Win95A */
602 case 0x80000a04: /* WIN98 */
603 return MAKELONG(3024, 10); /* W98 SE */
604 case 0x00000004: /* NT4 */
605 return MAKELONG(4277, 40); /* NT4 SP6 */
606 default:
607 FIXME("Version value not known yet. Please investigate it!\n");
608 return 0;
612 /* for better debugging info leave the static out for the time being */
613 #define static
615 /*======================= ITypeLib implementation =======================*/
617 typedef struct tagTLBCustData
619 GUID guid;
620 VARIANT data;
621 struct tagTLBCustData* next;
622 } TLBCustData;
624 /* data structure for import typelibs */
625 typedef struct tagTLBImpLib
627 int offset; /* offset in the file (MSFT)
628 offset in nametable (SLTG)
629 just used to identify library while reading
630 data from file */
631 GUID guid; /* libid */
632 BSTR name; /* name */
634 LCID lcid; /* lcid of imported typelib */
636 WORD wVersionMajor; /* major version number */
637 WORD wVersionMinor; /* minor version number */
639 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
640 NULL if not yet loaded */
641 struct tagTLBImpLib * next;
642 } TLBImpLib;
644 /* internal ITypeLib data */
645 typedef struct tagITypeLibImpl
647 ICOM_VFIELD(ITypeLib2);
648 UINT ref;
649 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
651 /* strings can be stored in tlb as multibyte strings BUT they are *always*
652 * exported to the application as a UNICODE string.
654 BSTR Name;
655 BSTR DocString;
656 BSTR HelpFile;
657 BSTR HelpStringDll;
658 unsigned long dwHelpContext;
659 int TypeInfoCount; /* nr of typeinfo's in librarry */
660 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
661 int ctCustData; /* number of items in cust data list */
662 TLBCustData * pCustData; /* linked list to cust data */
663 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
664 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
665 libary. Only used while read MSFT
666 typelibs */
667 } ITypeLibImpl;
669 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
671 /* ITypeLib methods */
672 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
673 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
675 /*======================= ITypeInfo implementation =======================*/
677 /* data for refernced types */
678 typedef struct tagTLBRefType
680 INT index; /* Type index for internal ref or for external ref
681 it the format is SLTG. -2 indicates to
682 use guid */
684 GUID guid; /* guid of the referenced type */
685 /* if index == TLB_REF_USE_GUID */
687 HREFTYPE reference; /* The href of this ref */
688 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
689 TLB_REF_INTERNAL for internal refs
690 TLB_REF_NOT_FOUND for broken refs */
692 struct tagTLBRefType * next;
693 } TLBRefType;
695 #define TLB_REF_USE_GUID -2
697 #define TLB_REF_INTERNAL (void*)-2
698 #define TLB_REF_NOT_FOUND (void*)-1
700 /* internal Parameter data */
701 typedef struct tagTLBParDesc
703 BSTR Name;
704 int ctCustData;
705 TLBCustData * pCustData; /* linked list to cust data */
706 } TLBParDesc;
708 /* internal Function data */
709 typedef struct tagTLBFuncDesc
711 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
712 BSTR Name; /* the name of this function */
713 TLBParDesc *pParamDesc; /* array with param names and custom data */
714 int helpcontext;
715 int HelpStringContext;
716 BSTR HelpString;
717 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
718 int ctCustData;
719 TLBCustData * pCustData; /* linked list to cust data; */
720 struct tagTLBFuncDesc * next;
721 } TLBFuncDesc;
723 /* internal Variable data */
724 typedef struct tagTLBVarDesc
726 VARDESC vardesc; /* lots of info on the variable and its attributes. */
727 BSTR Name; /* the name of this variable */
728 int HelpContext;
729 int HelpStringContext; /* FIXME: where? */
730 BSTR HelpString;
731 int ctCustData;
732 TLBCustData * pCustData;/* linked list to cust data; */
733 struct tagTLBVarDesc * next;
734 } TLBVarDesc;
736 /* internal implemented interface data */
737 typedef struct tagTLBImplType
739 HREFTYPE hRef; /* hRef of interface */
740 int implflags; /* IMPLFLAG_*s */
741 int ctCustData;
742 TLBCustData * pCustData;/* linked list to custom data; */
743 struct tagTLBImplType *next;
744 } TLBImplType;
746 /* internal TypeInfo data */
747 typedef struct tagITypeInfoImpl
749 ICOM_VFIELD(ITypeInfo2);
750 UINT ref;
751 TYPEATTR TypeAttr ; /* _lots_ of type information. */
752 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
753 int index; /* index in this typelib; */
754 /* type libs seem to store the doc strings in ascii
755 * so why should we do it in unicode?
757 BSTR Name;
758 BSTR DocString;
759 unsigned long dwHelpContext;
760 unsigned long dwHelpStringContext;
762 /* functions */
763 TLBFuncDesc * funclist; /* linked list with function descriptions */
765 /* variables */
766 TLBVarDesc * varlist; /* linked list with variable descriptions */
768 /* Implemented Interfaces */
769 TLBImplType * impltypelist;
771 TLBRefType * reflist;
772 int ctCustData;
773 TLBCustData * pCustData; /* linked list to cust data; */
774 struct tagITypeInfoImpl * next;
775 } ITypeInfoImpl;
777 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
779 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
781 typedef struct tagTLBContext
783 unsigned int oStart; /* start of TLB in file */
784 unsigned int pos; /* current pos */
785 unsigned int length; /* total length */
786 void *mapping; /* memory mapping */
787 MSFT_SegDir * pTblDir;
788 ITypeLibImpl* pLibInfo;
789 } TLBContext;
792 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
795 debug
797 static void dump_VarType(VARTYPE vt,char *szVarType) {
798 /* FIXME : we could have better trace here, depending on the VARTYPE
799 * of the variant
801 if (vt & VT_RESERVED)
802 szVarType += strlen(strcpy(szVarType, "reserved | "));
803 if (vt & VT_BYREF)
804 szVarType += strlen(strcpy(szVarType, "ref to "));
805 if (vt & VT_ARRAY)
806 szVarType += strlen(strcpy(szVarType, "array of "));
807 if (vt & VT_VECTOR)
808 szVarType += strlen(strcpy(szVarType, "vector of "));
809 switch(vt & VT_TYPEMASK) {
810 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
811 case VT_I2: sprintf(szVarType, "VT_I2"); break;
812 case VT_I4: sprintf(szVarType, "VT_I4"); break;
813 case VT_R4: sprintf(szVarType, "VT_R4"); break;
814 case VT_R8: sprintf(szVarType, "VT_R8"); break;
815 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
816 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
817 case VT_CY: sprintf(szVarType, "VT_CY"); break;
818 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
819 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
820 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
821 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
822 case VT_I1: sprintf(szVarType, "VT_I1"); break;
823 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
824 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
825 case VT_INT: sprintf(szVarType, "VT_INT"); break;
826 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
827 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
828 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
829 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
830 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
834 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
835 if (pTD->vt & VT_RESERVED)
836 szVarType += strlen(strcpy(szVarType, "reserved | "));
837 if (pTD->vt & VT_BYREF)
838 szVarType += strlen(strcpy(szVarType, "ref to "));
839 if (pTD->vt & VT_ARRAY)
840 szVarType += strlen(strcpy(szVarType, "array of "));
841 if (pTD->vt & VT_VECTOR)
842 szVarType += strlen(strcpy(szVarType, "vector of "));
843 switch(pTD->vt & VT_TYPEMASK) {
844 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
845 case VT_I2: sprintf(szVarType, "VT_I2"); break;
846 case VT_I4: sprintf(szVarType, "VT_I4"); break;
847 case VT_R4: sprintf(szVarType, "VT_R4"); break;
848 case VT_R8: sprintf(szVarType, "VT_R8"); break;
849 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
850 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
851 case VT_CY: sprintf(szVarType, "VT_CY"); break;
852 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
853 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
854 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
855 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
856 case VT_I1: sprintf(szVarType, "VT_I1"); break;
857 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
858 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
859 case VT_INT: sprintf(szVarType, "VT_INT"); break;
860 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
861 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
862 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
863 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
864 pTD->u.hreftype); break;
865 case VT_PTR: sprintf(szVarType, "ptr to ");
866 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
867 break;
868 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
869 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
870 break;
871 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
872 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
873 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
874 break;
876 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
880 static void dump_ELEMDESC(ELEMDESC *edesc) {
881 char buf[200];
882 dump_TypeDesc(&edesc->tdesc,buf);
883 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
884 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
885 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
887 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
888 int i;
889 MESSAGE("memid is %08lx\n",funcdesc->memid);
890 for (i=0;i<funcdesc->cParams;i++) {
891 MESSAGE("Param %d:\n",i);
892 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
894 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
895 switch (funcdesc->funckind) {
896 case FUNC_VIRTUAL: MESSAGE("virtual");break;
897 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
898 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
899 case FUNC_STATIC: MESSAGE("static");break;
900 case FUNC_DISPATCH: MESSAGE("dispatch");break;
901 default: MESSAGE("unknown");break;
903 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
904 switch (funcdesc->invkind) {
905 case INVOKE_FUNC: MESSAGE("func");break;
906 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
907 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
908 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
910 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
911 switch (funcdesc->callconv) {
912 case CC_CDECL: MESSAGE("cdecl");break;
913 case CC_PASCAL: MESSAGE("pascal");break;
914 case CC_STDCALL: MESSAGE("stdcall");break;
915 case CC_SYSCALL: MESSAGE("syscall");break;
916 default:break;
918 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
919 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
920 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
922 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
924 int i;
925 if (!TRACE_ON(typelib))
926 return;
927 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
928 for (i=0;i<pfd->funcdesc.cParams;i++)
929 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
932 dump_FUNCDESC(&(pfd->funcdesc));
934 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
935 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
937 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
939 while (pfd)
941 dump_TLBFuncDescOne(pfd);
942 pfd = pfd->next;
945 static void dump_TLBVarDesc(TLBVarDesc * pvd)
947 while (pvd)
949 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
950 pvd = pvd->next;
954 static void dump_TLBImpLib(TLBImpLib *import)
956 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
957 debugstr_w(import->name));
958 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
959 import->wVersionMinor, import->lcid, import->offset);
962 static void dump_TLBRefType(TLBRefType * prt)
964 while (prt)
966 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
967 if(prt->index == -1)
968 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
969 else
970 TRACE_(typelib)("type no: %d\n", prt->index);
972 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
973 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
974 TRACE_(typelib)("in lib\n");
975 dump_TLBImpLib(prt->pImpTLInfo);
977 prt = prt->next;
981 static void dump_TLBImplType(TLBImplType * impl)
983 while (impl) {
984 TRACE_(typelib)(
985 "implementing/inheriting interface hRef = %lx implflags %x\n",
986 impl->hRef, impl->implflags);
987 impl = impl->next;
991 static void dump_Variant(VARIANT * pvar)
993 char szVarType[32];
994 LPVOID ref;
996 TRACE("(%p)\n", pvar);
998 if (!pvar) return;
1000 ZeroMemory(szVarType, sizeof(szVarType));
1002 /* FIXME : we could have better trace here, depending on the VARTYPE
1003 * of the variant
1005 dump_VarType(V_VT(pvar),szVarType);
1007 TRACE("VARTYPE: %s\n", szVarType);
1009 if (V_VT(pvar) & VT_BYREF) {
1010 ref = V_UNION(pvar, byref);
1011 TRACE("%p\n", ref);
1013 else ref = &V_UNION(pvar, cVal);
1015 if (V_VT(pvar) & VT_ARRAY) {
1016 /* FIXME */
1017 return;
1019 if (V_VT(pvar) & VT_VECTOR) {
1020 /* FIXME */
1021 return;
1024 switch (V_VT(pvar))
1026 case VT_I2:
1027 TRACE("%d\n", *(short*)ref);
1028 break;
1030 case VT_I4:
1031 TRACE("%d\n", *(INT*)ref);
1032 break;
1034 case VT_R4:
1035 TRACE("%3.3e\n", *(float*)ref);
1036 break;
1038 case VT_R8:
1039 TRACE("%3.3e\n", *(double*)ref);
1040 break;
1042 case VT_BOOL:
1043 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1044 break;
1046 case VT_BSTR:
1047 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1048 break;
1050 case VT_UNKNOWN:
1051 case VT_DISPATCH:
1052 TRACE("%p\n", *(LPVOID*)ref);
1053 break;
1055 case VT_VARIANT:
1056 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1057 break;
1059 default:
1060 TRACE("(?)%ld\n", *(long*)ref);
1061 break;
1065 static void dump_DispParms(DISPPARAMS * pdp)
1067 int index = 0;
1069 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1071 while (index < pdp->cArgs)
1073 dump_Variant( &pdp->rgvarg[index] );
1074 ++index;
1078 static char * typekind_desc[] =
1080 "TKIND_ENUM",
1081 "TKIND_RECORD",
1082 "TKIND_MODULE",
1083 "TKIND_INTERFACE",
1084 "TKIND_DISPATCH",
1085 "TKIND_COCLASS",
1086 "TKIND_ALIAS",
1087 "TKIND_UNION",
1088 "TKIND_MAX"
1091 static void dump_TypeInfo(ITypeInfoImpl * pty)
1093 TRACE("%p ref=%u\n", pty, pty->ref);
1094 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1095 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1096 TRACE("fct:%u var:%u impl:%u\n",
1097 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1098 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1099 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1100 dump_TLBFuncDesc(pty->funclist);
1101 dump_TLBVarDesc(pty->varlist);
1102 dump_TLBImplType(pty->impltypelist);
1105 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1107 /* VT_LPWSTR is largest type that */
1108 /* may appear in type description*/
1109 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1110 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1111 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1112 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1113 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1114 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1115 {{0},30},{{0},31}
1118 static void TLB_abort()
1120 DebugBreak();
1122 static void * TLB_Alloc(unsigned size)
1124 void * ret;
1125 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1126 /* FIXME */
1127 ERR("cannot allocate memory\n");
1129 return ret;
1132 static void TLB_Free(void * ptr)
1134 HeapFree(GetProcessHeap(), 0, ptr);
1138 /**********************************************************************
1140 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1142 /* read function */
1143 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1145 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1146 pcx->pos, count, pcx->oStart, pcx->length, where);
1148 if (where != DO_NOT_SEEK)
1150 where += pcx->oStart;
1151 if (where > pcx->length)
1153 /* FIXME */
1154 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1155 TLB_abort();
1157 pcx->pos = where;
1159 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1160 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1161 pcx->pos += count;
1162 return count;
1165 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1167 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1169 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1170 memset(pGuid,0, sizeof(GUID));
1171 return;
1173 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1176 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1178 char * name;
1179 MSFT_NameIntro niName;
1180 int lengthInChars;
1181 WCHAR* pwstring = NULL;
1182 BSTR bstrName = NULL;
1184 MSFT_Read(&niName, sizeof(niName), pcx,
1185 pcx->pTblDir->pNametab.offset+offset);
1186 niName.namelen &= 0xFF; /* FIXME: correct ? */
1187 name=TLB_Alloc((niName.namelen & 0xff) +1);
1188 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1189 name[niName.namelen & 0xff]='\0';
1191 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1192 name, -1, NULL, 0);
1194 /* no invalid characters in string */
1195 if (lengthInChars)
1197 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1199 /* don't check for invalid character since this has been done previously */
1200 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1202 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1203 lengthInChars = SysStringLen(bstrName);
1204 HeapFree(GetProcessHeap(), 0, pwstring);
1207 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1208 return bstrName;
1211 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1213 char * string;
1214 INT16 length;
1215 int lengthInChars;
1216 BSTR bstr = NULL;
1218 if(offset<0) return NULL;
1219 MSFT_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1220 if(length <= 0) return 0;
1221 string=TLB_Alloc(length +1);
1222 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1223 string[length]='\0';
1225 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1226 string, -1, NULL, 0);
1228 /* no invalid characters in string */
1229 if (lengthInChars)
1231 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1233 /* don't check for invalid character since this has been done previously */
1234 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1236 bstr = SysAllocStringLen(pwstring, lengthInChars);
1237 lengthInChars = SysStringLen(bstr);
1238 HeapFree(GetProcessHeap(), 0, pwstring);
1241 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1242 return bstr;
1245 * read a value and fill a VARIANT structure
1247 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1249 int size;
1251 TRACE_(typelib)("\n");
1253 if(offset <0) { /* data are packed in here */
1254 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1255 V_UNION(pVar, iVal) = offset & 0xffff;
1256 return;
1258 MSFT_Read(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1259 pcx->pTblDir->pCustData.offset + offset );
1260 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1261 switch (V_VT(pVar)){
1262 case VT_EMPTY: /* FIXME: is this right? */
1263 case VT_NULL: /* FIXME: is this right? */
1264 case VT_I2 : /* this should not happen */
1265 case VT_I4 :
1266 case VT_R4 :
1267 case VT_ERROR :
1268 case VT_BOOL :
1269 case VT_I1 :
1270 case VT_UI1 :
1271 case VT_UI2 :
1272 case VT_UI4 :
1273 case VT_INT :
1274 case VT_UINT :
1275 case VT_VOID : /* FIXME: is this right? */
1276 case VT_HRESULT :
1277 size=4; break;
1278 case VT_R8 :
1279 case VT_CY :
1280 case VT_DATE :
1281 case VT_I8 :
1282 case VT_UI8 :
1283 case VT_DECIMAL : /* FIXME: is this right? */
1284 case VT_FILETIME :
1285 size=8;break;
1286 /* pointer types with known behaviour */
1287 case VT_BSTR :{
1288 char * ptr;
1289 MSFT_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1290 if(size <= 0) {
1291 FIXME("BSTR length = %d?\n", size);
1292 } else {
1293 ptr=TLB_Alloc(size);/* allocate temp buffer */
1294 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1295 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1296 /* FIXME: do we need a AtoW conversion here? */
1297 V_UNION(pVar, bstrVal[size])=L'\0';
1298 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1299 TLB_Free(ptr);
1302 size=-4; break;
1303 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1304 case VT_DISPATCH :
1305 case VT_VARIANT :
1306 case VT_UNKNOWN :
1307 case VT_PTR :
1308 case VT_SAFEARRAY :
1309 case VT_CARRAY :
1310 case VT_USERDEFINED :
1311 case VT_LPSTR :
1312 case VT_LPWSTR :
1313 case VT_BLOB :
1314 case VT_STREAM :
1315 case VT_STORAGE :
1316 case VT_STREAMED_OBJECT :
1317 case VT_STORED_OBJECT :
1318 case VT_BLOB_OBJECT :
1319 case VT_CF :
1320 case VT_CLSID :
1321 default:
1322 size=0;
1323 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1324 V_VT(pVar));
1327 if(size>0) /* (big|small) endian correct? */
1328 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1329 return;
1332 * create a linked list with custom data
1334 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1336 MSFT_CDGuid entry;
1337 TLBCustData* pNew;
1338 int count=0;
1340 TRACE_(typelib)("\n");
1342 while(offset >=0){
1343 count++;
1344 pNew=TLB_Alloc(sizeof(TLBCustData));
1345 MSFT_Read(&entry, sizeof(entry), pcx,
1346 pcx->pTblDir->pCDGuids.offset+offset);
1347 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1348 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1349 /* add new custom data at head of the list */
1350 pNew->next=*ppCustData;
1351 *ppCustData=pNew;
1352 offset = entry.next;
1354 return count;
1357 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1358 ITypeInfoImpl *pTI)
1360 if(type <0)
1361 pTd->vt=type & VT_TYPEMASK;
1362 else
1363 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1365 if(pTd->vt == VT_USERDEFINED)
1366 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1368 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1371 static void
1372 MSFT_DoFuncs(TLBContext* pcx,
1373 ITypeInfoImpl* pTI,
1374 int cFuncs,
1375 int cVars,
1376 int offset,
1377 TLBFuncDesc** pptfd)
1380 * member information is stored in a data structure at offset
1381 * indicated by the memoffset field of the typeinfo structure
1382 * There are several distinctive parts.
1383 * the first part starts with a field that holds the total length
1384 * of this (first) part excluding this field. Then follow the records,
1385 * for each member there is one record.
1387 * First entry is always the length of the record (excluding this
1388 * length word).
1389 * Rest of the record depends on the type of the member. If there is
1390 * a field indicating the member type (function variable intereface etc)
1391 * I have not found it yet. At this time we depend on the information
1392 * in the type info and the usual order how things are stored.
1394 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1395 * for each member;
1397 * Third is a equal sized array with file offsets to the name entry
1398 * of each member.
1400 * Forth and last (?) part is an array with offsets to the records in the
1401 * first part of this file segment.
1404 int infolen, nameoffset, reclength, nrattributes, i;
1405 int recoffset = offset + sizeof(INT);
1407 char recbuf[512];
1408 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1410 TRACE_(typelib)("\n");
1412 MSFT_Read(&infolen, sizeof(INT), pcx, offset);
1414 for ( i = 0; i < cFuncs ; i++ )
1416 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1418 /* name, eventually add to a hash table */
1419 MSFT_Read(&nameoffset,
1420 sizeof(INT),
1421 pcx,
1422 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1424 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1426 /* read the function information record */
1427 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1429 reclength &= 0x1ff;
1431 MSFT_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1433 /* do the attributes */
1434 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1435 / sizeof(int);
1437 if ( nrattributes > 0 )
1439 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1441 if ( nrattributes > 1 )
1443 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1444 pFuncRec->OptAttr[1]) ;
1446 if ( nrattributes > 2 )
1448 if ( pFuncRec->FKCCIC & 0x2000 )
1450 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1452 else
1454 (*pptfd)->Entry = MSFT_ReadString(pcx,
1455 pFuncRec->OptAttr[2]);
1457 if( nrattributes > 5 )
1459 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1461 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1463 MSFT_CustData(pcx,
1464 pFuncRec->OptAttr[6],
1465 &(*pptfd)->pCustData);
1472 /* fill the FuncDesc Structure */
1473 MSFT_Read( & (*pptfd)->funcdesc.memid,
1474 sizeof(INT), pcx,
1475 offset + infolen + ( i + 1) * sizeof(INT));
1477 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1478 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1479 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1480 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1481 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1482 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1483 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1485 MSFT_GetTdesc(pcx,
1486 pFuncRec->DataType,
1487 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1488 pTI);
1490 /* do the parameters/arguments */
1491 if(pFuncRec->nrargs)
1493 int j = 0;
1494 MSFT_ParameterInfo paraminfo;
1496 (*pptfd)->funcdesc.lprgelemdescParam =
1497 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1499 (*pptfd)->pParamDesc =
1500 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1502 MSFT_Read(&paraminfo,
1503 sizeof(paraminfo),
1504 pcx,
1505 recoffset + reclength -
1506 pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1508 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1510 TYPEDESC* lpArgTypeDesc = 0;
1512 MSFT_GetTdesc(pcx,
1513 paraminfo.DataType,
1514 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1515 pTI);
1517 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1519 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1521 /* SEEK value = jump to offset,
1522 * from there jump to the end of record,
1523 * go back by (j-1) arguments
1525 MSFT_Read( &paraminfo ,
1526 sizeof(MSFT_ParameterInfo), pcx,
1527 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1528 * sizeof(MSFT_ParameterInfo)));
1529 lpArgTypeDesc =
1530 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1532 while ( lpArgTypeDesc != NULL )
1534 switch ( lpArgTypeDesc->vt )
1536 case VT_PTR:
1537 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1538 break;
1540 case VT_CARRAY:
1541 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1542 break;
1544 case VT_USERDEFINED:
1545 MSFT_DoRefType(pcx, pTI,
1546 lpArgTypeDesc->u.hreftype);
1548 lpArgTypeDesc = NULL;
1549 break;
1551 default:
1552 lpArgTypeDesc = NULL;
1558 /* parameter is the return value! */
1559 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1561 TYPEDESC* lpArgTypeDesc;
1563 (*pptfd)->funcdesc.elemdescFunc =
1564 (*pptfd)->funcdesc.lprgelemdescParam[j];
1566 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1568 while ( lpArgTypeDesc != NULL )
1570 switch ( lpArgTypeDesc->vt )
1572 case VT_PTR:
1573 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1574 break;
1575 case VT_CARRAY:
1576 lpArgTypeDesc =
1577 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1579 break;
1581 case VT_USERDEFINED:
1582 MSFT_DoRefType(pcx,
1583 pTI,
1584 lpArgTypeDesc->u.hreftype);
1586 lpArgTypeDesc = NULL;
1587 break;
1589 default:
1590 lpArgTypeDesc = NULL;
1595 /* second time around */
1596 for(j=0;j<pFuncRec->nrargs;j++)
1598 /* name */
1599 (*pptfd)->pParamDesc[j].Name =
1600 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1602 /* default value */
1603 if ( (PARAMFLAG_FHASDEFAULT &
1604 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1605 ((pFuncRec->FKCCIC) & 0x1000) )
1607 INT* pInt = (INT *)((char *)pFuncRec +
1608 reclength -
1609 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1611 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1613 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1614 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1616 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1617 pInt[j], pcx);
1619 /* custom info */
1620 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1622 MSFT_CustData(pcx,
1623 pFuncRec->OptAttr[7+j],
1624 &(*pptfd)->pParamDesc[j].pCustData);
1629 /* scode is not used: archaic win16 stuff FIXME: right? */
1630 (*pptfd)->funcdesc.cScodes = 0 ;
1631 (*pptfd)->funcdesc.lprgscode = NULL ;
1633 pptfd = & ((*pptfd)->next);
1634 recoffset += reclength;
1637 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1638 int cVars, int offset, TLBVarDesc ** pptvd)
1640 int infolen, nameoffset, reclength;
1641 char recbuf[256];
1642 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1643 int i;
1644 int recoffset;
1646 TRACE_(typelib)("\n");
1648 MSFT_Read(&infolen,sizeof(INT), pcx, offset);
1649 MSFT_Read(&recoffset,sizeof(INT), pcx, offset + infolen +
1650 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1651 recoffset += offset+sizeof(INT);
1652 for(i=0;i<cVars;i++){
1653 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1654 /* name, eventually add to a hash table */
1655 MSFT_Read(&nameoffset, sizeof(INT), pcx,
1656 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1657 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1658 /* read the variable information record */
1659 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1660 reclength &=0xff;
1661 MSFT_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1662 /* Optional data */
1663 if(reclength >(6*sizeof(INT)) )
1664 (*pptvd)->HelpContext=pVarRec->HelpContext;
1665 if(reclength >(7*sizeof(INT)) )
1666 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1667 if(reclength >(8*sizeof(INT)) )
1668 if(reclength >(9*sizeof(INT)) )
1669 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1670 /* fill the VarDesc Structure */
1671 MSFT_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1672 offset + infolen + ( i + 1) * sizeof(INT));
1673 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1674 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1675 MSFT_GetTdesc(pcx, pVarRec->DataType,
1676 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1677 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1678 if(pVarRec->VarKind == VAR_CONST ){
1679 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1680 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1681 pVarRec->OffsValue, pcx);
1682 } else
1683 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1684 pptvd=&((*pptvd)->next);
1685 recoffset += reclength;
1688 /* fill in data for a hreftype (offset). When the refernced type is contained
1689 * in the typelib, it's just an (file) offset in the type info base dir.
1690 * If comes from import, it's an offset+1 in the ImpInfo table
1691 * */
1692 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1693 int offset)
1695 int j;
1696 TLBRefType **ppRefType = &pTI->reflist;
1698 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1700 while(*ppRefType) {
1701 if((*ppRefType)->reference == offset)
1702 return;
1703 ppRefType = &(*ppRefType)->next;
1706 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1707 sizeof(**ppRefType));
1709 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1710 /* external typelib */
1711 MSFT_ImpInfo impinfo;
1712 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1714 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1716 MSFT_Read(&impinfo, sizeof(impinfo), pcx,
1717 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1718 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1719 if(pImpLib->offset==impinfo.oImpFile) break;
1720 pImpLib=pImpLib->next;
1722 if(pImpLib){
1723 (*ppRefType)->reference=offset;
1724 (*ppRefType)->pImpTLInfo = pImpLib;
1725 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1726 (*ppRefType)->index = TLB_REF_USE_GUID;
1727 }else{
1728 ERR("Cannot find a reference\n");
1729 (*ppRefType)->reference=-1;
1730 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1732 }else{
1733 /* in this typelib */
1734 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1735 (*ppRefType)->reference=offset;
1736 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1740 /* process Implemented Interfaces of a com class */
1741 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1742 int offset)
1744 int i;
1745 MSFT_RefRecord refrec;
1746 TLBImplType **ppImpl = &pTI->impltypelist;
1748 TRACE_(typelib)("\n");
1750 for(i=0;i<count;i++){
1751 if(offset<0) break; /* paranoia */
1752 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1753 MSFT_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1754 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1755 (*ppImpl)->hRef = refrec.reftype;
1756 (*ppImpl)->implflags=refrec.flags;
1757 (*ppImpl)->ctCustData=
1758 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1759 offset=refrec.onext;
1760 ppImpl=&((*ppImpl)->next);
1764 * process a typeinfo record
1766 ITypeInfoImpl * MSFT_DoTypeInfo(
1767 TLBContext *pcx,
1768 int count,
1769 ITypeLibImpl * pLibInfo)
1771 MSFT_TypeInfoBase tiBase;
1772 ITypeInfoImpl *ptiRet;
1774 TRACE_(typelib)("count=%u\n", count);
1776 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1777 MSFT_Read(&tiBase, sizeof(tiBase) ,pcx ,
1778 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1779 /* this is where we are coming from */
1780 ptiRet->pTypeLib = pLibInfo;
1781 ITypeLib2_AddRef((ITypeLib2 *)pLibInfo);
1782 ptiRet->index=count;
1783 /* fill in the typeattr fields */
1784 FIXME("Assign constructor/destructor memid\n");
1786 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1787 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1788 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1789 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1790 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1791 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1792 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1793 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1794 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1795 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1796 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1797 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1798 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1799 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1800 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1801 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1802 MSFT_GetTdesc(pcx, tiBase.datatype1,
1803 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1805 /* FIXME: */
1806 /* IDLDESC idldescType; *//* never saw this one != zero */
1808 /* name, eventually add to a hash table */
1809 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1810 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1811 /* help info */
1812 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1813 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1814 ptiRet->dwHelpContext=tiBase.helpcontext;
1815 /* note: InfoType's Help file and HelpStringDll come from the containing
1816 * library. Further HelpString and Docstring appear to be the same thing :(
1818 /* functions */
1819 if(ptiRet->TypeAttr.cFuncs >0 )
1820 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1821 ptiRet->TypeAttr.cVars,
1822 tiBase.memoffset, & ptiRet->funclist);
1823 /* variables */
1824 if(ptiRet->TypeAttr.cVars >0 )
1825 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1826 ptiRet->TypeAttr.cVars,
1827 tiBase.memoffset, & ptiRet->varlist);
1828 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1829 switch(ptiRet->TypeAttr.typekind)
1831 case TKIND_COCLASS:
1832 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1833 tiBase.datatype1);
1834 break;
1835 case TKIND_DISPATCH:
1836 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1838 if (tiBase.datatype1 != -1)
1840 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1841 ptiRet->impltypelist->hRef = tiBase.datatype1;
1843 else
1844 { /* FIXME: This is a really bad hack to add IDispatch */
1845 char* szStdOle = "stdole2.tlb\0";
1846 int nStdOleLen = strlen(szStdOle);
1847 TLBRefType **ppRef = &ptiRet->reflist;
1849 while(*ppRef) {
1850 if((*ppRef)->reference == -1)
1851 break;
1852 ppRef = &(*ppRef)->next;
1854 if(!*ppRef) {
1855 *ppRef = TLB_Alloc(sizeof(**ppRef));
1856 (*ppRef)->guid = IID_IDispatch;
1857 (*ppRef)->reference = -1;
1858 (*ppRef)->index = TLB_REF_USE_GUID;
1859 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1860 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1861 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1862 nStdOleLen + 1);
1864 MultiByteToWideChar(CP_ACP,
1865 MB_PRECOMPOSED,
1866 szStdOle,
1868 (*ppRef)->pImpTLInfo->name,
1869 SysStringLen((*ppRef)->pImpTLInfo->name));
1871 (*ppRef)->pImpTLInfo->lcid = 0;
1872 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1873 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1876 break;
1877 default:
1878 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1879 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1880 ptiRet->impltypelist->hRef = tiBase.datatype1;
1881 break;
1884 ptiRet->ctCustData=
1885 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1887 TRACE_(typelib)("%s guid: %s kind:%s\n",
1888 debugstr_w(ptiRet->Name),
1889 debugstr_guid(&ptiRet->TypeAttr.guid),
1890 typekind_desc[ptiRet->TypeAttr.typekind]);
1892 return ptiRet;
1895 /****************************************************************************
1896 * TLB_ReadTypeLib
1898 * find the type of the typelib file and map the typelib resource into
1899 * the memory
1901 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1902 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1903 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1905 int ret = TYPE_E_CANTLOADLIBRARY;
1906 DWORD dwSignature = 0;
1907 HFILE hFile;
1909 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1911 *ppTypeLib = NULL;
1913 /* check the signature of the file */
1914 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1915 if (INVALID_HANDLE_VALUE != hFile)
1917 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1918 if (hMapping)
1920 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1921 if(pBase)
1923 /* retrieve file size */
1924 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1926 /* first try to load as *.tlb */
1927 dwSignature = *((DWORD*) pBase);
1928 if ( dwSignature == MSFT_SIGNATURE)
1930 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1932 else if ( dwSignature == SLTG_SIGNATURE)
1934 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1936 UnmapViewOfFile(pBase);
1938 CloseHandle(hMapping);
1940 CloseHandle(hFile);
1943 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1945 /* find the typelibrary resource*/
1946 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
1947 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1948 if (hinstDLL)
1950 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
1951 "TYPELIB");
1952 if (hrsrc)
1954 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1955 if (hGlobal)
1957 LPVOID pBase = LockResource(hGlobal);
1958 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1960 if (pBase)
1962 /* try to load as incore resource */
1963 dwSignature = *((DWORD*) pBase);
1964 if ( dwSignature == MSFT_SIGNATURE)
1966 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1968 else if ( dwSignature == SLTG_SIGNATURE)
1970 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1972 else
1974 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
1977 FreeResource( hGlobal );
1980 FreeLibrary(hinstDLL);
1984 if(*ppTypeLib)
1985 ret = S_OK;
1986 else
1987 ERR("Loading of typelib %s failed with error %ld\n",
1988 debugstr_w(pszFileName), GetLastError());
1990 return ret;
1993 /*================== ITypeLib(2) Methods ===================================*/
1995 /****************************************************************************
1996 * ITypeLib2_Constructor_MSFT
1998 * loading an MSFT typelib from an in-memory image
2000 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2002 TLBContext cx;
2003 long lPSegDir;
2004 MSFT_Header tlbHeader;
2005 MSFT_SegDir tlbSegDir;
2006 ITypeLibImpl * pTypeLibImpl;
2008 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2010 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2011 if (!pTypeLibImpl) return NULL;
2013 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2014 pTypeLibImpl->ref = 1;
2016 /* get pointer to beginning of typelib data */
2017 cx.pos = 0;
2018 cx.oStart=0;
2019 cx.mapping = pLib;
2020 cx.pLibInfo = pTypeLibImpl;
2021 cx.length = dwTLBLength;
2023 /* read header */
2024 MSFT_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2025 TRACE("header:\n");
2026 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2027 if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
2028 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2029 return NULL;
2031 /* there is a small amount of information here until the next important
2032 * part:
2033 * the segment directory . Try to calculate the amount of data */
2034 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2036 /* now read the segment directory */
2037 TRACE("read segment directory (at %ld)\n",lPSegDir);
2038 MSFT_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2039 cx.pTblDir = &tlbSegDir;
2041 /* just check two entries */
2042 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2044 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2045 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2046 return NULL;
2049 /* now fill our internal data */
2050 /* TLIBATTR fields */
2051 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2053 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2054 /* Windows seems to have zero here, is this correct? */
2055 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2056 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2057 else
2058 pTypeLibImpl->LibAttr.lcid = 0;
2060 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2061 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2062 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2063 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2065 /* name, eventually add to a hash table */
2066 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2068 /* help info */
2069 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2070 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2072 if( tlbHeader.varflags & HELPDLLFLAG)
2074 int offset;
2075 MSFT_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2076 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2079 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2081 /* custom data */
2082 if(tlbHeader.CustomDataOffset >= 0)
2084 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2087 /* fill in typedescriptions */
2088 if(tlbSegDir.pTypdescTab.length > 0)
2090 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2091 INT16 td[4];
2092 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2093 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2094 for(i=0; i<cTD; )
2096 /* FIXME: add several sanity checks here */
2097 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2098 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2100 /* FIXME: check safearray */
2101 if(td[3] < 0)
2102 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2103 else
2104 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2106 else if(td[0] == VT_CARRAY)
2108 /* array descr table here */
2109 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2111 else if(td[0] == VT_USERDEFINED)
2113 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2115 if(++i<cTD) MSFT_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
2118 /* second time around to fill the array subscript info */
2119 for(i=0;i<cTD;i++)
2121 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2122 if(tlbSegDir.pArrayDescriptions.offset>0)
2124 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2125 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2127 if(td[1]<0)
2128 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2129 else
2130 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2132 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2134 for(j = 0; j<td[2]; j++)
2136 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2137 sizeof(INT), &cx, DO_NOT_SEEK);
2138 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2139 sizeof(INT), &cx, DO_NOT_SEEK);
2142 else
2144 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2145 ERR("didn't find array description data\n");
2150 /* imported type libs */
2151 if(tlbSegDir.pImpFiles.offset>0)
2153 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2154 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2155 UINT16 size;
2157 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2159 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2160 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2161 MSFT_Read(&oGuid, sizeof(INT), &cx, offset);
2163 MSFT_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2164 MSFT_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2165 MSFT_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2166 MSFT_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2168 size >>= 2;
2169 (*ppImpLib)->name = TLB_Alloc(size+1);
2170 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2171 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2172 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2174 ppImpLib = &(*ppImpLib)->next;
2178 /* type info's */
2179 if(tlbHeader.nrtypeinfos >= 0 )
2181 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2182 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2183 int i;
2185 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2187 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2189 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2190 ppTI = &((*ppTI)->next);
2191 (pTypeLibImpl->TypeInfoCount)++;
2195 TRACE("(%p)\n", pTypeLibImpl);
2196 return (ITypeLib2*) pTypeLibImpl;
2200 static BSTR TLB_MultiByteToBSTR(char *ptr)
2202 DWORD len;
2203 WCHAR *nameW;
2204 BSTR ret;
2206 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2207 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2208 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2209 ret = SysAllocString(nameW);
2210 HeapFree(GetProcessHeap(), 0, nameW);
2211 return ret;
2214 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2216 char b[3];
2217 int i;
2218 short s;
2220 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2221 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2222 return FALSE;
2225 guid->Data4[0] = s >> 8;
2226 guid->Data4[1] = s & 0xff;
2228 b[2] = '\0';
2229 for(i = 0; i < 6; i++) {
2230 memcpy(b, str + 24 + 2 * i, 2);
2231 guid->Data4[i + 2] = strtol(b, NULL, 16);
2233 return TRUE;
2236 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2238 WORD bytelen;
2239 DWORD len;
2240 WCHAR *nameW;
2242 *pBstr = NULL;
2243 bytelen = *(WORD*)ptr;
2244 if(bytelen == 0xffff) return 2;
2245 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2246 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2247 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2248 *pBstr = SysAllocStringLen(nameW, len);
2249 HeapFree(GetProcessHeap(), 0, nameW);
2250 return bytelen + 2;
2253 static WORD SLTG_ReadStringA(char *ptr, char **str)
2255 WORD bytelen;
2257 *str = NULL;
2258 bytelen = *(WORD*)ptr;
2259 if(bytelen == 0xffff) return 2;
2260 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2261 memcpy(*str, ptr + 2, bytelen);
2262 (*str)[bytelen] = '\0';
2263 return bytelen + 2;
2266 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2268 char *ptr = pLibBlk;
2269 WORD w;
2271 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2272 FIXME("libblk magic = %04x\n", w);
2273 return 0;
2276 ptr += 6;
2277 if((w = *(WORD*)ptr) != 0xffff) {
2278 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2279 ptr += w;
2281 ptr += 2;
2283 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2285 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2287 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2288 ptr += 4;
2290 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2291 ptr += 2;
2293 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2294 ptr += 2;
2296 ptr += 4; /* skip res12 */
2298 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2299 ptr += 2;
2301 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2302 ptr += 2;
2304 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2305 ptr += 2;
2307 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2308 ptr += sizeof(GUID);
2310 return ptr - (char*)pLibBlk;
2313 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2315 BOOL done = FALSE;
2316 TYPEDESC *pTD = &pElem->tdesc;
2318 /* Handle [in/out] first */
2319 if((*pType & 0xc000) == 0xc000)
2320 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2321 else if(*pType & 0x8000)
2322 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2323 else if(*pType & 0x4000)
2324 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2325 else
2326 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2328 if(*pType & 0x2000)
2329 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2331 if(*pType & 0x80)
2332 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2334 while(!done) {
2335 if((*pType & 0xe00) == 0xe00) {
2336 pTD->vt = VT_PTR;
2337 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2338 sizeof(TYPEDESC));
2339 pTD = pTD->u.lptdesc;
2341 switch(*pType & 0x7f) {
2342 case VT_PTR:
2343 pTD->vt = VT_PTR;
2344 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2345 sizeof(TYPEDESC));
2346 pTD = pTD->u.lptdesc;
2347 break;
2349 case VT_USERDEFINED:
2350 pTD->vt = VT_USERDEFINED;
2351 pTD->u.hreftype = *(++pType) / 4;
2352 done = TRUE;
2353 break;
2355 case VT_CARRAY:
2357 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2358 array */
2360 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2362 pTD->vt = VT_CARRAY;
2363 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2364 sizeof(ARRAYDESC) +
2365 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2366 pTD->u.lpadesc->cDims = pSA->cDims;
2367 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2368 pSA->cDims * sizeof(SAFEARRAYBOUND));
2370 pTD = &pTD->u.lpadesc->tdescElem;
2371 break;
2374 case VT_SAFEARRAY:
2376 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2377 useful? */
2379 pType++;
2380 pTD->vt = VT_SAFEARRAY;
2381 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2382 sizeof(TYPEDESC));
2383 pTD = pTD->u.lptdesc;
2384 break;
2386 default:
2387 pTD->vt = *pType & 0x7f;
2388 done = TRUE;
2389 break;
2391 pType++;
2393 return pType;
2397 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2398 char *pNameTable)
2400 int ref;
2401 char *name;
2402 TLBRefType **ppRefType;
2404 if(pRef->magic != SLTG_REF_MAGIC) {
2405 FIXME("Ref magic = %x\n", pRef->magic);
2406 return;
2408 name = ( (char*)(&pRef->names) + pRef->number);
2410 ppRefType = &pTI->reflist;
2411 for(ref = 0; ref < pRef->number >> 3; ref++) {
2412 char *refname;
2413 unsigned int lib_offs, type_num;
2415 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2416 sizeof(**ppRefType));
2418 name += SLTG_ReadStringA(name, &refname);
2419 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2420 FIXME("Can't sscanf ref\n");
2421 if(lib_offs != 0xffff) {
2422 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2424 while(*import) {
2425 if((*import)->offset == lib_offs)
2426 break;
2427 import = &(*import)->next;
2429 if(!*import) {
2430 char fname[MAX_PATH+1];
2431 int len;
2433 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2434 sizeof(**import));
2435 (*import)->offset = lib_offs;
2436 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2437 &(*import)->guid);
2438 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2439 &(*import)->wVersionMajor,
2440 &(*import)->wVersionMinor,
2441 &(*import)->lcid, fname) != 4) {
2442 FIXME("can't sscanf ref %s\n",
2443 pNameTable + lib_offs + 40);
2445 len = strlen(fname);
2446 if(fname[len-1] != '#')
2447 FIXME("fname = %s\n", fname);
2448 fname[len-1] = '\0';
2449 (*import)->name = TLB_MultiByteToBSTR(fname);
2451 (*ppRefType)->pImpTLInfo = *import;
2452 } else { /* internal ref */
2453 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2455 (*ppRefType)->reference = ref;
2456 (*ppRefType)->index = type_num;
2458 HeapFree(GetProcessHeap(), 0, refname);
2459 ppRefType = &(*ppRefType)->next;
2461 if((BYTE)*name != SLTG_REF_MAGIC)
2462 FIXME("End of ref block magic = %x\n", *name);
2463 dump_TLBRefType(pTI->reflist);
2466 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2467 BOOL OneOnly)
2469 SLTG_ImplInfo *info;
2470 TLBImplType **ppImplType = &pTI->impltypelist;
2471 /* I don't really get this structure, usually it's 0x16 bytes
2472 long, but iuser.tlb contains some that are 0x18 bytes long.
2473 That's ok because we can use the next ptr to jump to the next
2474 one. But how do we know the length of the last one? The WORD
2475 at offs 0x8 might be the clue. For now I'm just assuming that
2476 the last one is the regular 0x16 bytes. */
2478 info = (SLTG_ImplInfo*)pBlk;
2479 while(1) {
2480 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2481 sizeof(**ppImplType));
2482 (*ppImplType)->hRef = info->ref;
2483 (*ppImplType)->implflags = info->impltypeflags;
2484 pTI->TypeAttr.cImplTypes++;
2485 ppImplType = &(*ppImplType)->next;
2487 if(info->next == 0xffff)
2488 break;
2489 if(OneOnly)
2490 FIXME("Interface inheriting more than one interface\n");
2491 info = (SLTG_ImplInfo*)(pBlk + info->next);
2493 info++; /* see comment at top of function */
2494 return (char*)info;
2497 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2498 char *pNameTable)
2500 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2501 SLTG_MemberHeader *pMemHeader;
2502 char *pFirstItem, *pNextItem;
2504 if(pTIHeader->href_table != 0xffffffff) {
2505 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2506 pNameTable);
2510 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2512 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2514 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2515 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2518 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2522 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2523 char *pNameTable)
2525 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2526 SLTG_MemberHeader *pMemHeader;
2527 SLTG_Function *pFunc;
2528 char *pFirstItem, *pNextItem;
2529 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2530 int num = 0;
2532 if(pTIHeader->href_table != 0xffffffff) {
2533 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2534 pNameTable);
2537 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2539 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2541 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2542 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2545 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2546 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2548 int param;
2549 WORD *pType, *pArg;
2551 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2552 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2553 FIXME("func magic = %02x\n", pFunc->magic);
2554 return NULL;
2556 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2557 sizeof(**ppFuncDesc));
2558 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2560 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2561 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2562 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2563 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2564 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2565 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2567 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2568 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2570 if(pFunc->retnextopt & 0x80)
2571 pType = &pFunc->rettype;
2572 else
2573 pType = (WORD*)(pFirstItem + pFunc->rettype);
2576 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2578 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2579 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2580 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2581 (*ppFuncDesc)->pParamDesc =
2582 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2583 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2585 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2587 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2588 char *paramName = pNameTable + *pArg;
2589 BOOL HaveOffs;
2590 /* If arg type follows then paramName points to the 2nd
2591 letter of the name, else the next WORD is an offset to
2592 the arg type and paramName points to the first letter.
2593 So let's take one char off paramName and see if we're
2594 pointing at an alpha-numeric char. However if *pArg is
2595 0xffff or 0xfffe then the param has no name, the former
2596 meaning that the next WORD is the type, the latter
2597 meaning the the next WORD is an offset to the type. */
2599 HaveOffs = FALSE;
2600 if(*pArg == 0xffff)
2601 paramName = NULL;
2602 else if(*pArg == 0xfffe) {
2603 paramName = NULL;
2604 HaveOffs = TRUE;
2606 else if(!isalnum(*(paramName-1)))
2607 HaveOffs = TRUE;
2609 pArg++;
2611 if(HaveOffs) { /* the next word is an offset to type */
2612 pType = (WORD*)(pFirstItem + *pArg);
2613 SLTG_DoType(pType, pFirstItem,
2614 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2615 pArg++;
2616 } else {
2617 if(paramName)
2618 paramName--;
2619 pArg = SLTG_DoType(pArg, pFirstItem,
2620 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2623 /* Are we an optional param ? */
2624 if((*ppFuncDesc)->funcdesc.cParams - param <=
2625 (*ppFuncDesc)->funcdesc.cParamsOpt)
2626 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2628 if(paramName) {
2629 (*ppFuncDesc)->pParamDesc[param].Name =
2630 TLB_MultiByteToBSTR(paramName);
2634 ppFuncDesc = &((*ppFuncDesc)->next);
2635 if(pFunc->next == 0xffff) break;
2637 pTI->TypeAttr.cFuncs = num;
2638 dump_TLBFuncDesc(pTI->funclist);
2639 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2642 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2643 char *pNameTable)
2645 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2646 SLTG_MemberHeader *pMemHeader;
2647 SLTG_RecordItem *pItem;
2648 char *pFirstItem;
2649 TLBVarDesc **ppVarDesc = &pTI->varlist;
2650 int num = 0;
2651 WORD *pType;
2652 char buf[300];
2654 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2656 pFirstItem = (char*)(pMemHeader + 1);
2657 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2658 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2659 if(pItem->magic != SLTG_RECORD_MAGIC) {
2660 FIXME("record magic = %02x\n", pItem->magic);
2661 return NULL;
2663 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2664 sizeof(**ppVarDesc));
2665 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2666 (*ppVarDesc)->vardesc.memid = pItem->memid;
2667 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2668 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2670 if(pItem->typepos == 0x02)
2671 pType = &pItem->type;
2672 else if(pItem->typepos == 0x00)
2673 pType = (WORD*)(pFirstItem + pItem->type);
2674 else {
2675 FIXME("typepos = %02x\n", pItem->typepos);
2676 break;
2679 SLTG_DoType(pType, pFirstItem,
2680 &(*ppVarDesc)->vardesc.elemdescVar);
2682 /* FIXME("helpcontext, helpstring\n"); */
2684 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2686 ppVarDesc = &((*ppVarDesc)->next);
2687 if(pItem->next == 0xffff) break;
2689 pTI->TypeAttr.cVars = num;
2690 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2693 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2694 char *pNameTable)
2696 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2697 SLTG_MemberHeader *pMemHeader;
2698 SLTG_EnumItem *pItem;
2699 char *pFirstItem;
2700 TLBVarDesc **ppVarDesc = &pTI->varlist;
2701 int num = 0;
2703 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2705 pFirstItem = (char*)(pMemHeader + 1);
2706 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2707 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2708 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2709 FIXME("enumitem magic = %04x\n", pItem->magic);
2710 return NULL;
2712 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2713 sizeof(**ppVarDesc));
2714 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2715 (*ppVarDesc)->vardesc.memid = pItem->memid;
2716 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2717 sizeof(VARIANT));
2718 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2719 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2720 *(INT*)(pItem->value + pFirstItem);
2721 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2722 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2723 /* FIXME("helpcontext, helpstring\n"); */
2725 ppVarDesc = &((*ppVarDesc)->next);
2726 if(pItem->next == 0xffff) break;
2728 pTI->TypeAttr.cVars = num;
2729 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2732 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2733 managable copy of it into this */
2734 typedef struct {
2735 WORD small_no;
2736 char *index_name;
2737 char *other_name;
2738 WORD res1a;
2739 WORD name_offs;
2740 WORD more_bytes;
2741 char *extra;
2742 WORD res20;
2743 DWORD helpcontext;
2744 WORD res26;
2745 GUID uuid;
2746 } SLTG_InternalOtherTypeInfo;
2748 /****************************************************************************
2749 * ITypeLib2_Constructor_SLTG
2751 * loading a SLTG typelib from an in-memory image
2753 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2755 ITypeLibImpl *pTypeLibImpl;
2756 SLTG_Header *pHeader;
2757 SLTG_BlkEntry *pBlkEntry;
2758 SLTG_Magic *pMagic;
2759 SLTG_Index *pIndex;
2760 SLTG_Pad9 *pPad9;
2761 LPVOID pBlk, pFirstBlk;
2762 SLTG_LibBlk *pLibBlk;
2763 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2764 char *pAfterOTIBlks = NULL;
2765 char *pNameTable, *ptr;
2766 int i;
2767 DWORD len, order;
2768 ITypeInfoImpl **ppTypeInfoImpl;
2770 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2772 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2773 if (!pTypeLibImpl) return NULL;
2775 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2776 pTypeLibImpl->ref = 1;
2778 pHeader = pLib;
2780 TRACE("header:\n");
2781 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2782 pHeader->nrOfFileBlks );
2783 if (memcmp(&pHeader->SLTG_magic, TLBMAGIC1, 4)) {
2784 FIXME("Header type magic 0x%08lx not supported.\n",
2785 pHeader->SLTG_magic);
2786 return NULL;
2789 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2790 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2792 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2793 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2795 /* Next we have a magic block */
2796 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2798 /* Let's see if we're still in sync */
2799 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2800 sizeof(SLTG_COMPOBJ_MAGIC))) {
2801 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2802 return NULL;
2804 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2805 sizeof(SLTG_DIR_MAGIC))) {
2806 FIXME("dir magic = %s\n", pMagic->dir_magic);
2807 return NULL;
2810 pIndex = (SLTG_Index*)(pMagic+1);
2812 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2814 pFirstBlk = (LPVOID)(pPad9 + 1);
2816 /* We'll set up a ptr to the main library block, which is the last one. */
2818 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2819 pBlkEntry[order].next != 0;
2820 order = pBlkEntry[order].next - 1, i++) {
2821 pBlk += pBlkEntry[order].len;
2823 pLibBlk = pBlk;
2825 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2827 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2828 interspersed */
2830 len += 0x40;
2832 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2834 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2835 sizeof(*pOtherTypeInfoBlks) *
2836 pTypeLibImpl->TypeInfoCount);
2839 ptr = (char*)pLibBlk + len;
2841 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2842 WORD w, extra;
2843 len = 0;
2845 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2847 w = *(WORD*)(ptr + 2);
2848 if(w != 0xffff) {
2849 len += w;
2850 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2851 w+1);
2852 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2853 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2855 w = *(WORD*)(ptr + 4 + len);
2856 if(w != 0xffff) {
2857 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2858 len += w;
2859 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2860 w+1);
2861 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2862 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2864 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2865 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2866 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2867 if(extra) {
2868 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2869 extra);
2870 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2871 len += extra;
2873 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2874 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2875 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2876 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2877 len += sizeof(SLTG_OtherTypeInfo);
2878 ptr += len;
2881 pAfterOTIBlks = ptr;
2883 /* Skip this WORD and get the next DWORD */
2884 len = *(DWORD*)(pAfterOTIBlks + 2);
2886 /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a
2887 magic dust and we should be pointing at the beginning of the name
2888 table */
2890 pNameTable = (char*)pLibBlk + len + 0x216;
2892 pNameTable += 2;
2894 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
2896 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
2899 /* Hopefully we now have enough ptrs set up to actually read in
2900 some TypeInfos. It's not clear which order to do them in, so
2901 I'll just follow the links along the BlkEntry chain and read
2902 them in in the order in which they're in the file */
2904 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
2906 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2907 pBlkEntry[order].next != 0;
2908 order = pBlkEntry[order].next - 1, i++) {
2910 SLTG_TypeInfoHeader *pTIHeader;
2911 SLTG_TypeInfoTail *pTITail;
2913 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
2914 pOtherTypeInfoBlks[i].index_name)) {
2915 FIXME("Index strings don't match\n");
2916 return NULL;
2919 pTIHeader = pBlk;
2920 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
2921 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
2922 return NULL;
2924 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
2925 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
2926 ITypeLib2_AddRef((ITypeLib2 *)pTypeLibImpl);
2927 (*ppTypeInfoImpl)->index = i;
2928 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
2929 pOtherTypeInfoBlks[i].name_offs +
2930 pNameTable);
2931 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
2932 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
2933 sizeof(GUID));
2934 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
2935 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
2936 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
2937 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
2938 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
2940 if((pTIHeader->typeflags1 & 7) != 2)
2941 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
2942 if(pTIHeader->typeflags3 != 2)
2943 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
2945 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2946 debugstr_w((*ppTypeInfoImpl)->Name),
2947 typekind_desc[pTIHeader->typekind],
2948 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
2949 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
2951 switch(pTIHeader->typekind) {
2952 case TKIND_ENUM:
2953 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
2954 break;
2956 case TKIND_RECORD:
2957 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
2958 break;
2960 case TKIND_INTERFACE:
2961 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
2962 break;
2964 case TKIND_COCLASS:
2965 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
2966 break;
2968 default:
2969 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
2970 pTITail = NULL;
2971 break;
2975 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
2976 but we've already set those */
2977 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
2978 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
2979 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
2981 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
2982 pBlk += pBlkEntry[order].len;
2985 if(i != pTypeLibImpl->TypeInfoCount) {
2986 FIXME("Somehow processed %d TypeInfos\n", i);
2987 return NULL;
2990 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
2991 return (ITypeLib2*)pTypeLibImpl;
2994 /* ITypeLib::QueryInterface
2996 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
2997 ITypeLib2 * iface,
2998 REFIID riid,
2999 VOID **ppvObject)
3001 ICOM_THIS( ITypeLibImpl, iface);
3003 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3005 *ppvObject=NULL;
3006 if(IsEqualIID(riid, &IID_IUnknown) ||
3007 IsEqualIID(riid,&IID_ITypeLib)||
3008 IsEqualIID(riid,&IID_ITypeLib2))
3010 *ppvObject = This;
3013 if(*ppvObject)
3015 ITypeLib2_AddRef(iface);
3016 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3017 return S_OK;
3019 TRACE("-- Interface: E_NOINTERFACE\n");
3020 return E_NOINTERFACE;
3023 /* ITypeLib::AddRef
3025 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3027 ICOM_THIS( ITypeLibImpl, iface);
3029 TRACE("(%p)->ref is %u\n",This, This->ref);
3031 return ++(This->ref);
3034 /* ITypeLib::Release
3036 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3038 ICOM_THIS( ITypeLibImpl, iface);
3040 --(This->ref);
3042 TRACE("(%p)->(%u)\n",This, This->ref);
3044 if (!This->ref)
3046 /* FIXME destroy child objects */
3048 TRACE(" destroying ITypeLib(%p)\n",This);
3050 if (This->Name)
3052 SysFreeString(This->Name);
3053 This->Name = NULL;
3056 if (This->DocString)
3058 SysFreeString(This->DocString);
3059 This->DocString = NULL;
3062 if (This->HelpFile)
3064 SysFreeString(This->HelpFile);
3065 This->HelpFile = NULL;
3068 if (This->HelpStringDll)
3070 SysFreeString(This->HelpStringDll);
3071 This->HelpStringDll = NULL;
3074 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3075 HeapFree(GetProcessHeap(),0,This);
3076 return 0;
3079 return This->ref;
3082 /* ITypeLib::GetTypeInfoCount
3084 * Returns the number of type descriptions in the type library
3086 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3088 ICOM_THIS( ITypeLibImpl, iface);
3089 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3090 return This->TypeInfoCount;
3093 /* ITypeLib::GetTypeInfo
3095 * retrieves the specified type description in the library.
3097 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3098 ITypeLib2 *iface,
3099 UINT index,
3100 ITypeInfo **ppTInfo)
3102 int i;
3104 ICOM_THIS( ITypeLibImpl, iface);
3105 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3107 TRACE("(%p)->(index=%d) \n", This, index);
3109 if (!ppTInfo) return E_INVALIDARG;
3111 /* search element n in list */
3112 for(i=0; i < index; i++)
3114 pTypeInfo = pTypeInfo->next;
3115 if (!pTypeInfo)
3117 TRACE("-- element not found\n");
3118 return TYPE_E_ELEMENTNOTFOUND;
3122 *ppTInfo = (ITypeInfo *) pTypeInfo;
3124 ITypeInfo_AddRef(*ppTInfo);
3125 TRACE("-- found (%p)\n",*ppTInfo);
3126 return S_OK;
3130 /* ITypeLibs::GetTypeInfoType
3132 * Retrieves the type of a type description.
3134 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3135 ITypeLib2 *iface,
3136 UINT index,
3137 TYPEKIND *pTKind)
3139 ICOM_THIS( ITypeLibImpl, iface);
3140 int i;
3141 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3143 TRACE("(%p) index %d \n",This, index);
3145 if(!pTKind) return E_INVALIDARG;
3147 /* search element n in list */
3148 for(i=0; i < index; i++)
3150 if(!pTInfo)
3152 TRACE("-- element not found\n");
3153 return TYPE_E_ELEMENTNOTFOUND;
3155 pTInfo = pTInfo->next;
3158 *pTKind = pTInfo->TypeAttr.typekind;
3159 TRACE("-- found Type (%d)\n", *pTKind);
3160 return S_OK;
3163 /* ITypeLib::GetTypeInfoOfGuid
3165 * Retrieves the type description that corresponds to the specified GUID.
3168 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3169 ITypeLib2 *iface,
3170 REFGUID guid,
3171 ITypeInfo **ppTInfo)
3173 ICOM_THIS( ITypeLibImpl, iface);
3174 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3176 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3178 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3180 /* search linked list for guid */
3181 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3183 pTypeInfo = pTypeInfo->next;
3185 if (!pTypeInfo)
3187 /* end of list reached */
3188 TRACE("-- element not found\n");
3189 return TYPE_E_ELEMENTNOTFOUND;
3193 TRACE("-- found (%p, %s)\n",
3194 pTypeInfo,
3195 debugstr_w(pTypeInfo->Name));
3197 *ppTInfo = (ITypeInfo*)pTypeInfo;
3198 ITypeInfo_AddRef(*ppTInfo);
3199 return S_OK;
3202 /* ITypeLib::GetLibAttr
3204 * Retrieves the structure that contains the library's attributes.
3207 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3208 ITypeLib2 *iface,
3209 LPTLIBATTR *ppTLibAttr)
3211 ICOM_THIS( ITypeLibImpl, iface);
3212 TRACE("(%p)\n",This);
3213 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3214 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3215 return S_OK;
3218 /* ITypeLib::GetTypeComp
3220 * Enables a client compiler to bind to a library's types, variables,
3221 * constants, and global functions.
3224 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3225 ITypeLib2 *iface,
3226 ITypeComp **ppTComp)
3228 ICOM_THIS( ITypeLibImpl, iface);
3229 FIXME("(%p): stub!\n",This);
3230 return E_NOTIMPL;
3233 /* ITypeLib::GetDocumentation
3235 * Retrieves the library's documentation string, the complete Help file name
3236 * and path, and the context identifier for the library Help topic in the Help
3237 * file.
3239 * On a successful return all non-null BSTR pointers will have been set,
3240 * possibly to NULL.
3242 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3243 ITypeLib2 *iface,
3244 INT index,
3245 BSTR *pBstrName,
3246 BSTR *pBstrDocString,
3247 DWORD *pdwHelpContext,
3248 BSTR *pBstrHelpFile)
3250 ICOM_THIS( ITypeLibImpl, iface);
3252 HRESULT result = E_INVALIDARG;
3254 ITypeInfo *pTInfo;
3257 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3258 This, index,
3259 pBstrName, pBstrDocString,
3260 pdwHelpContext, pBstrHelpFile);
3262 if(index<0)
3264 /* documentation for the typelib */
3265 if(pBstrName)
3267 if (This->Name)
3268 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3269 else
3270 *pBstrName = NULL;
3272 if(pBstrDocString)
3274 if (This->DocString)
3275 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3276 else if (This->Name)
3277 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3278 else
3279 *pBstrDocString = NULL;
3281 if(pdwHelpContext)
3283 *pdwHelpContext = This->dwHelpContext;
3285 if(pBstrHelpFile)
3287 if (This->HelpFile)
3288 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3289 else
3290 *pBstrHelpFile = NULL;
3293 result = S_OK;
3295 else
3297 /* for a typeinfo */
3298 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3300 if(SUCCEEDED(result))
3302 result = ITypeInfo_GetDocumentation(pTInfo,
3303 MEMBERID_NIL,
3304 pBstrName,
3305 pBstrDocString,
3306 pdwHelpContext, pBstrHelpFile);
3308 ITypeInfo_Release(pTInfo);
3311 return result;
3312 memerr3:
3313 if (pBstrDocString) SysFreeString (*pBstrDocString);
3314 memerr2:
3315 if (pBstrName) SysFreeString (*pBstrName);
3316 memerr1:
3317 return STG_E_INSUFFICIENTMEMORY;
3320 /* ITypeLib::IsName
3322 * Indicates whether a passed-in string contains the name of a type or member
3323 * described in the library.
3326 static HRESULT WINAPI ITypeLib2_fnIsName(
3327 ITypeLib2 *iface,
3328 LPOLESTR szNameBuf,
3329 ULONG lHashVal,
3330 BOOL *pfName)
3332 ICOM_THIS( ITypeLibImpl, iface);
3333 ITypeInfoImpl *pTInfo;
3334 TLBFuncDesc *pFInfo;
3335 TLBVarDesc *pVInfo;
3336 int i;
3337 UINT nNameBufLen = SysStringLen(szNameBuf);
3339 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3340 pfName);
3342 *pfName=TRUE;
3343 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3344 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3345 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3346 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3347 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3348 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3349 goto ITypeLib2_fnIsName_exit;
3351 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3352 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3355 *pfName=FALSE;
3357 ITypeLib2_fnIsName_exit:
3358 TRACE("(%p)slow! search for %s: %s found!\n", This,
3359 debugstr_w(szNameBuf), *pfName?"NOT":"");
3361 return S_OK;
3364 /* ITypeLib::FindName
3366 * Finds occurrences of a type description in a type library. This may be used
3367 * to quickly verify that a name exists in a type library.
3370 static HRESULT WINAPI ITypeLib2_fnFindName(
3371 ITypeLib2 *iface,
3372 LPOLESTR szNameBuf,
3373 ULONG lHashVal,
3374 ITypeInfo **ppTInfo,
3375 MEMBERID *rgMemId,
3376 UINT16 *pcFound)
3378 ICOM_THIS( ITypeLibImpl, iface);
3379 ITypeInfoImpl *pTInfo;
3380 TLBFuncDesc *pFInfo;
3381 TLBVarDesc *pVInfo;
3382 int i,j = 0;
3384 UINT nNameBufLen = SysStringLen(szNameBuf);
3386 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3387 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3388 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3389 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3390 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3391 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3392 goto ITypeLib2_fnFindName_exit;
3394 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3395 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3396 continue;
3397 ITypeLib2_fnFindName_exit:
3398 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3399 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3400 j++;
3402 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3403 This, *pcFound, debugstr_w(szNameBuf), j);
3405 *pcFound=j;
3407 return S_OK;
3410 /* ITypeLib::ReleaseTLibAttr
3412 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3415 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3416 ITypeLib2 *iface,
3417 TLIBATTR *pTLibAttr)
3419 ICOM_THIS( ITypeLibImpl, iface);
3420 TRACE("freeing (%p)\n",This);
3421 HeapFree(GetProcessHeap(),0,pTLibAttr);
3425 /* ITypeLib2::GetCustData
3427 * gets the custom data
3429 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3430 ITypeLib2 * iface,
3431 REFGUID guid,
3432 VARIANT *pVarVal)
3434 ICOM_THIS( ITypeLibImpl, iface);
3435 TLBCustData *pCData;
3437 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3439 if( IsEqualIID(guid, &pCData->guid)) break;
3442 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3444 if(pCData)
3446 VariantInit( pVarVal);
3447 VariantCopy( pVarVal, &pCData->data);
3448 return S_OK;
3450 return E_INVALIDARG; /* FIXME: correct? */
3453 /* ITypeLib2::GetLibStatistics
3455 * Returns statistics about a type library that are required for efficient
3456 * sizing of hash tables.
3459 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3460 ITypeLib2 * iface,
3461 ULONG *pcUniqueNames,
3462 ULONG *pcchUniqueNames)
3464 ICOM_THIS( ITypeLibImpl, iface);
3466 FIXME("(%p): stub!\n", This);
3468 if(pcUniqueNames) *pcUniqueNames=1;
3469 if(pcchUniqueNames) *pcchUniqueNames=1;
3470 return S_OK;
3473 /* ITypeLib2::GetDocumentation2
3475 * Retrieves the library's documentation string, the complete Help file name
3476 * and path, the localization context to use, and the context ID for the
3477 * library Help topic in the Help file.
3480 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3481 ITypeLib2 * iface,
3482 INT index,
3483 LCID lcid,
3484 BSTR *pbstrHelpString,
3485 DWORD *pdwHelpStringContext,
3486 BSTR *pbstrHelpStringDll)
3488 ICOM_THIS( ITypeLibImpl, iface);
3489 HRESULT result;
3490 ITypeInfo *pTInfo;
3492 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3494 /* the help string should be obtained from the helpstringdll,
3495 * using the _DLLGetDocumentation function, based on the supplied
3496 * lcid. Nice to do sometime...
3498 if(index<0)
3500 /* documentation for the typelib */
3501 if(pbstrHelpString)
3502 *pbstrHelpString=SysAllocString(This->DocString);
3503 if(pdwHelpStringContext)
3504 *pdwHelpStringContext=This->dwHelpContext;
3505 if(pbstrHelpStringDll)
3506 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3508 result = S_OK;
3510 else
3512 /* for a typeinfo */
3513 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3515 if(SUCCEEDED(result))
3517 ITypeInfo2 * pTInfo2;
3518 result = ITypeInfo_QueryInterface(pTInfo,
3519 &IID_ITypeInfo2,
3520 (LPVOID*) &pTInfo2);
3522 if(SUCCEEDED(result))
3524 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3525 MEMBERID_NIL,
3526 lcid,
3527 pbstrHelpString,
3528 pdwHelpStringContext,
3529 pbstrHelpStringDll);
3531 ITypeInfo2_Release(pTInfo2);
3534 ITypeInfo_Release(pTInfo);
3537 return result;
3540 /* ITypeLib2::GetAllCustData
3542 * Gets all custom data items for the library.
3545 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3546 ITypeLib2 * iface,
3547 CUSTDATA *pCustData)
3549 ICOM_THIS( ITypeLibImpl, iface);
3550 TLBCustData *pCData;
3551 int i;
3552 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3553 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3554 if(pCustData->prgCustData ){
3555 pCustData->cCustData=This->ctCustData;
3556 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3557 pCustData->prgCustData[i].guid=pCData->guid;
3558 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3560 }else{
3561 ERR(" OUT OF MEMORY! \n");
3562 return E_OUTOFMEMORY;
3564 return S_OK;
3567 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3568 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3569 ITypeLib2_fnQueryInterface,
3570 ITypeLib2_fnAddRef,
3571 ITypeLib2_fnRelease,
3572 ITypeLib2_fnGetTypeInfoCount,
3573 ITypeLib2_fnGetTypeInfo,
3574 ITypeLib2_fnGetTypeInfoType,
3575 ITypeLib2_fnGetTypeInfoOfGuid,
3576 ITypeLib2_fnGetLibAttr,
3577 ITypeLib2_fnGetTypeComp,
3578 ITypeLib2_fnGetDocumentation,
3579 ITypeLib2_fnIsName,
3580 ITypeLib2_fnFindName,
3581 ITypeLib2_fnReleaseTLibAttr,
3583 ITypeLib2_fnGetCustData,
3584 ITypeLib2_fnGetLibStatistics,
3585 ITypeLib2_fnGetDocumentation2,
3586 ITypeLib2_fnGetAllCustData
3589 /*================== ITypeInfo(2) Methods ===================================*/
3590 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3592 ITypeInfoImpl * pTypeInfoImpl;
3594 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3595 if (pTypeInfoImpl)
3597 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3598 pTypeInfoImpl->ref=1;
3600 TRACE("(%p)\n", pTypeInfoImpl);
3601 return (ITypeInfo2*) pTypeInfoImpl;
3604 /* ITypeInfo::QueryInterface
3606 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3607 ITypeInfo2 *iface,
3608 REFIID riid,
3609 VOID **ppvObject)
3611 ICOM_THIS( ITypeLibImpl, iface);
3613 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3615 *ppvObject=NULL;
3616 if(IsEqualIID(riid, &IID_IUnknown) ||
3617 IsEqualIID(riid,&IID_ITypeInfo)||
3618 IsEqualIID(riid,&IID_ITypeInfo2))
3619 *ppvObject = This;
3621 if(*ppvObject){
3622 ITypeInfo_AddRef(iface);
3623 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3624 return S_OK;
3626 TRACE("-- Interface: E_NOINTERFACE\n");
3627 return E_NOINTERFACE;
3630 /* ITypeInfo::AddRef
3632 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3634 ICOM_THIS( ITypeInfoImpl, iface);
3636 ++(This->ref);
3638 TRACE("(%p)->ref is %u\n",This, This->ref);
3639 return This->ref;
3642 /* ITypeInfo::Release
3644 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3646 ICOM_THIS( ITypeInfoImpl, iface);
3648 --(This->ref);
3650 TRACE("(%p)->(%u)\n",This, This->ref);
3652 if (!This->ref)
3654 FIXME("destroy child objects\n");
3656 TRACE("destroying ITypeInfo(%p)\n",This);
3657 if (This->Name)
3659 SysFreeString(This->Name);
3660 This->Name = 0;
3663 if (This->DocString)
3665 SysFreeString(This->DocString);
3666 This->DocString = 0;
3669 if (This->next)
3671 ITypeInfo_Release((ITypeInfo*)This->next);
3674 HeapFree(GetProcessHeap(),0,This);
3675 return 0;
3677 return This->ref;
3680 /* ITypeInfo::GetTypeAttr
3682 * Retrieves a TYPEATTR structure that contains the attributes of the type
3683 * description.
3686 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3687 LPTYPEATTR *ppTypeAttr)
3689 ICOM_THIS( ITypeInfoImpl, iface);
3690 TRACE("(%p)\n",This);
3691 /* FIXME: must do a copy here */
3692 *ppTypeAttr=&This->TypeAttr;
3693 return S_OK;
3696 /* ITypeInfo::GetTypeComp
3698 * Retrieves the ITypeComp interface for the type description, which enables a
3699 * client compiler to bind to the type description's members.
3702 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3703 ITypeComp * *ppTComp)
3705 ICOM_THIS( ITypeInfoImpl, iface);
3706 FIXME("(%p) stub!\n", This);
3707 return S_OK;
3710 /* ITypeInfo::GetFuncDesc
3712 * Retrieves the FUNCDESC structure that contains information about a
3713 * specified function.
3716 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3717 LPFUNCDESC *ppFuncDesc)
3719 ICOM_THIS( ITypeInfoImpl, iface);
3720 int i;
3721 TLBFuncDesc * pFDesc;
3722 TRACE("(%p) index %d\n", This, index);
3723 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3725 if(pFDesc){
3726 /* FIXME: must do a copy here */
3727 *ppFuncDesc=&pFDesc->funcdesc;
3728 return S_OK;
3730 return E_INVALIDARG;
3733 /* ITypeInfo::GetVarDesc
3735 * Retrieves a VARDESC structure that describes the specified variable.
3738 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3739 LPVARDESC *ppVarDesc)
3741 ICOM_THIS( ITypeInfoImpl, iface);
3742 int i;
3743 TLBVarDesc * pVDesc;
3744 TRACE("(%p) index %d\n", This, index);
3745 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3747 if(pVDesc){
3748 /* FIXME: must do a copy here */
3749 *ppVarDesc=&pVDesc->vardesc;
3750 return S_OK;
3752 return E_INVALIDARG;
3755 /* ITypeInfo_GetNames
3757 * Retrieves the variable with the specified member ID (or the name of the
3758 * property or method and its parameters) that correspond to the specified
3759 * function ID.
3761 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3762 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3764 ICOM_THIS( ITypeInfoImpl, iface);
3765 TLBFuncDesc * pFDesc;
3766 TLBVarDesc * pVDesc;
3767 int i;
3768 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3769 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3770 if(pFDesc)
3772 /* function found, now return function and parameter names */
3773 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3775 if(!i)
3776 *rgBstrNames=SysAllocString(pFDesc->Name);
3777 else
3778 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3780 *pcNames=i;
3782 else
3784 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3785 if(pVDesc)
3787 *rgBstrNames=SysAllocString(pVDesc->Name);
3788 *pcNames=1;
3790 else
3792 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3794 /* recursive search */
3795 ITypeInfo *pTInfo;
3796 HRESULT result;
3797 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3798 &pTInfo);
3799 if(SUCCEEDED(result))
3801 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3802 ITypeInfo_Release(pTInfo);
3803 return result;
3805 WARN("Could not search inherited interface!\n");
3807 else
3809 WARN("no names found\n");
3811 *pcNames=0;
3812 return TYPE_E_ELEMENTNOTFOUND;
3815 return S_OK;
3819 /* ITypeInfo::GetRefTypeOfImplType
3821 * If a type description describes a COM class, it retrieves the type
3822 * description of the implemented interface types. For an interface,
3823 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3824 * if any exist.
3827 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3828 ITypeInfo2 *iface,
3829 UINT index,
3830 HREFTYPE *pRefType)
3832 ICOM_THIS( ITypeInfoImpl, iface);
3833 int(i);
3834 TLBImplType *pImpl = This->impltypelist;
3836 TRACE("(%p) index %d\n", This, index);
3837 dump_TypeInfo(This);
3839 if(index==(UINT)-1)
3841 /* only valid on dual interfaces;
3842 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3844 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3846 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3847 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3849 *pRefType = -1;
3851 else
3853 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3854 *pRefType = pImpl->hRef;
3857 else
3859 /* get element n from linked list */
3860 for(i=0; pImpl && i<index; i++)
3862 pImpl = pImpl->next;
3865 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3867 *pRefType = pImpl->hRef;
3869 TRACE("-- 0x%08lx\n", pImpl->hRef );
3872 return S_OK;
3876 /* ITypeInfo::GetImplTypeFlags
3878 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3879 * or base interface in a type description.
3881 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
3882 UINT index, INT *pImplTypeFlags)
3884 ICOM_THIS( ITypeInfoImpl, iface);
3885 int i;
3886 TLBImplType *pImpl;
3888 TRACE("(%p) index %d\n", This, index);
3889 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
3890 i++, pImpl=pImpl->next)
3892 if(i==index && pImpl){
3893 *pImplTypeFlags=pImpl->implflags;
3894 return S_OK;
3896 *pImplTypeFlags=0;
3897 return TYPE_E_ELEMENTNOTFOUND;
3900 /* GetIDsOfNames
3901 * Maps between member names and member IDs, and parameter names and
3902 * parameter IDs.
3904 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
3905 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
3907 ICOM_THIS( ITypeInfoImpl, iface);
3908 TLBFuncDesc * pFDesc;
3909 TLBVarDesc * pVDesc;
3910 HRESULT ret=S_OK;
3912 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
3913 cNames);
3914 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
3915 int i, j;
3916 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
3917 if(cNames) *pMemId=pFDesc->funcdesc.memid;
3918 for(i=1; i < cNames; i++){
3919 for(j=0; j<pFDesc->funcdesc.cParams; j++)
3920 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
3921 break;
3922 if( j<pFDesc->funcdesc.cParams)
3923 pMemId[i]=j;
3924 else
3925 ret=DISP_E_UNKNOWNNAME;
3927 return ret;
3930 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
3931 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
3932 if(cNames) *pMemId=pVDesc->vardesc.memid;
3933 return ret;
3936 /* not found, see if this is and interface with an inheritance */
3937 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
3938 This->TypeAttr.cImplTypes ){
3939 /* recursive search */
3940 ITypeInfo *pTInfo;
3941 ret=ITypeInfo_GetRefTypeInfo(iface,
3942 This->impltypelist->hRef, &pTInfo);
3943 if(SUCCEEDED(ret)){
3944 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
3945 ITypeInfo_Release(pTInfo);
3946 return ret;
3948 WARN("Could not search inherited interface!\n");
3949 } else
3950 WARN("no names found\n");
3951 return DISP_E_UNKNOWNNAME;
3954 /* ITypeInfo::Invoke
3956 * Invokes a method, or accesses a property of an object, that implements the
3957 * interface described by the type description.
3959 DWORD
3960 _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
3961 DWORD res;
3963 if (TRACE_ON(ole)) {
3964 int i;
3965 MESSAGE("Calling %p(",func);
3966 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
3967 MESSAGE(")\n");
3970 switch (callconv) {
3971 case CC_STDCALL:
3973 switch (nrargs) {
3974 case 0: {
3975 DWORD (WINAPI *xfunc)() = func;
3976 res = xfunc();
3977 break;
3979 case 1: {
3980 DWORD (WINAPI *xfunc)(DWORD) = func;
3981 res = xfunc(args[0]);
3982 break;
3984 case 2: {
3985 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
3986 res = xfunc(args[0],args[1]);
3987 break;
3989 case 3: {
3990 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
3991 res = xfunc(args[0],args[1],args[2]);
3992 break;
3994 case 4: {
3995 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD) = func;
3996 res = xfunc(args[0],args[1],args[2],args[3]);
3997 break;
3999 case 5: {
4000 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4001 res = xfunc(args[0],args[1],args[2],args[3],args[4]);
4002 break;
4004 case 6: {
4005 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4006 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5]);
4007 break;
4009 case 7: {
4010 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4011 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4012 break;
4014 default:
4015 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4016 res = -1;
4017 break;
4019 break;
4020 default:
4021 FIXME("unsupported calling convention %d\n",callconv);
4022 res = -1;
4023 break;
4025 TRACE("returns %08lx\n",res);
4026 return res;
4029 static HRESULT WINAPI ITypeInfo_fnInvoke(
4030 ITypeInfo2 *iface,
4031 VOID *pIUnk,
4032 MEMBERID memid,
4033 UINT16 dwFlags,
4034 DISPPARAMS *pDispParams,
4035 VARIANT *pVarResult,
4036 EXCEPINFO *pExcepInfo,
4037 UINT *pArgErr)
4039 ICOM_THIS( ITypeInfoImpl, iface);
4040 TLBFuncDesc * pFDesc;
4041 TLBVarDesc * pVDesc;
4042 int i;
4044 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4045 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4047 dump_DispParms(pDispParams);
4049 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4050 if (pFDesc->funcdesc.memid == memid) {
4051 if (pFDesc->funcdesc.invkind & dwFlags)
4052 break;
4054 if (pFDesc) {
4055 dump_TLBFuncDescOne(pFDesc);
4056 switch (pFDesc->funcdesc.funckind) {
4057 case FUNC_PUREVIRTUAL:
4058 case FUNC_VIRTUAL: {
4059 DWORD res;
4060 DWORD *args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*(pFDesc->funcdesc.cParams+1));
4061 DWORD *args2 = (DWORD*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*(pFDesc->funcdesc.cParams));
4062 args[0] = (DWORD)pIUnk;
4064 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4065 if (i<pDispParams->cArgs) {
4066 TRACE("set %d to disparg type %d vs %d\n",i,
4067 V_VT(&pDispParams->rgvarg[pDispParams->cArgs-i-1]),
4068 pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt
4070 args[i+1] = V_UNION(&pDispParams->rgvarg[pDispParams->cArgs-i-1],lVal);
4071 } else {
4072 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4073 TRACE("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4074 /*FIXME: give pointers for the rest, so propertyget works*/
4075 args[i+1] = (DWORD)&args2[i];
4077 /* If pointer to variant, pass reference to variant
4078 * in result variant array.
4080 if ((tdesc->vt == VT_PTR) &&
4081 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4082 pVarResult
4084 args[i+1] = (DWORD)(pVarResult+(i-pDispParams->cArgs));
4087 if (pFDesc->funcdesc.cParamsOpt)
4088 FIXME("Does not support optional parameters (%d)\n",
4089 pFDesc->funcdesc.cParamsOpt
4092 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4093 pFDesc->funcdesc.callconv,
4094 pFDesc->funcdesc.cParams+1,
4095 args
4097 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4098 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4099 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4100 /* If we are a pointer to a variant, we are done already */
4101 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4102 continue;
4104 VariantInit(&pVarResult[i]);
4105 V_UNION(pVarResult+i,intVal) = args2[i+pDispParams->cArgs];
4107 if (tdesc->vt == VT_PTR)
4108 tdesc = tdesc->u.lptdesc;
4109 V_VT(pVarResult+i) = tdesc->vt;
4111 /* HACK: VB5 likes this.
4112 * I do not know why. There is 1 example in MSDN which uses
4113 * this which appears broken (mixes int vals and
4114 * IDispatch*.).
4116 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4117 V_VT(pVarResult+i) = VT_DISPATCH;
4118 TRACE("storing into variant: [%d]\n", i);
4119 dump_Variant(pVarResult+i);
4122 HeapFree(GetProcessHeap(),0,args2);
4123 HeapFree(GetProcessHeap(),0,args);
4124 return S_OK;
4126 case FUNC_DISPATCH: {
4127 IDispatch *disp;
4128 HRESULT hr;
4130 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4131 if (hr) {
4132 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4133 return hr;
4135 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4136 hr = IDispatch_Invoke(
4137 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4138 pVarResult,pExcepInfo,pArgErr
4140 if (hr)
4141 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4142 IDispatch_Release(disp);
4143 return hr;
4145 default:
4146 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4147 return E_FAIL;
4149 } else {
4150 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4151 if (pVDesc->vardesc.memid == memid) {
4152 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4153 dump_TLBVarDesc(pVDesc);
4154 break;
4158 /* not found, look for it in inherited interfaces */
4159 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4160 /* recursive search */
4161 ITypeInfo *pTInfo;
4162 HRESULT hr;
4163 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4164 if(SUCCEEDED(hr)){
4165 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4166 ITypeInfo_Release(pTInfo);
4167 return hr;
4169 WARN("Could not search inherited interface!\n");
4171 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4172 return DISP_E_MEMBERNOTFOUND;
4175 /* ITypeInfo::GetDocumentation
4177 * Retrieves the documentation string, the complete Help file name and path,
4178 * and the context ID for the Help topic for a specified type description.
4180 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4181 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4182 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4184 ICOM_THIS( ITypeInfoImpl, iface);
4185 TLBFuncDesc * pFDesc;
4186 TLBVarDesc * pVDesc;
4187 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4188 " HelpContext(%p) HelpFile(%p)\n",
4189 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4190 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4191 if(pBstrName)
4192 *pBstrName=SysAllocString(This->Name);
4193 if(pBstrDocString)
4194 *pBstrDocString=SysAllocString(This->DocString);
4195 if(pdwHelpContext)
4196 *pdwHelpContext=This->dwHelpContext;
4197 if(pBstrHelpFile)
4198 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4199 return S_OK;
4200 }else {/* for a member */
4201 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4202 if(pFDesc->funcdesc.memid==memid){
4203 if(pBstrName)
4204 *pBstrName = SysAllocString(pFDesc->Name);
4205 if(pBstrDocString)
4206 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4207 if(pdwHelpContext)
4208 *pdwHelpContext=pFDesc->helpcontext;
4209 return S_OK;
4211 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4212 if(pVDesc->vardesc.memid==memid){
4213 FIXME("Not implemented\n");
4214 return S_OK;
4217 return TYPE_E_ELEMENTNOTFOUND;
4220 /* ITypeInfo::GetDllEntry
4222 * Retrieves a description or specification of an entry point for a function
4223 * in a DLL.
4225 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4226 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4227 WORD *pwOrdinal)
4229 ICOM_THIS( ITypeInfoImpl, iface);
4230 FIXME("(%p) stub!\n", This);
4231 return E_FAIL;
4234 /* ITypeInfo::GetRefTypeInfo
4236 * If a type description references other type descriptions, it retrieves
4237 * the referenced type descriptions.
4239 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4240 ITypeInfo2 *iface,
4241 HREFTYPE hRefType,
4242 ITypeInfo **ppTInfo)
4244 ICOM_THIS( ITypeInfoImpl, iface);
4245 HRESULT result = E_FAIL;
4248 if (hRefType == -1 &&
4249 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4250 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4252 /* when we meet a DUAL dispinterface, we must create the interface
4253 * version of it.
4255 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4258 /* the interface version contains the same information as the dispinterface
4259 * copy the contents of the structs.
4261 *pTypeInfoImpl = *This;
4262 pTypeInfoImpl->ref = 1;
4264 /* change the type to interface */
4265 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4267 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4269 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4271 result = S_OK;
4273 } else {
4274 TLBRefType *pRefType;
4275 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4276 if(pRefType->reference == hRefType)
4277 break;
4279 if(!pRefType)
4280 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4281 if(pRefType && hRefType != -1) {
4282 ITypeLib *pTLib = NULL;
4284 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4285 int Index;
4286 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4287 } else {
4288 if(pRefType->pImpTLInfo->pImpTypeLib) {
4289 TRACE("typeinfo in imported typelib that is already loaded\n");
4290 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4291 ITypeLib2_AddRef((ITypeLib*) pTLib);
4292 result = S_OK;
4293 } else {
4294 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4295 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4296 pRefType->pImpTLInfo->wVersionMajor,
4297 pRefType->pImpTLInfo->wVersionMinor,
4298 pRefType->pImpTLInfo->lcid,
4299 &pTLib);
4301 if(!SUCCEEDED(result)) {
4302 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4303 result=LoadTypeLib(libnam, &pTLib);
4304 SysFreeString(libnam);
4306 if(SUCCEEDED(result)) {
4307 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4308 ITypeLib2_AddRef(pTLib);
4312 if(SUCCEEDED(result)) {
4313 if(pRefType->index == TLB_REF_USE_GUID)
4314 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4315 &pRefType->guid,
4316 ppTInfo);
4317 else
4318 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4319 ppTInfo);
4321 if (pTLib != NULL)
4322 ITypeLib2_Release(pTLib);
4326 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4327 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4328 return result;
4331 /* ITypeInfo::AddressOfMember
4333 * Retrieves the addresses of static functions or variables, such as those
4334 * defined in a DLL.
4336 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4337 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4339 ICOM_THIS( ITypeInfoImpl, iface);
4340 FIXME("(%p) stub!\n", This);
4341 return S_OK;
4344 /* ITypeInfo::CreateInstance
4346 * Creates a new instance of a type that describes a component object class
4347 * (coclass).
4349 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4350 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4352 ICOM_THIS( ITypeInfoImpl, iface);
4353 FIXME("(%p) stub!\n", This);
4354 return S_OK;
4357 /* ITypeInfo::GetMops
4359 * Retrieves marshaling information.
4361 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4362 BSTR *pBstrMops)
4364 ICOM_THIS( ITypeInfoImpl, iface);
4365 FIXME("(%p) stub!\n", This);
4366 return S_OK;
4369 /* ITypeInfo::GetContainingTypeLib
4371 * Retrieves the containing type library and the index of the type description
4372 * within that type library.
4374 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4375 ITypeLib * *ppTLib, UINT *pIndex)
4377 ICOM_THIS( ITypeInfoImpl, iface);
4378 if (!pIndex)
4379 return E_INVALIDARG;
4380 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4381 *pIndex=This->index;
4382 ITypeLib2_AddRef(*ppTLib);
4383 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4384 return S_OK;
4387 /* ITypeInfo::ReleaseTypeAttr
4389 * Releases a TYPEATTR previously returned by GetTypeAttr.
4392 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4393 TYPEATTR* pTypeAttr)
4395 ICOM_THIS( ITypeInfoImpl, iface);
4396 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4397 return S_OK;
4400 /* ITypeInfo::ReleaseFuncDesc
4402 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4404 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4405 ITypeInfo2 *iface,
4406 FUNCDESC *pFuncDesc)
4408 ICOM_THIS( ITypeInfoImpl, iface);
4409 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4410 return S_OK;
4413 /* ITypeInfo::ReleaseVarDesc
4415 * Releases a VARDESC previously returned by GetVarDesc.
4417 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4418 VARDESC *pVarDesc)
4420 ICOM_THIS( ITypeInfoImpl, iface);
4421 TRACE("(%p)->(%p)\n", This, pVarDesc);
4422 return S_OK;
4425 /* ITypeInfo2::GetTypeKind
4427 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4430 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4431 TYPEKIND *pTypeKind)
4433 ICOM_THIS( ITypeInfoImpl, iface);
4434 *pTypeKind=This->TypeAttr.typekind;
4435 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4436 return S_OK;
4439 /* ITypeInfo2::GetTypeFlags
4441 * Returns the type flags without any allocations. This returns a DWORD type
4442 * flag, which expands the type flags without growing the TYPEATTR (type
4443 * attribute).
4446 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4447 UINT *pTypeFlags)
4449 ICOM_THIS( ITypeInfoImpl, iface);
4450 *pTypeFlags=This->TypeAttr.wTypeFlags;
4451 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4452 return S_OK;
4455 /* ITypeInfo2::GetFuncIndexOfMemId
4456 * Binds to a specific member based on a known DISPID, where the member name
4457 * is not known (for example, when binding to a default member).
4460 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4461 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4463 ICOM_THIS( ITypeInfoImpl, iface);
4464 TLBFuncDesc *pFuncInfo;
4465 int i;
4466 HRESULT result;
4467 /* FIXME: should check for invKind??? */
4468 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4469 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4470 if(pFuncInfo){
4471 *pFuncIndex=i;
4472 result= S_OK;
4473 }else{
4474 *pFuncIndex=0;
4475 result=E_INVALIDARG;
4477 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4478 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4479 return result;
4482 /* TypeInfo2::GetVarIndexOfMemId
4484 * Binds to a specific member based on a known DISPID, where the member name
4485 * is not known (for example, when binding to a default member).
4488 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4489 MEMBERID memid, UINT *pVarIndex)
4491 ICOM_THIS( ITypeInfoImpl, iface);
4492 TLBVarDesc *pVarInfo;
4493 int i;
4494 HRESULT result;
4495 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4496 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4498 if(pVarInfo){
4499 *pVarIndex=i;
4500 result= S_OK;
4501 }else{
4502 *pVarIndex=0;
4503 result=E_INVALIDARG;
4505 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4506 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4507 return result;
4510 /* ITypeInfo2::GetCustData
4512 * Gets the custom data
4514 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4515 ITypeInfo2 * iface,
4516 REFGUID guid,
4517 VARIANT *pVarVal)
4519 ICOM_THIS( ITypeInfoImpl, iface);
4520 TLBCustData *pCData;
4522 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4523 if( IsEqualIID(guid, &pCData->guid)) break;
4525 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4527 if(pCData)
4529 VariantInit( pVarVal);
4530 VariantCopy( pVarVal, &pCData->data);
4531 return S_OK;
4533 return E_INVALIDARG; /* FIXME: correct? */
4536 /* ITypeInfo2::GetFuncCustData
4538 * Gets the custom data
4540 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4541 ITypeInfo2 * iface,
4542 UINT index,
4543 REFGUID guid,
4544 VARIANT *pVarVal)
4546 ICOM_THIS( ITypeInfoImpl, iface);
4547 TLBCustData *pCData=NULL;
4548 TLBFuncDesc * pFDesc;
4549 int i;
4550 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4551 pFDesc=pFDesc->next);
4553 if(pFDesc)
4554 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4555 if( IsEqualIID(guid, &pCData->guid)) break;
4557 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4559 if(pCData){
4560 VariantInit( pVarVal);
4561 VariantCopy( pVarVal, &pCData->data);
4562 return S_OK;
4564 return E_INVALIDARG; /* FIXME: correct? */
4567 /* ITypeInfo2::GetParamCustData
4569 * Gets the custom data
4571 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4572 ITypeInfo2 * iface,
4573 UINT indexFunc,
4574 UINT indexParam,
4575 REFGUID guid,
4576 VARIANT *pVarVal)
4578 ICOM_THIS( ITypeInfoImpl, iface);
4579 TLBCustData *pCData=NULL;
4580 TLBFuncDesc * pFDesc;
4581 int i;
4583 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4585 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4586 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4587 pCData = pCData->next)
4588 if( IsEqualIID(guid, &pCData->guid)) break;
4590 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4592 if(pCData)
4594 VariantInit( pVarVal);
4595 VariantCopy( pVarVal, &pCData->data);
4596 return S_OK;
4598 return E_INVALIDARG; /* FIXME: correct? */
4601 /* ITypeInfo2::GetVarCustData
4603 * Gets the custom data
4605 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4606 ITypeInfo2 * iface,
4607 UINT index,
4608 REFGUID guid,
4609 VARIANT *pVarVal)
4611 ICOM_THIS( ITypeInfoImpl, iface);
4612 TLBCustData *pCData=NULL;
4613 TLBVarDesc * pVDesc;
4614 int i;
4616 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4618 if(pVDesc)
4620 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4622 if( IsEqualIID(guid, &pCData->guid)) break;
4626 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4628 if(pCData)
4630 VariantInit( pVarVal);
4631 VariantCopy( pVarVal, &pCData->data);
4632 return S_OK;
4634 return E_INVALIDARG; /* FIXME: correct? */
4637 /* ITypeInfo2::GetImplCustData
4639 * Gets the custom data
4641 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4642 ITypeInfo2 * iface,
4643 UINT index,
4644 REFGUID guid,
4645 VARIANT *pVarVal)
4647 ICOM_THIS( ITypeInfoImpl, iface);
4648 TLBCustData *pCData=NULL;
4649 TLBImplType * pRDesc;
4650 int i;
4652 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4654 if(pRDesc)
4656 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4658 if( IsEqualIID(guid, &pCData->guid)) break;
4662 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4664 if(pCData)
4666 VariantInit( pVarVal);
4667 VariantCopy( pVarVal, &pCData->data);
4668 return S_OK;
4670 return E_INVALIDARG; /* FIXME: correct? */
4673 /* ITypeInfo2::GetDocumentation2
4675 * Retrieves the documentation string, the complete Help file name and path,
4676 * the localization context to use, and the context ID for the library Help
4677 * topic in the Help file.
4680 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4681 ITypeInfo2 * iface,
4682 MEMBERID memid,
4683 LCID lcid,
4684 BSTR *pbstrHelpString,
4685 DWORD *pdwHelpStringContext,
4686 BSTR *pbstrHelpStringDll)
4688 ICOM_THIS( ITypeInfoImpl, iface);
4689 TLBFuncDesc * pFDesc;
4690 TLBVarDesc * pVDesc;
4691 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4692 "HelpStringContext(%p) HelpStringDll(%p)\n",
4693 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4694 pbstrHelpStringDll );
4695 /* the help string should be obtained from the helpstringdll,
4696 * using the _DLLGetDocumentation function, based on the supplied
4697 * lcid. Nice to do sometime...
4699 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4700 if(pbstrHelpString)
4701 *pbstrHelpString=SysAllocString(This->Name);
4702 if(pdwHelpStringContext)
4703 *pdwHelpStringContext=This->dwHelpStringContext;
4704 if(pbstrHelpStringDll)
4705 *pbstrHelpStringDll=
4706 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4707 return S_OK;
4708 }else {/* for a member */
4709 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4710 if(pFDesc->funcdesc.memid==memid){
4711 if(pbstrHelpString)
4712 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4713 if(pdwHelpStringContext)
4714 *pdwHelpStringContext=pFDesc->HelpStringContext;
4715 if(pbstrHelpStringDll)
4716 *pbstrHelpStringDll=
4717 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4718 return S_OK;
4720 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4721 if(pVDesc->vardesc.memid==memid){
4722 if(pbstrHelpString)
4723 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4724 if(pdwHelpStringContext)
4725 *pdwHelpStringContext=pVDesc->HelpStringContext;
4726 if(pbstrHelpStringDll)
4727 *pbstrHelpStringDll=
4728 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4729 return S_OK;
4732 return TYPE_E_ELEMENTNOTFOUND;
4735 /* ITypeInfo2::GetAllCustData
4737 * Gets all custom data items for the Type info.
4740 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4741 ITypeInfo2 * iface,
4742 CUSTDATA *pCustData)
4744 ICOM_THIS( ITypeInfoImpl, iface);
4745 TLBCustData *pCData;
4746 int i;
4748 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4750 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4751 if(pCustData->prgCustData ){
4752 pCustData->cCustData=This->ctCustData;
4753 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4754 pCustData->prgCustData[i].guid=pCData->guid;
4755 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4757 }else{
4758 ERR(" OUT OF MEMORY! \n");
4759 return E_OUTOFMEMORY;
4761 return S_OK;
4764 /* ITypeInfo2::GetAllFuncCustData
4766 * Gets all custom data items for the specified Function
4769 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4770 ITypeInfo2 * iface,
4771 UINT index,
4772 CUSTDATA *pCustData)
4774 ICOM_THIS( ITypeInfoImpl, iface);
4775 TLBCustData *pCData;
4776 TLBFuncDesc * pFDesc;
4777 int i;
4778 TRACE("(%p) index %d\n", This, index);
4779 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4780 pFDesc=pFDesc->next)
4782 if(pFDesc){
4783 pCustData->prgCustData =
4784 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4785 if(pCustData->prgCustData ){
4786 pCustData->cCustData=pFDesc->ctCustData;
4787 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4788 pCData = pCData->next){
4789 pCustData->prgCustData[i].guid=pCData->guid;
4790 VariantCopy(& pCustData->prgCustData[i].varValue,
4791 & pCData->data);
4793 }else{
4794 ERR(" OUT OF MEMORY! \n");
4795 return E_OUTOFMEMORY;
4797 return S_OK;
4799 return TYPE_E_ELEMENTNOTFOUND;
4802 /* ITypeInfo2::GetAllParamCustData
4804 * Gets all custom data items for the Functions
4807 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4808 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4810 ICOM_THIS( ITypeInfoImpl, iface);
4811 TLBCustData *pCData=NULL;
4812 TLBFuncDesc * pFDesc;
4813 int i;
4814 TRACE("(%p) index %d\n", This, indexFunc);
4815 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4816 pFDesc=pFDesc->next)
4818 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4819 pCustData->prgCustData =
4820 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4821 sizeof(CUSTDATAITEM));
4822 if(pCustData->prgCustData ){
4823 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
4824 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
4825 pCData; i++, pCData = pCData->next){
4826 pCustData->prgCustData[i].guid=pCData->guid;
4827 VariantCopy(& pCustData->prgCustData[i].varValue,
4828 & pCData->data);
4830 }else{
4831 ERR(" OUT OF MEMORY! \n");
4832 return E_OUTOFMEMORY;
4834 return S_OK;
4836 return TYPE_E_ELEMENTNOTFOUND;
4839 /* ITypeInfo2::GetAllVarCustData
4841 * Gets all custom data items for the specified Variable
4844 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
4845 UINT index, CUSTDATA *pCustData)
4847 ICOM_THIS( ITypeInfoImpl, iface);
4848 TLBCustData *pCData;
4849 TLBVarDesc * pVDesc;
4850 int i;
4851 TRACE("(%p) index %d\n", This, index);
4852 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
4853 pVDesc=pVDesc->next)
4855 if(pVDesc){
4856 pCustData->prgCustData =
4857 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
4858 if(pCustData->prgCustData ){
4859 pCustData->cCustData=pVDesc->ctCustData;
4860 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
4861 pCData = pCData->next){
4862 pCustData->prgCustData[i].guid=pCData->guid;
4863 VariantCopy(& pCustData->prgCustData[i].varValue,
4864 & pCData->data);
4866 }else{
4867 ERR(" OUT OF MEMORY! \n");
4868 return E_OUTOFMEMORY;
4870 return S_OK;
4872 return TYPE_E_ELEMENTNOTFOUND;
4875 /* ITypeInfo2::GetAllImplCustData
4877 * Gets all custom data items for the specified implementation type
4880 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
4881 ITypeInfo2 * iface,
4882 UINT index,
4883 CUSTDATA *pCustData)
4885 ICOM_THIS( ITypeInfoImpl, iface);
4886 TLBCustData *pCData;
4887 TLBImplType * pRDesc;
4888 int i;
4889 TRACE("(%p) index %d\n", This, index);
4890 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
4891 pRDesc=pRDesc->next)
4893 if(pRDesc){
4894 pCustData->prgCustData =
4895 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
4896 if(pCustData->prgCustData ){
4897 pCustData->cCustData=pRDesc->ctCustData;
4898 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
4899 pCData = pCData->next){
4900 pCustData->prgCustData[i].guid=pCData->guid;
4901 VariantCopy(& pCustData->prgCustData[i].varValue,
4902 & pCData->data);
4904 }else{
4905 ERR(" OUT OF MEMORY! \n");
4906 return E_OUTOFMEMORY;
4908 return S_OK;
4910 return TYPE_E_ELEMENTNOTFOUND;
4913 static ICOM_VTABLE(ITypeInfo2) tinfvt =
4915 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4917 ITypeInfo_fnQueryInterface,
4918 ITypeInfo_fnAddRef,
4919 ITypeInfo_fnRelease,
4921 ITypeInfo_fnGetTypeAttr,
4922 ITypeInfo_fnGetTypeComp,
4923 ITypeInfo_fnGetFuncDesc,
4924 ITypeInfo_fnGetVarDesc,
4925 ITypeInfo_fnGetNames,
4926 ITypeInfo_fnGetRefTypeOfImplType,
4927 ITypeInfo_fnGetImplTypeFlags,
4928 ITypeInfo_fnGetIDsOfNames,
4929 ITypeInfo_fnInvoke,
4930 ITypeInfo_fnGetDocumentation,
4931 ITypeInfo_fnGetDllEntry,
4932 ITypeInfo_fnGetRefTypeInfo,
4933 ITypeInfo_fnAddressOfMember,
4934 ITypeInfo_fnCreateInstance,
4935 ITypeInfo_fnGetMops,
4936 ITypeInfo_fnGetContainingTypeLib,
4937 ITypeInfo_fnReleaseTypeAttr,
4938 ITypeInfo_fnReleaseFuncDesc,
4939 ITypeInfo_fnReleaseVarDesc,
4941 ITypeInfo2_fnGetTypeKind,
4942 ITypeInfo2_fnGetTypeFlags,
4943 ITypeInfo2_fnGetFuncIndexOfMemId,
4944 ITypeInfo2_fnGetVarIndexOfMemId,
4945 ITypeInfo2_fnGetCustData,
4946 ITypeInfo2_fnGetFuncCustData,
4947 ITypeInfo2_fnGetParamCustData,
4948 ITypeInfo2_fnGetVarCustData,
4949 ITypeInfo2_fnGetImplTypeCustData,
4950 ITypeInfo2_fnGetDocumentation2,
4951 ITypeInfo2_fnGetAllCustData,
4952 ITypeInfo2_fnGetAllFuncCustData,
4953 ITypeInfo2_fnGetAllParamCustData,
4954 ITypeInfo2_fnGetAllVarCustData,
4955 ITypeInfo2_fnGetAllImplTypeCustData,