Porting fixes.
[wine/wine64.git] / dlls / oleaut32 / typelib.c
blob029b8f8d369427bcf37265451a9ffcbeaca106db
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
47 * behaviour.
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
55 #include "config.h"
56 #include "wine/port.h"
58 #include <stdlib.h>
59 #include <string.h>
60 #include <stdio.h>
61 #include <ctype.h>
63 #include "winerror.h"
64 #include "winnls.h" /* for PRIMARYLANGID */
65 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
66 #include "winuser.h"
68 #include "wine/unicode.h"
69 #include "wine/obj_base.h"
70 #include "heap.h"
71 #include "ole2disp.h"
72 #include "typelib.h"
73 #include "wine/debug.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78 /****************************************************************************
79 * QueryPathOfRegTypeLib [TYPELIB.14]
81 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
82 * RETURNS
83 * path of typelib
85 HRESULT WINAPI
86 QueryPathOfRegTypeLib16(
87 REFGUID guid, /* [in] referenced guid */
88 WORD wMaj, /* [in] major version */
89 WORD wMin, /* [in] minor version */
90 LCID lcid, /* [in] locale id */
91 LPBSTR16 path /* [out] path of typelib */
92 ) {
93 char xguid[80];
94 char typelibkey[100],pathname[260];
95 DWORD plen;
97 TRACE("\n");
99 if (HIWORD(guid)) {
100 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
101 guid->Data1, guid->Data2, guid->Data3,
102 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
103 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
104 wMaj,wMin,lcid);
105 } else {
106 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
107 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
108 return E_FAIL;
110 plen = sizeof(pathname);
111 if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
112 /* try again without lang specific id */
113 if (SUBLANGID(lcid))
114 return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
115 FIXME("key %s not found\n",typelibkey);
116 return E_FAIL;
118 *path = SysAllocString16(pathname);
119 return S_OK;
122 /****************************************************************************
123 * QueryPathOfRegTypeLib [OLEAUT32.164]
124 * RETURNS
125 * path of typelib
127 HRESULT WINAPI
128 QueryPathOfRegTypeLib(
129 REFGUID guid, /* [in] referenced guid */
130 WORD wMaj, /* [in] major version */
131 WORD wMin, /* [in] minor version */
132 LCID lcid, /* [in] locale id */
133 LPBSTR path ) /* [out] path of typelib */
135 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
136 string termination character on output strings */
138 HRESULT hr = E_FAIL;
140 LCID myLCID = lcid;
142 char szXGUID[80];
143 char szTypeLibKey[100];
144 char szPath[MAX_PATH];
145 DWORD dwPathLen = sizeof(szPath);
147 if ( !HIWORD(guid) )
149 sprintf(szXGUID,
150 "<guid 0x%08lx>",
151 (DWORD) guid);
153 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
154 return E_FAIL;
157 while (hr != S_OK)
159 sprintf(szTypeLibKey,
160 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
161 guid->Data1, guid->Data2, guid->Data3,
162 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
163 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
164 wMaj,
165 wMin,
166 myLCID);
168 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
170 if (!lcid)
171 break;
172 else if (myLCID == lcid)
174 /* try with sub-langid */
175 myLCID = SUBLANGID(lcid);
177 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
179 /* try with system langid */
180 myLCID = 0;
182 else
184 break;
187 else
189 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
190 BSTR bstrPath = SysAllocStringLen(NULL,len);
192 MultiByteToWideChar(CP_ACP,
193 MB_PRECOMPOSED,
194 szPath,
195 dwPathLen,
196 bstrPath,
197 len);
198 *path = bstrPath;
199 hr = S_OK;
203 if (hr != S_OK)
204 TRACE_(typelib)("%s not found\n", szTypeLibKey);
206 return hr;
209 /******************************************************************************
210 * CreateTypeLib [OLEAUT32.160] creates a typelib
212 * RETURNS
213 * Success: S_OK
214 * Failure: Status
216 HRESULT WINAPI CreateTypeLib(
217 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
219 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
220 return E_FAIL;
222 /******************************************************************************
223 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
224 * NOTES
225 * Docs: OLECHAR FAR* szFile
226 * Docs: iTypeLib FAR* FAR* pptLib
228 * RETURNS
229 * Success: S_OK
230 * Failure: Status
232 HRESULT WINAPI LoadTypeLib16(
233 LPOLESTR szFile, /* [in] Name of file to load from */
234 ITypeLib** pptLib) /* [out] Pointer to pointer to loaded type library */
236 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
238 if (pptLib!=0)
239 *pptLib=0;
241 return E_FAIL;
244 /******************************************************************************
245 * LoadTypeLib [OLEAUT32.161]
246 * Loads and registers a type library
247 * NOTES
248 * Docs: OLECHAR FAR* szFile
249 * Docs: iTypeLib FAR* FAR* pptLib
251 * RETURNS
252 * Success: S_OK
253 * Failure: Status
255 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
257 HRESULT WINAPI LoadTypeLib(
258 const OLECHAR *szFile,/* [in] Name of file to load from */
259 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
261 TRACE("\n");
262 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
265 /******************************************************************************
266 * LoadTypeLibEx [OLEAUT32.183]
267 * Loads and optionally registers a type library
269 * RETURNS
270 * Success: S_OK
271 * Failure: Status
273 HRESULT WINAPI LoadTypeLibEx(
274 LPCOLESTR szFile, /* [in] Name of file to load from */
275 REGKIND regkind, /* [in] Specify kind of registration */
276 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
278 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
279 WCHAR *pIndexStr;
280 HRESULT res;
281 INT index = 1;
282 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
284 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
285 NULL)) {
287 /* Look for a trailing '\\' followed by an index */
288 pIndexStr = strrchrW(szFile, '\\');
289 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
290 index = atoiW(pIndexStr);
291 memcpy(szFileCopy, szFile,
292 (pIndexStr - szFile - 1) * sizeof(WCHAR));
293 szFileCopy[pIndexStr - szFile - 1] = '\0';
294 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
295 szPath,NULL))
296 return TYPE_E_CANTLOADLIBRARY;
297 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
298 return TYPE_E_CANTLOADLIBRARY;
299 } else
300 return TYPE_E_CANTLOADLIBRARY;
303 TRACE("File %s index %d\n", debugstr_w(szPath), index);
305 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
307 if (SUCCEEDED(res))
308 switch(regkind)
310 case REGKIND_DEFAULT:
311 /* FIXME: is this correct? */
312 if (!szFile || !szFile[0] ||
313 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
314 break;
315 /* else fall-through */
316 case REGKIND_REGISTER:
317 /* FIXME: Help path? */
318 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
320 IUnknown_Release(*pptLib);
321 *pptLib = 0;
323 break;
324 case REGKIND_NONE:
325 break;
328 TRACE(" returns %08lx\n",res);
329 return res;
332 /******************************************************************************
333 * LoadRegTypeLib [OLEAUT32.162]
335 HRESULT WINAPI LoadRegTypeLib(
336 REFGUID rguid, /* [in] referenced guid */
337 WORD wVerMajor, /* [in] major version */
338 WORD wVerMinor, /* [in] minor version */
339 LCID lcid, /* [in] locale id */
340 ITypeLib **ppTLib) /* [out] path of typelib */
342 BSTR bstr=NULL;
343 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
345 if(SUCCEEDED(res))
347 res= LoadTypeLib(bstr, ppTLib);
348 SysFreeString(bstr);
351 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
353 return res;
357 /******************************************************************************
358 * RegisterTypeLib [OLEAUT32.163]
359 * Adds information about a type library to the System Registry
360 * NOTES
361 * Docs: ITypeLib FAR * ptlib
362 * Docs: OLECHAR FAR* szFullPath
363 * Docs: OLECHAR FAR* szHelpDir
365 * RETURNS
366 * Success: S_OK
367 * Failure: Status
369 HRESULT WINAPI RegisterTypeLib(
370 ITypeLib * ptlib, /* [in] Pointer to the library*/
371 OLECHAR * szFullPath, /* [in] full Path of the library*/
372 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
373 may be NULL*/
375 HRESULT res;
376 TLIBATTR *attr;
377 OLECHAR guid[80];
378 LPSTR guidA;
379 CHAR keyName[120];
380 HKEY key, subKey;
381 UINT types, tidx;
382 TYPEKIND kind;
383 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
385 if (ptlib == NULL || szFullPath == NULL)
386 return E_INVALIDARG;
388 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
389 return E_FAIL;
391 StringFromGUID2(&attr->guid, guid, 80);
392 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
393 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
394 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
395 HeapFree(GetProcessHeap(), 0, guidA);
397 res = S_OK;
398 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
399 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
401 LPOLESTR doc;
403 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
405 if (RegSetValueExW(key, NULL, 0, REG_SZ,
406 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
407 res = E_FAIL;
409 SysFreeString(doc);
411 else
412 res = E_FAIL;
414 /* FIXME: This *seems* to be 0 always, not sure though */
415 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
416 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
418 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
419 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
420 res = E_FAIL;
422 RegCloseKey(subKey);
424 else
425 res = E_FAIL;
427 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
428 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
430 CHAR buf[20];
431 /* FIXME: is %u correct? */
432 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
433 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
434 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
435 res = E_FAIL;
437 RegCloseKey(key);
439 else
440 res = E_FAIL;
442 /* register OLE Automation-compatible interfaces for this typelib */
443 types = ITypeLib_GetTypeInfoCount(ptlib);
444 for (tidx=0; tidx<types; tidx++) {
445 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
446 LPOLESTR name = NULL;
447 ITypeInfo *tinfo = NULL;
448 BOOL stop = FALSE;
449 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
450 switch (kind) {
451 case TKIND_INTERFACE:
452 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
453 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
454 break;
455 case TKIND_DISPATCH:
456 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
457 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
458 break;
459 case TKIND_COCLASS:
460 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
461 /* coclasses should probably not be registered? */
462 break;
463 default:
464 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
465 break;
467 if (tinfo) {
468 TYPEATTR *tattr = NULL;
469 ITypeInfo_GetTypeAttr(tinfo, &tattr);
470 if (tattr) {
471 TRACE_(typelib)("guid=%s, flags=%04x (",
472 debugstr_guid(&tattr->guid),
473 tattr->wTypeFlags);
474 if (TRACE_ON(typelib)) {
475 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
476 XX(FAPPOBJECT);
477 XX(FCANCREATE);
478 XX(FLICENSED);
479 XX(FPREDECLID);
480 XX(FHIDDEN);
481 XX(FCONTROL);
482 XX(FDUAL);
483 XX(FNONEXTENSIBLE);
484 XX(FOLEAUTOMATION);
485 XX(FRESTRICTED);
486 XX(FAGGREGATABLE);
487 XX(FREPLACEABLE);
488 XX(FDISPATCHABLE);
489 XX(FREVERSEBIND);
490 XX(FPROXY);
491 #undef XX
492 MESSAGE("\n");
495 * FIXME: The 1 is just here until we implement rpcrt4
496 * stub/proxy handling. Until then it helps IShield
497 * v6 to work.
499 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
501 /* register interface<->typelib coupling */
502 StringFromGUID2(&tattr->guid, guid, 80);
503 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
504 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
505 HeapFree(GetProcessHeap(), 0, guidA);
507 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
508 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
509 if (name)
510 RegSetValueExW(key, NULL, 0, REG_SZ,
511 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
513 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
514 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
515 RegSetValueExA(subKey, NULL, 0, REG_SZ,
516 PSOA, strlen(PSOA));
517 RegCloseKey(subKey);
519 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
520 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
521 RegSetValueExA(subKey, NULL, 0, REG_SZ,
522 PSOA, strlen(PSOA));
523 RegCloseKey(subKey);
526 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
527 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
528 CHAR ver[32];
529 StringFromGUID2(&attr->guid, guid, 80);
530 snprintf(ver, sizeof(ver), "%x.%x",
531 attr->wMajorVerNum, attr->wMinorVerNum);
532 RegSetValueExW(subKey, NULL, 0, REG_SZ,
533 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
534 RegSetValueExA(subKey, "Version", 0, REG_SZ,
535 ver, lstrlenA(ver));
536 RegCloseKey(subKey);
538 RegCloseKey(key);
541 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
543 ITypeInfo_Release(tinfo);
545 SysFreeString(name);
546 if (stop) break;
550 ITypeLib_ReleaseTLibAttr(ptlib, attr);
552 return res;
556 /******************************************************************************
557 * UnRegisterTypeLib [OLEAUT32.186]
558 * Removes information about a type library from the System Registry
559 * NOTES
561 * RETURNS
562 * Success: S_OK
563 * Failure: Status
565 HRESULT WINAPI UnRegisterTypeLib(
566 REFGUID libid, /* [in] Guid of the library */
567 WORD wVerMajor, /* [in] major version */
568 WORD wVerMinor, /* [in] minor version */
569 LCID lcid, /* [in] locale id */
570 SYSKIND syskind)
572 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
573 return S_OK; /* FIXME: pretend everything is OK */
576 /****************************************************************************
577 * OaBuildVersion (TYPELIB.15)
579 * known TYPELIB.DLL versions:
581 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
582 * OLE 2.02 1993-94 02 3002
583 * OLE 2.03 23 730
584 * OLE 2.03 03 3025
585 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
586 * OLE 2.1 NT 1993-95 ?? ???
587 * OLE 2.3.1 W95 23 700
588 * OLE2 4.0 NT4SP6 1993-98 40 4277
590 DWORD WINAPI OaBuildVersion16(void)
592 /* FIXME: I'd like to return the highest currently known version value
593 * in case the user didn't force a --winver, but I don't know how
594 * to retrieve the "versionForced" info from misc/version.c :(
595 * (this would be useful in other places, too) */
596 FIXME("If you get version error messages, please report them\n");
597 switch(GetVersion() & 0x8000ffff) /* mask off build number */
599 case 0x80000a03: /* WIN31 */
600 return MAKELONG(3027, 3); /* WfW 3.11 */
601 case 0x80000004: /* WIN95 */
602 return MAKELONG(700, 23); /* Win95A */
603 case 0x80000a04: /* WIN98 */
604 return MAKELONG(3024, 10); /* W98 SE */
605 case 0x00000004: /* NT4 */
606 return MAKELONG(4277, 40); /* NT4 SP6 */
607 default:
608 FIXME("Version value not known yet. Please investigate it!\n");
609 return 0;
613 /* for better debugging info leave the static out for the time being */
614 #define static
616 /*======================= ITypeLib implementation =======================*/
618 typedef struct tagTLBCustData
620 GUID guid;
621 VARIANT data;
622 struct tagTLBCustData* next;
623 } TLBCustData;
625 /* data structure for import typelibs */
626 typedef struct tagTLBImpLib
628 int offset; /* offset in the file (MSFT)
629 offset in nametable (SLTG)
630 just used to identify library while reading
631 data from file */
632 GUID guid; /* libid */
633 BSTR name; /* name */
635 LCID lcid; /* lcid of imported typelib */
637 WORD wVersionMajor; /* major version number */
638 WORD wVersionMinor; /* minor version number */
640 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
641 NULL if not yet loaded */
642 struct tagTLBImpLib * next;
643 } TLBImpLib;
645 /* internal ITypeLib data */
646 typedef struct tagITypeLibImpl
648 ICOM_VFIELD(ITypeLib2);
649 UINT ref;
650 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
652 /* strings can be stored in tlb as multibyte strings BUT they are *always*
653 * exported to the application as a UNICODE string.
655 BSTR Name;
656 BSTR DocString;
657 BSTR HelpFile;
658 BSTR HelpStringDll;
659 unsigned long dwHelpContext;
660 int TypeInfoCount; /* nr of typeinfo's in librarry */
661 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
662 int ctCustData; /* number of items in cust data list */
663 TLBCustData * pCustData; /* linked list to cust data */
664 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
665 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
666 libary. Only used while read MSFT
667 typelibs */
668 } ITypeLibImpl;
670 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
672 /* ITypeLib methods */
673 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
674 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
676 /*======================= ITypeInfo implementation =======================*/
678 /* data for refernced types */
679 typedef struct tagTLBRefType
681 INT index; /* Type index for internal ref or for external ref
682 it the format is SLTG. -2 indicates to
683 use guid */
685 GUID guid; /* guid of the referenced type */
686 /* if index == TLB_REF_USE_GUID */
688 HREFTYPE reference; /* The href of this ref */
689 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
690 TLB_REF_INTERNAL for internal refs
691 TLB_REF_NOT_FOUND for broken refs */
693 struct tagTLBRefType * next;
694 } TLBRefType;
696 #define TLB_REF_USE_GUID -2
698 #define TLB_REF_INTERNAL (void*)-2
699 #define TLB_REF_NOT_FOUND (void*)-1
701 /* internal Parameter data */
702 typedef struct tagTLBParDesc
704 BSTR Name;
705 int ctCustData;
706 TLBCustData * pCustData; /* linked list to cust data */
707 } TLBParDesc;
709 /* internal Function data */
710 typedef struct tagTLBFuncDesc
712 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
713 BSTR Name; /* the name of this function */
714 TLBParDesc *pParamDesc; /* array with param names and custom data */
715 int helpcontext;
716 int HelpStringContext;
717 BSTR HelpString;
718 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
719 int ctCustData;
720 TLBCustData * pCustData; /* linked list to cust data; */
721 struct tagTLBFuncDesc * next;
722 } TLBFuncDesc;
724 /* internal Variable data */
725 typedef struct tagTLBVarDesc
727 VARDESC vardesc; /* lots of info on the variable and its attributes. */
728 BSTR Name; /* the name of this variable */
729 int HelpContext;
730 int HelpStringContext; /* FIXME: where? */
731 BSTR HelpString;
732 int ctCustData;
733 TLBCustData * pCustData;/* linked list to cust data; */
734 struct tagTLBVarDesc * next;
735 } TLBVarDesc;
737 /* internal implemented interface data */
738 typedef struct tagTLBImplType
740 HREFTYPE hRef; /* hRef of interface */
741 int implflags; /* IMPLFLAG_*s */
742 int ctCustData;
743 TLBCustData * pCustData;/* linked list to custom data; */
744 struct tagTLBImplType *next;
745 } TLBImplType;
747 /* internal TypeInfo data */
748 typedef struct tagITypeInfoImpl
750 ICOM_VFIELD(ITypeInfo2);
751 UINT ref;
752 TYPEATTR TypeAttr ; /* _lots_ of type information. */
753 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
754 int index; /* index in this typelib; */
755 /* type libs seem to store the doc strings in ascii
756 * so why should we do it in unicode?
758 BSTR Name;
759 BSTR DocString;
760 unsigned long dwHelpContext;
761 unsigned long dwHelpStringContext;
763 /* functions */
764 TLBFuncDesc * funclist; /* linked list with function descriptions */
766 /* variables */
767 TLBVarDesc * varlist; /* linked list with variable descriptions */
769 /* Implemented Interfaces */
770 TLBImplType * impltypelist;
772 TLBRefType * reflist;
773 int ctCustData;
774 TLBCustData * pCustData; /* linked list to cust data; */
775 struct tagITypeInfoImpl * next;
776 } ITypeInfoImpl;
778 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
780 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
782 typedef struct tagTLBContext
784 unsigned int oStart; /* start of TLB in file */
785 unsigned int pos; /* current pos */
786 unsigned int length; /* total length */
787 void *mapping; /* memory mapping */
788 MSFT_SegDir * pTblDir;
789 ITypeLibImpl* pLibInfo;
790 } TLBContext;
793 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
796 debug
798 static void dump_VarType(VARTYPE vt,char *szVarType) {
799 /* FIXME : we could have better trace here, depending on the VARTYPE
800 * of the variant
802 if (vt & VT_RESERVED)
803 szVarType += strlen(strcpy(szVarType, "reserved | "));
804 if (vt & VT_BYREF)
805 szVarType += strlen(strcpy(szVarType, "ref to "));
806 if (vt & VT_ARRAY)
807 szVarType += strlen(strcpy(szVarType, "array of "));
808 if (vt & VT_VECTOR)
809 szVarType += strlen(strcpy(szVarType, "vector of "));
810 switch(vt & VT_TYPEMASK) {
811 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
812 case VT_I2: sprintf(szVarType, "VT_I2"); break;
813 case VT_I4: sprintf(szVarType, "VT_I4"); break;
814 case VT_R4: sprintf(szVarType, "VT_R4"); break;
815 case VT_R8: sprintf(szVarType, "VT_R8"); break;
816 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
817 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
818 case VT_CY: sprintf(szVarType, "VT_CY"); break;
819 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
820 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
821 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
822 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
823 case VT_I1: sprintf(szVarType, "VT_I1"); break;
824 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
825 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
826 case VT_INT: sprintf(szVarType, "VT_INT"); break;
827 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
828 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
829 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
830 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
831 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
835 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
836 if (pTD->vt & VT_RESERVED)
837 szVarType += strlen(strcpy(szVarType, "reserved | "));
838 if (pTD->vt & VT_BYREF)
839 szVarType += strlen(strcpy(szVarType, "ref to "));
840 if (pTD->vt & VT_ARRAY)
841 szVarType += strlen(strcpy(szVarType, "array of "));
842 if (pTD->vt & VT_VECTOR)
843 szVarType += strlen(strcpy(szVarType, "vector of "));
844 switch(pTD->vt & VT_TYPEMASK) {
845 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
846 case VT_I2: sprintf(szVarType, "VT_I2"); break;
847 case VT_I4: sprintf(szVarType, "VT_I4"); break;
848 case VT_R4: sprintf(szVarType, "VT_R4"); break;
849 case VT_R8: sprintf(szVarType, "VT_R8"); break;
850 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
851 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
852 case VT_CY: sprintf(szVarType, "VT_CY"); break;
853 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
854 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
855 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
856 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
857 case VT_I1: sprintf(szVarType, "VT_I1"); break;
858 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
859 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
860 case VT_INT: sprintf(szVarType, "VT_INT"); break;
861 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
862 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
863 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
864 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
865 pTD->u.hreftype); break;
866 case VT_PTR: sprintf(szVarType, "ptr to ");
867 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
868 break;
869 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
870 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
871 break;
872 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
873 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
874 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
875 break;
877 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
881 static void dump_ELEMDESC(ELEMDESC *edesc) {
882 char buf[200];
883 dump_TypeDesc(&edesc->tdesc,buf);
884 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
885 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
886 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
888 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
889 int i;
890 MESSAGE("memid is %08lx\n",funcdesc->memid);
891 for (i=0;i<funcdesc->cParams;i++) {
892 MESSAGE("Param %d:\n",i);
893 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
895 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
896 switch (funcdesc->funckind) {
897 case FUNC_VIRTUAL: MESSAGE("virtual");break;
898 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
899 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
900 case FUNC_STATIC: MESSAGE("static");break;
901 case FUNC_DISPATCH: MESSAGE("dispatch");break;
902 default: MESSAGE("unknown");break;
904 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
905 switch (funcdesc->invkind) {
906 case INVOKE_FUNC: MESSAGE("func");break;
907 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
908 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
909 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
911 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
912 switch (funcdesc->callconv) {
913 case CC_CDECL: MESSAGE("cdecl");break;
914 case CC_PASCAL: MESSAGE("pascal");break;
915 case CC_STDCALL: MESSAGE("stdcall");break;
916 case CC_SYSCALL: MESSAGE("syscall");break;
917 default:break;
919 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
920 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
921 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
923 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
925 int i;
926 if (!TRACE_ON(typelib))
927 return;
928 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
929 for (i=0;i<pfd->funcdesc.cParams;i++)
930 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
933 dump_FUNCDESC(&(pfd->funcdesc));
935 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
936 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
938 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
940 while (pfd)
942 dump_TLBFuncDescOne(pfd);
943 pfd = pfd->next;
946 static void dump_TLBVarDesc(TLBVarDesc * pvd)
948 while (pvd)
950 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
951 pvd = pvd->next;
955 static void dump_TLBImpLib(TLBImpLib *import)
957 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
958 debugstr_w(import->name));
959 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
960 import->wVersionMinor, import->lcid, import->offset);
963 static void dump_TLBRefType(TLBRefType * prt)
965 while (prt)
967 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
968 if(prt->index == -1)
969 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
970 else
971 TRACE_(typelib)("type no: %d\n", prt->index);
973 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
974 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
975 TRACE_(typelib)("in lib\n");
976 dump_TLBImpLib(prt->pImpTLInfo);
978 prt = prt->next;
982 static void dump_TLBImplType(TLBImplType * impl)
984 while (impl) {
985 TRACE_(typelib)(
986 "implementing/inheriting interface hRef = %lx implflags %x\n",
987 impl->hRef, impl->implflags);
988 impl = impl->next;
992 static void dump_Variant(VARIANT * pvar)
994 char szVarType[32];
995 LPVOID ref;
997 TRACE("(%p)\n", pvar);
999 if (!pvar) return;
1001 ZeroMemory(szVarType, sizeof(szVarType));
1003 /* FIXME : we could have better trace here, depending on the VARTYPE
1004 * of the variant
1006 dump_VarType(V_VT(pvar),szVarType);
1008 TRACE("VARTYPE: %s\n", szVarType);
1010 if (V_VT(pvar) & VT_BYREF) {
1011 ref = V_UNION(pvar, byref);
1012 TRACE("%p\n", ref);
1014 else ref = &V_UNION(pvar, cVal);
1016 if (V_VT(pvar) & VT_ARRAY) {
1017 /* FIXME */
1018 return;
1020 if (V_VT(pvar) & VT_VECTOR) {
1021 /* FIXME */
1022 return;
1025 switch (V_VT(pvar))
1027 case VT_I2:
1028 TRACE("%d\n", *(short*)ref);
1029 break;
1031 case VT_I4:
1032 TRACE("%d\n", *(INT*)ref);
1033 break;
1035 case VT_R4:
1036 TRACE("%3.3e\n", *(float*)ref);
1037 break;
1039 case VT_R8:
1040 TRACE("%3.3e\n", *(double*)ref);
1041 break;
1043 case VT_BOOL:
1044 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1045 break;
1047 case VT_BSTR:
1048 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1049 break;
1051 case VT_UNKNOWN:
1052 case VT_DISPATCH:
1053 TRACE("%p\n", *(LPVOID*)ref);
1054 break;
1056 case VT_VARIANT:
1057 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1058 break;
1060 default:
1061 TRACE("(?)%ld\n", *(long*)ref);
1062 break;
1066 static void dump_DispParms(DISPPARAMS * pdp)
1068 int index = 0;
1070 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1072 while (index < pdp->cArgs)
1074 dump_Variant( &pdp->rgvarg[index] );
1075 ++index;
1079 static char * typekind_desc[] =
1081 "TKIND_ENUM",
1082 "TKIND_RECORD",
1083 "TKIND_MODULE",
1084 "TKIND_INTERFACE",
1085 "TKIND_DISPATCH",
1086 "TKIND_COCLASS",
1087 "TKIND_ALIAS",
1088 "TKIND_UNION",
1089 "TKIND_MAX"
1092 static void dump_TypeInfo(ITypeInfoImpl * pty)
1094 TRACE("%p ref=%u\n", pty, pty->ref);
1095 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1096 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1097 TRACE("fct:%u var:%u impl:%u\n",
1098 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1099 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1100 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1101 dump_TLBFuncDesc(pty->funclist);
1102 dump_TLBVarDesc(pty->varlist);
1103 dump_TLBImplType(pty->impltypelist);
1106 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1108 /* VT_LPWSTR is largest type that */
1109 /* may appear in type description*/
1110 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1111 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1112 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1113 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1114 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1115 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1116 {{0},30},{{0},31}
1119 static void TLB_abort()
1121 DebugBreak();
1123 static void * TLB_Alloc(unsigned size)
1125 void * ret;
1126 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1127 /* FIXME */
1128 ERR("cannot allocate memory\n");
1130 return ret;
1133 static void TLB_Free(void * ptr)
1135 HeapFree(GetProcessHeap(), 0, ptr);
1139 /**********************************************************************
1141 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1143 /* read function */
1144 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1146 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1147 pcx->pos, count, pcx->oStart, pcx->length, where);
1149 if (where != DO_NOT_SEEK)
1151 where += pcx->oStart;
1152 if (where > pcx->length)
1154 /* FIXME */
1155 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1156 TLB_abort();
1158 pcx->pos = where;
1160 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1161 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1162 pcx->pos += count;
1163 return count;
1166 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1168 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1170 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1171 memset(pGuid,0, sizeof(GUID));
1172 return;
1174 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1177 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1179 char * name;
1180 MSFT_NameIntro niName;
1181 int lengthInChars;
1182 WCHAR* pwstring = NULL;
1183 BSTR bstrName = NULL;
1185 MSFT_Read(&niName, sizeof(niName), pcx,
1186 pcx->pTblDir->pNametab.offset+offset);
1187 niName.namelen &= 0xFF; /* FIXME: correct ? */
1188 name=TLB_Alloc((niName.namelen & 0xff) +1);
1189 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1190 name[niName.namelen & 0xff]='\0';
1192 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1193 name, -1, NULL, 0);
1195 /* no invalid characters in string */
1196 if (lengthInChars)
1198 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1200 /* don't check for invalid character since this has been done previously */
1201 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1203 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1204 lengthInChars = SysStringLen(bstrName);
1205 HeapFree(GetProcessHeap(), 0, pwstring);
1208 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1209 return bstrName;
1212 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1214 char * string;
1215 INT16 length;
1216 int lengthInChars;
1217 BSTR bstr = NULL;
1219 if(offset<0) return NULL;
1220 MSFT_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1221 if(length <= 0) return 0;
1222 string=TLB_Alloc(length +1);
1223 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1224 string[length]='\0';
1226 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1227 string, -1, NULL, 0);
1229 /* no invalid characters in string */
1230 if (lengthInChars)
1232 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1234 /* don't check for invalid character since this has been done previously */
1235 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1237 bstr = SysAllocStringLen(pwstring, lengthInChars);
1238 lengthInChars = SysStringLen(bstr);
1239 HeapFree(GetProcessHeap(), 0, pwstring);
1242 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1243 return bstr;
1246 * read a value and fill a VARIANT structure
1248 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1250 int size;
1252 TRACE_(typelib)("\n");
1254 if(offset <0) { /* data are packed in here */
1255 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1256 V_UNION(pVar, iVal) = offset & 0xffff;
1257 return;
1259 MSFT_Read(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1260 pcx->pTblDir->pCustData.offset + offset );
1261 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1262 switch (V_VT(pVar)){
1263 case VT_EMPTY: /* FIXME: is this right? */
1264 case VT_NULL: /* FIXME: is this right? */
1265 case VT_I2 : /* this should not happen */
1266 case VT_I4 :
1267 case VT_R4 :
1268 case VT_ERROR :
1269 case VT_BOOL :
1270 case VT_I1 :
1271 case VT_UI1 :
1272 case VT_UI2 :
1273 case VT_UI4 :
1274 case VT_INT :
1275 case VT_UINT :
1276 case VT_VOID : /* FIXME: is this right? */
1277 case VT_HRESULT :
1278 size=4; break;
1279 case VT_R8 :
1280 case VT_CY :
1281 case VT_DATE :
1282 case VT_I8 :
1283 case VT_UI8 :
1284 case VT_DECIMAL : /* FIXME: is this right? */
1285 case VT_FILETIME :
1286 size=8;break;
1287 /* pointer types with known behaviour */
1288 case VT_BSTR :{
1289 char * ptr;
1290 MSFT_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1291 if(size <= 0) {
1292 FIXME("BSTR length = %d?\n", size);
1293 } else {
1294 ptr=TLB_Alloc(size);/* allocate temp buffer */
1295 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1296 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1297 /* FIXME: do we need a AtoW conversion here? */
1298 V_UNION(pVar, bstrVal[size])=L'\0';
1299 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1300 TLB_Free(ptr);
1303 size=-4; break;
1304 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1305 case VT_DISPATCH :
1306 case VT_VARIANT :
1307 case VT_UNKNOWN :
1308 case VT_PTR :
1309 case VT_SAFEARRAY :
1310 case VT_CARRAY :
1311 case VT_USERDEFINED :
1312 case VT_LPSTR :
1313 case VT_LPWSTR :
1314 case VT_BLOB :
1315 case VT_STREAM :
1316 case VT_STORAGE :
1317 case VT_STREAMED_OBJECT :
1318 case VT_STORED_OBJECT :
1319 case VT_BLOB_OBJECT :
1320 case VT_CF :
1321 case VT_CLSID :
1322 default:
1323 size=0;
1324 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1325 V_VT(pVar));
1328 if(size>0) /* (big|small) endian correct? */
1329 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1330 return;
1333 * create a linked list with custom data
1335 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1337 MSFT_CDGuid entry;
1338 TLBCustData* pNew;
1339 int count=0;
1341 TRACE_(typelib)("\n");
1343 while(offset >=0){
1344 count++;
1345 pNew=TLB_Alloc(sizeof(TLBCustData));
1346 MSFT_Read(&entry, sizeof(entry), pcx,
1347 pcx->pTblDir->pCDGuids.offset+offset);
1348 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1349 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1350 /* add new custom data at head of the list */
1351 pNew->next=*ppCustData;
1352 *ppCustData=pNew;
1353 offset = entry.next;
1355 return count;
1358 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1359 ITypeInfoImpl *pTI)
1361 if(type <0)
1362 pTd->vt=type & VT_TYPEMASK;
1363 else
1364 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1366 if(pTd->vt == VT_USERDEFINED)
1367 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1369 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1372 static void
1373 MSFT_DoFuncs(TLBContext* pcx,
1374 ITypeInfoImpl* pTI,
1375 int cFuncs,
1376 int cVars,
1377 int offset,
1378 TLBFuncDesc** pptfd)
1381 * member information is stored in a data structure at offset
1382 * indicated by the memoffset field of the typeinfo structure
1383 * There are several distinctive parts.
1384 * the first part starts with a field that holds the total length
1385 * of this (first) part excluding this field. Then follow the records,
1386 * for each member there is one record.
1388 * First entry is always the length of the record (excluding this
1389 * length word).
1390 * Rest of the record depends on the type of the member. If there is
1391 * a field indicating the member type (function variable intereface etc)
1392 * I have not found it yet. At this time we depend on the information
1393 * in the type info and the usual order how things are stored.
1395 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1396 * for each member;
1398 * Third is a equal sized array with file offsets to the name entry
1399 * of each member.
1401 * Forth and last (?) part is an array with offsets to the records in the
1402 * first part of this file segment.
1405 int infolen, nameoffset, reclength, nrattributes, i;
1406 int recoffset = offset + sizeof(INT);
1408 char recbuf[512];
1409 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1411 TRACE_(typelib)("\n");
1413 MSFT_Read(&infolen, sizeof(INT), pcx, offset);
1415 for ( i = 0; i < cFuncs ; i++ )
1417 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1419 /* name, eventually add to a hash table */
1420 MSFT_Read(&nameoffset,
1421 sizeof(INT),
1422 pcx,
1423 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1425 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1427 /* read the function information record */
1428 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1430 reclength &= 0x1ff;
1432 MSFT_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1434 /* do the attributes */
1435 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1436 / sizeof(int);
1438 if ( nrattributes > 0 )
1440 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1442 if ( nrattributes > 1 )
1444 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1445 pFuncRec->OptAttr[1]) ;
1447 if ( nrattributes > 2 )
1449 if ( pFuncRec->FKCCIC & 0x2000 )
1451 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1453 else
1455 (*pptfd)->Entry = MSFT_ReadString(pcx,
1456 pFuncRec->OptAttr[2]);
1458 if( nrattributes > 5 )
1460 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1462 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1464 MSFT_CustData(pcx,
1465 pFuncRec->OptAttr[6],
1466 &(*pptfd)->pCustData);
1473 /* fill the FuncDesc Structure */
1474 MSFT_Read( & (*pptfd)->funcdesc.memid,
1475 sizeof(INT), pcx,
1476 offset + infolen + ( i + 1) * sizeof(INT));
1478 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1479 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1480 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1481 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1482 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1483 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1484 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1486 MSFT_GetTdesc(pcx,
1487 pFuncRec->DataType,
1488 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1489 pTI);
1491 /* do the parameters/arguments */
1492 if(pFuncRec->nrargs)
1494 int j = 0;
1495 MSFT_ParameterInfo paraminfo;
1497 (*pptfd)->funcdesc.lprgelemdescParam =
1498 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1500 (*pptfd)->pParamDesc =
1501 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1503 MSFT_Read(&paraminfo,
1504 sizeof(paraminfo),
1505 pcx,
1506 recoffset + reclength -
1507 pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1509 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1511 TYPEDESC* lpArgTypeDesc = 0;
1513 MSFT_GetTdesc(pcx,
1514 paraminfo.DataType,
1515 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1516 pTI);
1518 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1520 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1522 /* SEEK value = jump to offset,
1523 * from there jump to the end of record,
1524 * go back by (j-1) arguments
1526 MSFT_Read( &paraminfo ,
1527 sizeof(MSFT_ParameterInfo), pcx,
1528 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1529 * sizeof(MSFT_ParameterInfo)));
1530 lpArgTypeDesc =
1531 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1533 while ( lpArgTypeDesc != NULL )
1535 switch ( lpArgTypeDesc->vt )
1537 case VT_PTR:
1538 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1539 break;
1541 case VT_CARRAY:
1542 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1543 break;
1545 case VT_USERDEFINED:
1546 MSFT_DoRefType(pcx, pTI,
1547 lpArgTypeDesc->u.hreftype);
1549 lpArgTypeDesc = NULL;
1550 break;
1552 default:
1553 lpArgTypeDesc = NULL;
1559 /* parameter is the return value! */
1560 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1562 TYPEDESC* lpArgTypeDesc;
1564 (*pptfd)->funcdesc.elemdescFunc =
1565 (*pptfd)->funcdesc.lprgelemdescParam[j];
1567 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1569 while ( lpArgTypeDesc != NULL )
1571 switch ( lpArgTypeDesc->vt )
1573 case VT_PTR:
1574 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1575 break;
1576 case VT_CARRAY:
1577 lpArgTypeDesc =
1578 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1580 break;
1582 case VT_USERDEFINED:
1583 MSFT_DoRefType(pcx,
1584 pTI,
1585 lpArgTypeDesc->u.hreftype);
1587 lpArgTypeDesc = NULL;
1588 break;
1590 default:
1591 lpArgTypeDesc = NULL;
1596 /* second time around */
1597 for(j=0;j<pFuncRec->nrargs;j++)
1599 /* name */
1600 (*pptfd)->pParamDesc[j].Name =
1601 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1603 /* default value */
1604 if ( (PARAMFLAG_FHASDEFAULT &
1605 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1606 ((pFuncRec->FKCCIC) & 0x1000) )
1608 INT* pInt = (INT *)((char *)pFuncRec +
1609 reclength -
1610 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1612 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1614 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1615 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1617 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1618 pInt[j], pcx);
1620 /* custom info */
1621 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1623 MSFT_CustData(pcx,
1624 pFuncRec->OptAttr[7+j],
1625 &(*pptfd)->pParamDesc[j].pCustData);
1630 /* scode is not used: archaic win16 stuff FIXME: right? */
1631 (*pptfd)->funcdesc.cScodes = 0 ;
1632 (*pptfd)->funcdesc.lprgscode = NULL ;
1634 pptfd = & ((*pptfd)->next);
1635 recoffset += reclength;
1638 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1639 int cVars, int offset, TLBVarDesc ** pptvd)
1641 int infolen, nameoffset, reclength;
1642 char recbuf[256];
1643 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1644 int i;
1645 int recoffset;
1647 TRACE_(typelib)("\n");
1649 MSFT_Read(&infolen,sizeof(INT), pcx, offset);
1650 MSFT_Read(&recoffset,sizeof(INT), pcx, offset + infolen +
1651 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1652 recoffset += offset+sizeof(INT);
1653 for(i=0;i<cVars;i++){
1654 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1655 /* name, eventually add to a hash table */
1656 MSFT_Read(&nameoffset, sizeof(INT), pcx,
1657 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1658 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1659 /* read the variable information record */
1660 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1661 reclength &=0xff;
1662 MSFT_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1663 /* Optional data */
1664 if(reclength >(6*sizeof(INT)) )
1665 (*pptvd)->HelpContext=pVarRec->HelpContext;
1666 if(reclength >(7*sizeof(INT)) )
1667 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1668 if(reclength >(8*sizeof(INT)) )
1669 if(reclength >(9*sizeof(INT)) )
1670 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1671 /* fill the VarDesc Structure */
1672 MSFT_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1673 offset + infolen + ( i + 1) * sizeof(INT));
1674 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1675 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1676 MSFT_GetTdesc(pcx, pVarRec->DataType,
1677 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1678 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1679 if(pVarRec->VarKind == VAR_CONST ){
1680 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1681 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1682 pVarRec->OffsValue, pcx);
1683 } else
1684 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1685 pptvd=&((*pptvd)->next);
1686 recoffset += reclength;
1689 /* fill in data for a hreftype (offset). When the refernced type is contained
1690 * in the typelib, it's just an (file) offset in the type info base dir.
1691 * If comes from import, it's an offset+1 in the ImpInfo table
1692 * */
1693 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1694 int offset)
1696 int j;
1697 TLBRefType **ppRefType = &pTI->reflist;
1699 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1701 while(*ppRefType) {
1702 if((*ppRefType)->reference == offset)
1703 return;
1704 ppRefType = &(*ppRefType)->next;
1707 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1708 sizeof(**ppRefType));
1710 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1711 /* external typelib */
1712 MSFT_ImpInfo impinfo;
1713 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1715 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1717 MSFT_Read(&impinfo, sizeof(impinfo), pcx,
1718 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1719 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1720 if(pImpLib->offset==impinfo.oImpFile) break;
1721 pImpLib=pImpLib->next;
1723 if(pImpLib){
1724 (*ppRefType)->reference=offset;
1725 (*ppRefType)->pImpTLInfo = pImpLib;
1726 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1727 (*ppRefType)->index = TLB_REF_USE_GUID;
1728 }else{
1729 ERR("Cannot find a reference\n");
1730 (*ppRefType)->reference=-1;
1731 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1733 }else{
1734 /* in this typelib */
1735 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1736 (*ppRefType)->reference=offset;
1737 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1741 /* process Implemented Interfaces of a com class */
1742 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1743 int offset)
1745 int i;
1746 MSFT_RefRecord refrec;
1747 TLBImplType **ppImpl = &pTI->impltypelist;
1749 TRACE_(typelib)("\n");
1751 for(i=0;i<count;i++){
1752 if(offset<0) break; /* paranoia */
1753 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1754 MSFT_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1755 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1756 (*ppImpl)->hRef = refrec.reftype;
1757 (*ppImpl)->implflags=refrec.flags;
1758 (*ppImpl)->ctCustData=
1759 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1760 offset=refrec.onext;
1761 ppImpl=&((*ppImpl)->next);
1765 * process a typeinfo record
1767 ITypeInfoImpl * MSFT_DoTypeInfo(
1768 TLBContext *pcx,
1769 int count,
1770 ITypeLibImpl * pLibInfo)
1772 MSFT_TypeInfoBase tiBase;
1773 ITypeInfoImpl *ptiRet;
1775 TRACE_(typelib)("count=%u\n", count);
1777 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1778 MSFT_Read(&tiBase, sizeof(tiBase) ,pcx ,
1779 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1780 /* this is where we are coming from */
1781 ptiRet->pTypeLib = pLibInfo;
1782 ITypeLib2_AddRef((ITypeLib2 *)pLibInfo);
1783 ptiRet->index=count;
1784 /* fill in the typeattr fields */
1785 FIXME("Assign constructor/destructor memid\n");
1787 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1788 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1789 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1790 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1791 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1792 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1793 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1794 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1795 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1796 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1797 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1798 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1799 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1800 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1801 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1802 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1803 MSFT_GetTdesc(pcx, tiBase.datatype1,
1804 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1806 /* FIXME: */
1807 /* IDLDESC idldescType; *//* never saw this one != zero */
1809 /* name, eventually add to a hash table */
1810 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1811 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1812 /* help info */
1813 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1814 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1815 ptiRet->dwHelpContext=tiBase.helpcontext;
1816 /* note: InfoType's Help file and HelpStringDll come from the containing
1817 * library. Further HelpString and Docstring appear to be the same thing :(
1819 /* functions */
1820 if(ptiRet->TypeAttr.cFuncs >0 )
1821 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1822 ptiRet->TypeAttr.cVars,
1823 tiBase.memoffset, & ptiRet->funclist);
1824 /* variables */
1825 if(ptiRet->TypeAttr.cVars >0 )
1826 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1827 ptiRet->TypeAttr.cVars,
1828 tiBase.memoffset, & ptiRet->varlist);
1829 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1830 switch(ptiRet->TypeAttr.typekind)
1832 case TKIND_COCLASS:
1833 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1834 tiBase.datatype1);
1835 break;
1836 case TKIND_DISPATCH:
1837 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1839 if (tiBase.datatype1 != -1)
1841 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1842 ptiRet->impltypelist->hRef = tiBase.datatype1;
1844 else
1845 { /* FIXME: This is a really bad hack to add IDispatch */
1846 char* szStdOle = "stdole2.tlb\0";
1847 int nStdOleLen = strlen(szStdOle);
1848 TLBRefType **ppRef = &ptiRet->reflist;
1850 while(*ppRef) {
1851 if((*ppRef)->reference == -1)
1852 break;
1853 ppRef = &(*ppRef)->next;
1855 if(!*ppRef) {
1856 *ppRef = TLB_Alloc(sizeof(**ppRef));
1857 (*ppRef)->guid = IID_IDispatch;
1858 (*ppRef)->reference = -1;
1859 (*ppRef)->index = TLB_REF_USE_GUID;
1860 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1861 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1862 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1863 nStdOleLen + 1);
1865 MultiByteToWideChar(CP_ACP,
1866 MB_PRECOMPOSED,
1867 szStdOle,
1869 (*ppRef)->pImpTLInfo->name,
1870 SysStringLen((*ppRef)->pImpTLInfo->name));
1872 (*ppRef)->pImpTLInfo->lcid = 0;
1873 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1874 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1877 break;
1878 default:
1879 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1880 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1881 ptiRet->impltypelist->hRef = tiBase.datatype1;
1882 break;
1885 ptiRet->ctCustData=
1886 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1888 TRACE_(typelib)("%s guid: %s kind:%s\n",
1889 debugstr_w(ptiRet->Name),
1890 debugstr_guid(&ptiRet->TypeAttr.guid),
1891 typekind_desc[ptiRet->TypeAttr.typekind]);
1893 return ptiRet;
1896 /****************************************************************************
1897 * TLB_ReadTypeLib
1899 * find the type of the typelib file and map the typelib resource into
1900 * the memory
1902 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1903 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1904 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1906 int ret = TYPE_E_CANTLOADLIBRARY;
1907 DWORD dwSignature = 0;
1908 HFILE hFile;
1910 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1912 *ppTypeLib = NULL;
1914 /* check the signature of the file */
1915 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1916 if (INVALID_HANDLE_VALUE != hFile)
1918 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1919 if (hMapping)
1921 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1922 if(pBase)
1924 /* retrieve file size */
1925 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1927 /* first try to load as *.tlb */
1928 dwSignature = *((DWORD*) pBase);
1929 if ( dwSignature == MSFT_SIGNATURE)
1931 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1933 else if ( dwSignature == SLTG_SIGNATURE)
1935 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1937 UnmapViewOfFile(pBase);
1939 CloseHandle(hMapping);
1941 CloseHandle(hFile);
1944 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1946 /* find the typelibrary resource*/
1947 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
1948 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1949 if (hinstDLL)
1951 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
1952 "TYPELIB");
1953 if (hrsrc)
1955 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1956 if (hGlobal)
1958 LPVOID pBase = LockResource(hGlobal);
1959 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1961 if (pBase)
1963 /* try to load as incore resource */
1964 dwSignature = *((DWORD*) pBase);
1965 if ( dwSignature == MSFT_SIGNATURE)
1967 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1969 else if ( dwSignature == SLTG_SIGNATURE)
1971 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1973 else
1975 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
1978 FreeResource( hGlobal );
1981 FreeLibrary(hinstDLL);
1985 if(*ppTypeLib)
1986 ret = S_OK;
1987 else
1988 ERR("Loading of typelib %s failed with error %ld\n",
1989 debugstr_w(pszFileName), GetLastError());
1991 return ret;
1994 /*================== ITypeLib(2) Methods ===================================*/
1996 /****************************************************************************
1997 * ITypeLib2_Constructor_MSFT
1999 * loading an MSFT typelib from an in-memory image
2001 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2003 TLBContext cx;
2004 long lPSegDir;
2005 MSFT_Header tlbHeader;
2006 MSFT_SegDir tlbSegDir;
2007 ITypeLibImpl * pTypeLibImpl;
2009 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2011 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2012 if (!pTypeLibImpl) return NULL;
2014 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2015 pTypeLibImpl->ref = 1;
2017 /* get pointer to beginning of typelib data */
2018 cx.pos = 0;
2019 cx.oStart=0;
2020 cx.mapping = pLib;
2021 cx.pLibInfo = pTypeLibImpl;
2022 cx.length = dwTLBLength;
2024 /* read header */
2025 MSFT_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2026 TRACE("header:\n");
2027 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2028 if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
2029 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2030 return NULL;
2032 /* there is a small amount of information here until the next important
2033 * part:
2034 * the segment directory . Try to calculate the amount of data */
2035 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2037 /* now read the segment directory */
2038 TRACE("read segment directory (at %ld)\n",lPSegDir);
2039 MSFT_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2040 cx.pTblDir = &tlbSegDir;
2042 /* just check two entries */
2043 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2045 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2046 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2047 return NULL;
2050 /* now fill our internal data */
2051 /* TLIBATTR fields */
2052 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2054 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2055 /* Windows seems to have zero here, is this correct? */
2056 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2057 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2058 else
2059 pTypeLibImpl->LibAttr.lcid = 0;
2061 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2062 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2063 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2064 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2066 /* name, eventually add to a hash table */
2067 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2069 /* help info */
2070 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2071 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2073 if( tlbHeader.varflags & HELPDLLFLAG)
2075 int offset;
2076 MSFT_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2077 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2080 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2082 /* custom data */
2083 if(tlbHeader.CustomDataOffset >= 0)
2085 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2088 /* fill in typedescriptions */
2089 if(tlbSegDir.pTypdescTab.length > 0)
2091 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2092 INT16 td[4];
2093 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2094 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2095 for(i=0; i<cTD; )
2097 /* FIXME: add several sanity checks here */
2098 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2099 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2101 /* FIXME: check safearray */
2102 if(td[3] < 0)
2103 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2104 else
2105 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2107 else if(td[0] == VT_CARRAY)
2109 /* array descr table here */
2110 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2112 else if(td[0] == VT_USERDEFINED)
2114 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2116 if(++i<cTD) MSFT_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
2119 /* second time around to fill the array subscript info */
2120 for(i=0;i<cTD;i++)
2122 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2123 if(tlbSegDir.pArrayDescriptions.offset>0)
2125 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2126 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2128 if(td[1]<0)
2129 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2130 else
2131 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2133 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2135 for(j = 0; j<td[2]; j++)
2137 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2138 sizeof(INT), &cx, DO_NOT_SEEK);
2139 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2140 sizeof(INT), &cx, DO_NOT_SEEK);
2143 else
2145 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2146 ERR("didn't find array description data\n");
2151 /* imported type libs */
2152 if(tlbSegDir.pImpFiles.offset>0)
2154 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2155 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2156 UINT16 size;
2158 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2160 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2161 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2162 MSFT_Read(&oGuid, sizeof(INT), &cx, offset);
2164 MSFT_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2165 MSFT_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2166 MSFT_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2167 MSFT_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2169 size >>= 2;
2170 (*ppImpLib)->name = TLB_Alloc(size+1);
2171 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2172 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2173 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2175 ppImpLib = &(*ppImpLib)->next;
2179 /* type info's */
2180 if(tlbHeader.nrtypeinfos >= 0 )
2182 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2183 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2184 int i;
2186 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2188 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2190 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2191 ppTI = &((*ppTI)->next);
2192 (pTypeLibImpl->TypeInfoCount)++;
2196 TRACE("(%p)\n", pTypeLibImpl);
2197 return (ITypeLib2*) pTypeLibImpl;
2201 static BSTR TLB_MultiByteToBSTR(char *ptr)
2203 DWORD len;
2204 WCHAR *nameW;
2205 BSTR ret;
2207 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2208 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2209 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2210 ret = SysAllocString(nameW);
2211 HeapFree(GetProcessHeap(), 0, nameW);
2212 return ret;
2215 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2217 char b[3];
2218 int i;
2219 short s;
2221 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2222 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2223 return FALSE;
2226 guid->Data4[0] = s >> 8;
2227 guid->Data4[1] = s & 0xff;
2229 b[2] = '\0';
2230 for(i = 0; i < 6; i++) {
2231 memcpy(b, str + 24 + 2 * i, 2);
2232 guid->Data4[i + 2] = strtol(b, NULL, 16);
2234 return TRUE;
2237 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2239 WORD bytelen;
2240 DWORD len;
2241 WCHAR *nameW;
2243 *pBstr = NULL;
2244 bytelen = *(WORD*)ptr;
2245 if(bytelen == 0xffff) return 2;
2246 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2247 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2248 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2249 *pBstr = SysAllocStringLen(nameW, len);
2250 HeapFree(GetProcessHeap(), 0, nameW);
2251 return bytelen + 2;
2254 static WORD SLTG_ReadStringA(char *ptr, char **str)
2256 WORD bytelen;
2258 *str = NULL;
2259 bytelen = *(WORD*)ptr;
2260 if(bytelen == 0xffff) return 2;
2261 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2262 memcpy(*str, ptr + 2, bytelen);
2263 (*str)[bytelen] = '\0';
2264 return bytelen + 2;
2267 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2269 char *ptr = pLibBlk;
2270 WORD w;
2272 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2273 FIXME("libblk magic = %04x\n", w);
2274 return 0;
2277 ptr += 6;
2278 if((w = *(WORD*)ptr) != 0xffff) {
2279 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2280 ptr += w;
2282 ptr += 2;
2284 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2286 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2288 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2289 ptr += 4;
2291 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2292 ptr += 2;
2294 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2295 ptr += 2;
2297 ptr += 4; /* skip res12 */
2299 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2300 ptr += 2;
2302 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2303 ptr += 2;
2305 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2306 ptr += 2;
2308 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2309 ptr += sizeof(GUID);
2311 return ptr - (char*)pLibBlk;
2314 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2316 BOOL done = FALSE;
2317 TYPEDESC *pTD = &pElem->tdesc;
2319 /* Handle [in/out] first */
2320 if((*pType & 0xc000) == 0xc000)
2321 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2322 else if(*pType & 0x8000)
2323 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2324 else if(*pType & 0x4000)
2325 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2326 else
2327 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2329 if(*pType & 0x2000)
2330 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2332 if(*pType & 0x80)
2333 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2335 while(!done) {
2336 if((*pType & 0xe00) == 0xe00) {
2337 pTD->vt = VT_PTR;
2338 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2339 sizeof(TYPEDESC));
2340 pTD = pTD->u.lptdesc;
2342 switch(*pType & 0x7f) {
2343 case VT_PTR:
2344 pTD->vt = VT_PTR;
2345 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2346 sizeof(TYPEDESC));
2347 pTD = pTD->u.lptdesc;
2348 break;
2350 case VT_USERDEFINED:
2351 pTD->vt = VT_USERDEFINED;
2352 pTD->u.hreftype = *(++pType) / 4;
2353 done = TRUE;
2354 break;
2356 case VT_CARRAY:
2358 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2359 array */
2361 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2363 pTD->vt = VT_CARRAY;
2364 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2365 sizeof(ARRAYDESC) +
2366 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2367 pTD->u.lpadesc->cDims = pSA->cDims;
2368 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2369 pSA->cDims * sizeof(SAFEARRAYBOUND));
2371 pTD = &pTD->u.lpadesc->tdescElem;
2372 break;
2375 case VT_SAFEARRAY:
2377 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2378 useful? */
2380 pType++;
2381 pTD->vt = VT_SAFEARRAY;
2382 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2383 sizeof(TYPEDESC));
2384 pTD = pTD->u.lptdesc;
2385 break;
2387 default:
2388 pTD->vt = *pType & 0x7f;
2389 done = TRUE;
2390 break;
2392 pType++;
2394 return pType;
2398 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2399 char *pNameTable)
2401 int ref;
2402 char *name;
2403 TLBRefType **ppRefType;
2405 if(pRef->magic != SLTG_REF_MAGIC) {
2406 FIXME("Ref magic = %x\n", pRef->magic);
2407 return;
2409 name = ( (char*)(&pRef->names) + pRef->number);
2411 ppRefType = &pTI->reflist;
2412 for(ref = 0; ref < pRef->number >> 3; ref++) {
2413 char *refname;
2414 unsigned int lib_offs, type_num;
2416 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2417 sizeof(**ppRefType));
2419 name += SLTG_ReadStringA(name, &refname);
2420 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2421 FIXME("Can't sscanf ref\n");
2422 if(lib_offs != 0xffff) {
2423 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2425 while(*import) {
2426 if((*import)->offset == lib_offs)
2427 break;
2428 import = &(*import)->next;
2430 if(!*import) {
2431 char fname[MAX_PATH+1];
2432 int len;
2434 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2435 sizeof(**import));
2436 (*import)->offset = lib_offs;
2437 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2438 &(*import)->guid);
2439 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2440 &(*import)->wVersionMajor,
2441 &(*import)->wVersionMinor,
2442 &(*import)->lcid, fname) != 4) {
2443 FIXME("can't sscanf ref %s\n",
2444 pNameTable + lib_offs + 40);
2446 len = strlen(fname);
2447 if(fname[len-1] != '#')
2448 FIXME("fname = %s\n", fname);
2449 fname[len-1] = '\0';
2450 (*import)->name = TLB_MultiByteToBSTR(fname);
2452 (*ppRefType)->pImpTLInfo = *import;
2453 } else { /* internal ref */
2454 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2456 (*ppRefType)->reference = ref;
2457 (*ppRefType)->index = type_num;
2459 HeapFree(GetProcessHeap(), 0, refname);
2460 ppRefType = &(*ppRefType)->next;
2462 if((BYTE)*name != SLTG_REF_MAGIC)
2463 FIXME("End of ref block magic = %x\n", *name);
2464 dump_TLBRefType(pTI->reflist);
2467 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2468 BOOL OneOnly)
2470 SLTG_ImplInfo *info;
2471 TLBImplType **ppImplType = &pTI->impltypelist;
2472 /* I don't really get this structure, usually it's 0x16 bytes
2473 long, but iuser.tlb contains some that are 0x18 bytes long.
2474 That's ok because we can use the next ptr to jump to the next
2475 one. But how do we know the length of the last one? The WORD
2476 at offs 0x8 might be the clue. For now I'm just assuming that
2477 the last one is the regular 0x16 bytes. */
2479 info = (SLTG_ImplInfo*)pBlk;
2480 while(1) {
2481 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2482 sizeof(**ppImplType));
2483 (*ppImplType)->hRef = info->ref;
2484 (*ppImplType)->implflags = info->impltypeflags;
2485 pTI->TypeAttr.cImplTypes++;
2486 ppImplType = &(*ppImplType)->next;
2488 if(info->next == 0xffff)
2489 break;
2490 if(OneOnly)
2491 FIXME("Interface inheriting more than one interface\n");
2492 info = (SLTG_ImplInfo*)(pBlk + info->next);
2494 info++; /* see comment at top of function */
2495 return (char*)info;
2498 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2499 char *pNameTable)
2501 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2502 SLTG_MemberHeader *pMemHeader;
2503 char *pFirstItem, *pNextItem;
2505 if(pTIHeader->href_table != 0xffffffff) {
2506 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2507 pNameTable);
2511 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2513 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2515 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2516 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2519 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2523 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2524 char *pNameTable)
2526 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2527 SLTG_MemberHeader *pMemHeader;
2528 SLTG_Function *pFunc;
2529 char *pFirstItem, *pNextItem;
2530 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2531 int num = 0;
2533 if(pTIHeader->href_table != 0xffffffff) {
2534 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2535 pNameTable);
2538 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2540 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2542 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2543 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2546 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2547 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2549 int param;
2550 WORD *pType, *pArg;
2552 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2553 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2554 FIXME("func magic = %02x\n", pFunc->magic);
2555 return NULL;
2557 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2558 sizeof(**ppFuncDesc));
2559 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2561 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2562 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2563 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2564 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2565 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2566 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2568 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2569 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2571 if(pFunc->retnextopt & 0x80)
2572 pType = &pFunc->rettype;
2573 else
2574 pType = (WORD*)(pFirstItem + pFunc->rettype);
2577 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2579 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2580 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2581 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2582 (*ppFuncDesc)->pParamDesc =
2583 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2584 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2586 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2588 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2589 char *paramName = pNameTable + *pArg;
2590 BOOL HaveOffs;
2591 /* If arg type follows then paramName points to the 2nd
2592 letter of the name, else the next WORD is an offset to
2593 the arg type and paramName points to the first letter.
2594 So let's take one char off paramName and see if we're
2595 pointing at an alpha-numeric char. However if *pArg is
2596 0xffff or 0xfffe then the param has no name, the former
2597 meaning that the next WORD is the type, the latter
2598 meaning the the next WORD is an offset to the type. */
2600 HaveOffs = FALSE;
2601 if(*pArg == 0xffff)
2602 paramName = NULL;
2603 else if(*pArg == 0xfffe) {
2604 paramName = NULL;
2605 HaveOffs = TRUE;
2607 else if(!isalnum(*(paramName-1)))
2608 HaveOffs = TRUE;
2610 pArg++;
2612 if(HaveOffs) { /* the next word is an offset to type */
2613 pType = (WORD*)(pFirstItem + *pArg);
2614 SLTG_DoType(pType, pFirstItem,
2615 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2616 pArg++;
2617 } else {
2618 if(paramName)
2619 paramName--;
2620 pArg = SLTG_DoType(pArg, pFirstItem,
2621 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2624 /* Are we an optional param ? */
2625 if((*ppFuncDesc)->funcdesc.cParams - param <=
2626 (*ppFuncDesc)->funcdesc.cParamsOpt)
2627 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2629 if(paramName) {
2630 (*ppFuncDesc)->pParamDesc[param].Name =
2631 TLB_MultiByteToBSTR(paramName);
2635 ppFuncDesc = &((*ppFuncDesc)->next);
2636 if(pFunc->next == 0xffff) break;
2638 pTI->TypeAttr.cFuncs = num;
2639 dump_TLBFuncDesc(pTI->funclist);
2640 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2643 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2644 char *pNameTable)
2646 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2647 SLTG_MemberHeader *pMemHeader;
2648 SLTG_RecordItem *pItem;
2649 char *pFirstItem;
2650 TLBVarDesc **ppVarDesc = &pTI->varlist;
2651 int num = 0;
2652 WORD *pType;
2653 char buf[300];
2655 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2657 pFirstItem = (char*)(pMemHeader + 1);
2658 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2659 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2660 if(pItem->magic != SLTG_RECORD_MAGIC) {
2661 FIXME("record magic = %02x\n", pItem->magic);
2662 return NULL;
2664 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2665 sizeof(**ppVarDesc));
2666 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2667 (*ppVarDesc)->vardesc.memid = pItem->memid;
2668 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2669 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2671 if(pItem->typepos == 0x02)
2672 pType = &pItem->type;
2673 else if(pItem->typepos == 0x00)
2674 pType = (WORD*)(pFirstItem + pItem->type);
2675 else {
2676 FIXME("typepos = %02x\n", pItem->typepos);
2677 break;
2680 SLTG_DoType(pType, pFirstItem,
2681 &(*ppVarDesc)->vardesc.elemdescVar);
2683 /* FIXME("helpcontext, helpstring\n"); */
2685 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2687 ppVarDesc = &((*ppVarDesc)->next);
2688 if(pItem->next == 0xffff) break;
2690 pTI->TypeAttr.cVars = num;
2691 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2694 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2695 char *pNameTable)
2697 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2698 SLTG_MemberHeader *pMemHeader;
2699 SLTG_EnumItem *pItem;
2700 char *pFirstItem;
2701 TLBVarDesc **ppVarDesc = &pTI->varlist;
2702 int num = 0;
2704 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2706 pFirstItem = (char*)(pMemHeader + 1);
2707 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2708 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2709 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2710 FIXME("enumitem magic = %04x\n", pItem->magic);
2711 return NULL;
2713 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2714 sizeof(**ppVarDesc));
2715 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2716 (*ppVarDesc)->vardesc.memid = pItem->memid;
2717 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2718 sizeof(VARIANT));
2719 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2720 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2721 *(INT*)(pItem->value + pFirstItem);
2722 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2723 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2724 /* FIXME("helpcontext, helpstring\n"); */
2726 ppVarDesc = &((*ppVarDesc)->next);
2727 if(pItem->next == 0xffff) break;
2729 pTI->TypeAttr.cVars = num;
2730 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2733 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2734 managable copy of it into this */
2735 typedef struct {
2736 WORD small_no;
2737 char *index_name;
2738 char *other_name;
2739 WORD res1a;
2740 WORD name_offs;
2741 WORD more_bytes;
2742 char *extra;
2743 WORD res20;
2744 DWORD helpcontext;
2745 WORD res26;
2746 GUID uuid;
2747 } SLTG_InternalOtherTypeInfo;
2749 /****************************************************************************
2750 * ITypeLib2_Constructor_SLTG
2752 * loading a SLTG typelib from an in-memory image
2754 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2756 ITypeLibImpl *pTypeLibImpl;
2757 SLTG_Header *pHeader;
2758 SLTG_BlkEntry *pBlkEntry;
2759 SLTG_Magic *pMagic;
2760 SLTG_Index *pIndex;
2761 SLTG_Pad9 *pPad9;
2762 LPVOID pBlk, pFirstBlk;
2763 SLTG_LibBlk *pLibBlk;
2764 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2765 char *pAfterOTIBlks = NULL;
2766 char *pNameTable, *ptr;
2767 int i;
2768 DWORD len, order;
2769 ITypeInfoImpl **ppTypeInfoImpl;
2771 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2773 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2774 if (!pTypeLibImpl) return NULL;
2776 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2777 pTypeLibImpl->ref = 1;
2779 pHeader = pLib;
2781 TRACE("header:\n");
2782 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2783 pHeader->nrOfFileBlks );
2784 if (memcmp(&pHeader->SLTG_magic, TLBMAGIC1, 4)) {
2785 FIXME("Header type magic 0x%08lx not supported.\n",
2786 pHeader->SLTG_magic);
2787 return NULL;
2790 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2791 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2793 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2794 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2796 /* Next we have a magic block */
2797 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2799 /* Let's see if we're still in sync */
2800 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2801 sizeof(SLTG_COMPOBJ_MAGIC))) {
2802 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2803 return NULL;
2805 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2806 sizeof(SLTG_DIR_MAGIC))) {
2807 FIXME("dir magic = %s\n", pMagic->dir_magic);
2808 return NULL;
2811 pIndex = (SLTG_Index*)(pMagic+1);
2813 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2815 pFirstBlk = (LPVOID)(pPad9 + 1);
2817 /* We'll set up a ptr to the main library block, which is the last one. */
2819 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2820 pBlkEntry[order].next != 0;
2821 order = pBlkEntry[order].next - 1, i++) {
2822 pBlk += pBlkEntry[order].len;
2824 pLibBlk = pBlk;
2826 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2828 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2829 interspersed */
2831 len += 0x40;
2833 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2835 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2836 sizeof(*pOtherTypeInfoBlks) *
2837 pTypeLibImpl->TypeInfoCount);
2840 ptr = (char*)pLibBlk + len;
2842 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2843 WORD w, extra;
2844 len = 0;
2846 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2848 w = *(WORD*)(ptr + 2);
2849 if(w != 0xffff) {
2850 len += w;
2851 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2852 w+1);
2853 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2854 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2856 w = *(WORD*)(ptr + 4 + len);
2857 if(w != 0xffff) {
2858 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2859 len += w;
2860 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2861 w+1);
2862 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2863 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2865 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2866 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2867 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2868 if(extra) {
2869 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2870 extra);
2871 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2872 len += extra;
2874 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2875 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2876 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2877 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2878 len += sizeof(SLTG_OtherTypeInfo);
2879 ptr += len;
2882 pAfterOTIBlks = ptr;
2884 /* Skip this WORD and get the next DWORD */
2885 len = *(DWORD*)(pAfterOTIBlks + 2);
2887 /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a
2888 magic dust and we should be pointing at the beginning of the name
2889 table */
2891 pNameTable = (char*)pLibBlk + len + 0x216;
2893 pNameTable += 2;
2895 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
2897 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
2900 /* Hopefully we now have enough ptrs set up to actually read in
2901 some TypeInfos. It's not clear which order to do them in, so
2902 I'll just follow the links along the BlkEntry chain and read
2903 them in in the order in which they're in the file */
2905 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
2907 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2908 pBlkEntry[order].next != 0;
2909 order = pBlkEntry[order].next - 1, i++) {
2911 SLTG_TypeInfoHeader *pTIHeader;
2912 SLTG_TypeInfoTail *pTITail;
2914 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
2915 pOtherTypeInfoBlks[i].index_name)) {
2916 FIXME("Index strings don't match\n");
2917 return NULL;
2920 pTIHeader = pBlk;
2921 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
2922 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
2923 return NULL;
2925 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
2926 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
2927 ITypeLib2_AddRef((ITypeLib2 *)pTypeLibImpl);
2928 (*ppTypeInfoImpl)->index = i;
2929 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
2930 pOtherTypeInfoBlks[i].name_offs +
2931 pNameTable);
2932 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
2933 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
2934 sizeof(GUID));
2935 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
2936 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
2937 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
2938 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
2939 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
2941 if((pTIHeader->typeflags1 & 7) != 2)
2942 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
2943 if(pTIHeader->typeflags3 != 2)
2944 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
2946 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2947 debugstr_w((*ppTypeInfoImpl)->Name),
2948 typekind_desc[pTIHeader->typekind],
2949 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
2950 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
2952 switch(pTIHeader->typekind) {
2953 case TKIND_ENUM:
2954 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
2955 break;
2957 case TKIND_RECORD:
2958 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
2959 break;
2961 case TKIND_INTERFACE:
2962 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
2963 break;
2965 case TKIND_COCLASS:
2966 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
2967 break;
2969 default:
2970 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
2971 pTITail = NULL;
2972 break;
2976 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
2977 but we've already set those */
2978 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
2979 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
2980 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
2982 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
2983 pBlk += pBlkEntry[order].len;
2986 if(i != pTypeLibImpl->TypeInfoCount) {
2987 FIXME("Somehow processed %d TypeInfos\n", i);
2988 return NULL;
2991 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
2992 return (ITypeLib2*)pTypeLibImpl;
2995 /* ITypeLib::QueryInterface
2997 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
2998 ITypeLib2 * iface,
2999 REFIID riid,
3000 VOID **ppvObject)
3002 ICOM_THIS( ITypeLibImpl, iface);
3004 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3006 *ppvObject=NULL;
3007 if(IsEqualIID(riid, &IID_IUnknown) ||
3008 IsEqualIID(riid,&IID_ITypeLib)||
3009 IsEqualIID(riid,&IID_ITypeLib2))
3011 *ppvObject = This;
3014 if(*ppvObject)
3016 ITypeLib2_AddRef(iface);
3017 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3018 return S_OK;
3020 TRACE("-- Interface: E_NOINTERFACE\n");
3021 return E_NOINTERFACE;
3024 /* ITypeLib::AddRef
3026 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3028 ICOM_THIS( ITypeLibImpl, iface);
3030 TRACE("(%p)->ref is %u\n",This, This->ref);
3032 return ++(This->ref);
3035 /* ITypeLib::Release
3037 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3039 ICOM_THIS( ITypeLibImpl, iface);
3041 --(This->ref);
3043 TRACE("(%p)->(%u)\n",This, This->ref);
3045 if (!This->ref)
3047 /* FIXME destroy child objects */
3049 TRACE(" destroying ITypeLib(%p)\n",This);
3051 if (This->Name)
3053 SysFreeString(This->Name);
3054 This->Name = NULL;
3057 if (This->DocString)
3059 SysFreeString(This->DocString);
3060 This->DocString = NULL;
3063 if (This->HelpFile)
3065 SysFreeString(This->HelpFile);
3066 This->HelpFile = NULL;
3069 if (This->HelpStringDll)
3071 SysFreeString(This->HelpStringDll);
3072 This->HelpStringDll = NULL;
3075 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3076 HeapFree(GetProcessHeap(),0,This);
3077 return 0;
3080 return This->ref;
3083 /* ITypeLib::GetTypeInfoCount
3085 * Returns the number of type descriptions in the type library
3087 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3089 ICOM_THIS( ITypeLibImpl, iface);
3090 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3091 return This->TypeInfoCount;
3094 /* ITypeLib::GetTypeInfo
3096 * retrieves the specified type description in the library.
3098 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3099 ITypeLib2 *iface,
3100 UINT index,
3101 ITypeInfo **ppTInfo)
3103 int i;
3105 ICOM_THIS( ITypeLibImpl, iface);
3106 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3108 TRACE("(%p)->(index=%d) \n", This, index);
3110 if (!ppTInfo) return E_INVALIDARG;
3112 /* search element n in list */
3113 for(i=0; i < index; i++)
3115 pTypeInfo = pTypeInfo->next;
3116 if (!pTypeInfo)
3118 TRACE("-- element not found\n");
3119 return TYPE_E_ELEMENTNOTFOUND;
3123 *ppTInfo = (ITypeInfo *) pTypeInfo;
3125 ITypeInfo_AddRef(*ppTInfo);
3126 TRACE("-- found (%p)\n",*ppTInfo);
3127 return S_OK;
3131 /* ITypeLibs::GetTypeInfoType
3133 * Retrieves the type of a type description.
3135 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3136 ITypeLib2 *iface,
3137 UINT index,
3138 TYPEKIND *pTKind)
3140 ICOM_THIS( ITypeLibImpl, iface);
3141 int i;
3142 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3144 TRACE("(%p) index %d \n",This, index);
3146 if(!pTKind) return E_INVALIDARG;
3148 /* search element n in list */
3149 for(i=0; i < index; i++)
3151 if(!pTInfo)
3153 TRACE("-- element not found\n");
3154 return TYPE_E_ELEMENTNOTFOUND;
3156 pTInfo = pTInfo->next;
3159 *pTKind = pTInfo->TypeAttr.typekind;
3160 TRACE("-- found Type (%d)\n", *pTKind);
3161 return S_OK;
3164 /* ITypeLib::GetTypeInfoOfGuid
3166 * Retrieves the type description that corresponds to the specified GUID.
3169 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3170 ITypeLib2 *iface,
3171 REFGUID guid,
3172 ITypeInfo **ppTInfo)
3174 ICOM_THIS( ITypeLibImpl, iface);
3175 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3177 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3179 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3181 /* search linked list for guid */
3182 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3184 pTypeInfo = pTypeInfo->next;
3186 if (!pTypeInfo)
3188 /* end of list reached */
3189 TRACE("-- element not found\n");
3190 return TYPE_E_ELEMENTNOTFOUND;
3194 TRACE("-- found (%p, %s)\n",
3195 pTypeInfo,
3196 debugstr_w(pTypeInfo->Name));
3198 *ppTInfo = (ITypeInfo*)pTypeInfo;
3199 ITypeInfo_AddRef(*ppTInfo);
3200 return S_OK;
3203 /* ITypeLib::GetLibAttr
3205 * Retrieves the structure that contains the library's attributes.
3208 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3209 ITypeLib2 *iface,
3210 LPTLIBATTR *ppTLibAttr)
3212 ICOM_THIS( ITypeLibImpl, iface);
3213 TRACE("(%p)\n",This);
3214 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3215 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3216 return S_OK;
3219 /* ITypeLib::GetTypeComp
3221 * Enables a client compiler to bind to a library's types, variables,
3222 * constants, and global functions.
3225 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3226 ITypeLib2 *iface,
3227 ITypeComp **ppTComp)
3229 ICOM_THIS( ITypeLibImpl, iface);
3230 FIXME("(%p): stub!\n",This);
3231 return E_NOTIMPL;
3234 /* ITypeLib::GetDocumentation
3236 * Retrieves the library's documentation string, the complete Help file name
3237 * and path, and the context identifier for the library Help topic in the Help
3238 * file.
3240 * On a successful return all non-null BSTR pointers will have been set,
3241 * possibly to NULL.
3243 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3244 ITypeLib2 *iface,
3245 INT index,
3246 BSTR *pBstrName,
3247 BSTR *pBstrDocString,
3248 DWORD *pdwHelpContext,
3249 BSTR *pBstrHelpFile)
3251 ICOM_THIS( ITypeLibImpl, iface);
3253 HRESULT result = E_INVALIDARG;
3255 ITypeInfo *pTInfo;
3258 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3259 This, index,
3260 pBstrName, pBstrDocString,
3261 pdwHelpContext, pBstrHelpFile);
3263 if(index<0)
3265 /* documentation for the typelib */
3266 if(pBstrName)
3268 if (This->Name)
3269 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3270 else
3271 *pBstrName = NULL;
3273 if(pBstrDocString)
3275 if (This->DocString)
3276 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3277 else if (This->Name)
3278 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3279 else
3280 *pBstrDocString = NULL;
3282 if(pdwHelpContext)
3284 *pdwHelpContext = This->dwHelpContext;
3286 if(pBstrHelpFile)
3288 if (This->HelpFile)
3289 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3290 else
3291 *pBstrHelpFile = NULL;
3294 result = S_OK;
3296 else
3298 /* for a typeinfo */
3299 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3301 if(SUCCEEDED(result))
3303 result = ITypeInfo_GetDocumentation(pTInfo,
3304 MEMBERID_NIL,
3305 pBstrName,
3306 pBstrDocString,
3307 pdwHelpContext, pBstrHelpFile);
3309 ITypeInfo_Release(pTInfo);
3312 return result;
3313 memerr3:
3314 if (pBstrDocString) SysFreeString (*pBstrDocString);
3315 memerr2:
3316 if (pBstrName) SysFreeString (*pBstrName);
3317 memerr1:
3318 return STG_E_INSUFFICIENTMEMORY;
3321 /* ITypeLib::IsName
3323 * Indicates whether a passed-in string contains the name of a type or member
3324 * described in the library.
3327 static HRESULT WINAPI ITypeLib2_fnIsName(
3328 ITypeLib2 *iface,
3329 LPOLESTR szNameBuf,
3330 ULONG lHashVal,
3331 BOOL *pfName)
3333 ICOM_THIS( ITypeLibImpl, iface);
3334 ITypeInfoImpl *pTInfo;
3335 TLBFuncDesc *pFInfo;
3336 TLBVarDesc *pVInfo;
3337 int i;
3338 UINT nNameBufLen = SysStringLen(szNameBuf);
3340 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3341 pfName);
3343 *pfName=TRUE;
3344 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3345 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3346 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3347 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3348 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3349 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3350 goto ITypeLib2_fnIsName_exit;
3352 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3353 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3356 *pfName=FALSE;
3358 ITypeLib2_fnIsName_exit:
3359 TRACE("(%p)slow! search for %s: %s found!\n", This,
3360 debugstr_w(szNameBuf), *pfName?"NOT":"");
3362 return S_OK;
3365 /* ITypeLib::FindName
3367 * Finds occurrences of a type description in a type library. This may be used
3368 * to quickly verify that a name exists in a type library.
3371 static HRESULT WINAPI ITypeLib2_fnFindName(
3372 ITypeLib2 *iface,
3373 LPOLESTR szNameBuf,
3374 ULONG lHashVal,
3375 ITypeInfo **ppTInfo,
3376 MEMBERID *rgMemId,
3377 UINT16 *pcFound)
3379 ICOM_THIS( ITypeLibImpl, iface);
3380 ITypeInfoImpl *pTInfo;
3381 TLBFuncDesc *pFInfo;
3382 TLBVarDesc *pVInfo;
3383 int i,j = 0;
3385 UINT nNameBufLen = SysStringLen(szNameBuf);
3387 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3388 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3389 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3390 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3391 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3392 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3393 goto ITypeLib2_fnFindName_exit;
3395 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3396 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3397 continue;
3398 ITypeLib2_fnFindName_exit:
3399 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3400 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3401 j++;
3403 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3404 This, *pcFound, debugstr_w(szNameBuf), j);
3406 *pcFound=j;
3408 return S_OK;
3411 /* ITypeLib::ReleaseTLibAttr
3413 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3416 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3417 ITypeLib2 *iface,
3418 TLIBATTR *pTLibAttr)
3420 ICOM_THIS( ITypeLibImpl, iface);
3421 TRACE("freeing (%p)\n",This);
3422 HeapFree(GetProcessHeap(),0,pTLibAttr);
3426 /* ITypeLib2::GetCustData
3428 * gets the custom data
3430 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3431 ITypeLib2 * iface,
3432 REFGUID guid,
3433 VARIANT *pVarVal)
3435 ICOM_THIS( ITypeLibImpl, iface);
3436 TLBCustData *pCData;
3438 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3440 if( IsEqualIID(guid, &pCData->guid)) break;
3443 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3445 if(pCData)
3447 VariantInit( pVarVal);
3448 VariantCopy( pVarVal, &pCData->data);
3449 return S_OK;
3451 return E_INVALIDARG; /* FIXME: correct? */
3454 /* ITypeLib2::GetLibStatistics
3456 * Returns statistics about a type library that are required for efficient
3457 * sizing of hash tables.
3460 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3461 ITypeLib2 * iface,
3462 ULONG *pcUniqueNames,
3463 ULONG *pcchUniqueNames)
3465 ICOM_THIS( ITypeLibImpl, iface);
3467 FIXME("(%p): stub!\n", This);
3469 if(pcUniqueNames) *pcUniqueNames=1;
3470 if(pcchUniqueNames) *pcchUniqueNames=1;
3471 return S_OK;
3474 /* ITypeLib2::GetDocumentation2
3476 * Retrieves the library's documentation string, the complete Help file name
3477 * and path, the localization context to use, and the context ID for the
3478 * library Help topic in the Help file.
3481 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3482 ITypeLib2 * iface,
3483 INT index,
3484 LCID lcid,
3485 BSTR *pbstrHelpString,
3486 DWORD *pdwHelpStringContext,
3487 BSTR *pbstrHelpStringDll)
3489 ICOM_THIS( ITypeLibImpl, iface);
3490 HRESULT result;
3491 ITypeInfo *pTInfo;
3493 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3495 /* the help string should be obtained from the helpstringdll,
3496 * using the _DLLGetDocumentation function, based on the supplied
3497 * lcid. Nice to do sometime...
3499 if(index<0)
3501 /* documentation for the typelib */
3502 if(pbstrHelpString)
3503 *pbstrHelpString=SysAllocString(This->DocString);
3504 if(pdwHelpStringContext)
3505 *pdwHelpStringContext=This->dwHelpContext;
3506 if(pbstrHelpStringDll)
3507 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3509 result = S_OK;
3511 else
3513 /* for a typeinfo */
3514 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3516 if(SUCCEEDED(result))
3518 ITypeInfo2 * pTInfo2;
3519 result = ITypeInfo_QueryInterface(pTInfo,
3520 &IID_ITypeInfo2,
3521 (LPVOID*) &pTInfo2);
3523 if(SUCCEEDED(result))
3525 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3526 MEMBERID_NIL,
3527 lcid,
3528 pbstrHelpString,
3529 pdwHelpStringContext,
3530 pbstrHelpStringDll);
3532 ITypeInfo2_Release(pTInfo2);
3535 ITypeInfo_Release(pTInfo);
3538 return result;
3541 /* ITypeLib2::GetAllCustData
3543 * Gets all custom data items for the library.
3546 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3547 ITypeLib2 * iface,
3548 CUSTDATA *pCustData)
3550 ICOM_THIS( ITypeLibImpl, iface);
3551 TLBCustData *pCData;
3552 int i;
3553 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3554 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3555 if(pCustData->prgCustData ){
3556 pCustData->cCustData=This->ctCustData;
3557 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3558 pCustData->prgCustData[i].guid=pCData->guid;
3559 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3561 }else{
3562 ERR(" OUT OF MEMORY! \n");
3563 return E_OUTOFMEMORY;
3565 return S_OK;
3568 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3569 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3570 ITypeLib2_fnQueryInterface,
3571 ITypeLib2_fnAddRef,
3572 ITypeLib2_fnRelease,
3573 ITypeLib2_fnGetTypeInfoCount,
3574 ITypeLib2_fnGetTypeInfo,
3575 ITypeLib2_fnGetTypeInfoType,
3576 ITypeLib2_fnGetTypeInfoOfGuid,
3577 ITypeLib2_fnGetLibAttr,
3578 ITypeLib2_fnGetTypeComp,
3579 ITypeLib2_fnGetDocumentation,
3580 ITypeLib2_fnIsName,
3581 ITypeLib2_fnFindName,
3582 ITypeLib2_fnReleaseTLibAttr,
3584 ITypeLib2_fnGetCustData,
3585 ITypeLib2_fnGetLibStatistics,
3586 ITypeLib2_fnGetDocumentation2,
3587 ITypeLib2_fnGetAllCustData
3590 /*================== ITypeInfo(2) Methods ===================================*/
3591 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3593 ITypeInfoImpl * pTypeInfoImpl;
3595 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3596 if (pTypeInfoImpl)
3598 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3599 pTypeInfoImpl->ref=1;
3601 TRACE("(%p)\n", pTypeInfoImpl);
3602 return (ITypeInfo2*) pTypeInfoImpl;
3605 /* ITypeInfo::QueryInterface
3607 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3608 ITypeInfo2 *iface,
3609 REFIID riid,
3610 VOID **ppvObject)
3612 ICOM_THIS( ITypeLibImpl, iface);
3614 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3616 *ppvObject=NULL;
3617 if(IsEqualIID(riid, &IID_IUnknown) ||
3618 IsEqualIID(riid,&IID_ITypeInfo)||
3619 IsEqualIID(riid,&IID_ITypeInfo2))
3620 *ppvObject = This;
3622 if(*ppvObject){
3623 ITypeInfo_AddRef(iface);
3624 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3625 return S_OK;
3627 TRACE("-- Interface: E_NOINTERFACE\n");
3628 return E_NOINTERFACE;
3631 /* ITypeInfo::AddRef
3633 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3635 ICOM_THIS( ITypeInfoImpl, iface);
3637 ++(This->ref);
3639 TRACE("(%p)->ref is %u\n",This, This->ref);
3640 return This->ref;
3643 /* ITypeInfo::Release
3645 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3647 ICOM_THIS( ITypeInfoImpl, iface);
3649 --(This->ref);
3651 TRACE("(%p)->(%u)\n",This, This->ref);
3653 if (!This->ref)
3655 FIXME("destroy child objects\n");
3657 TRACE("destroying ITypeInfo(%p)\n",This);
3658 if (This->Name)
3660 SysFreeString(This->Name);
3661 This->Name = 0;
3664 if (This->DocString)
3666 SysFreeString(This->DocString);
3667 This->DocString = 0;
3670 if (This->next)
3672 ITypeInfo_Release((ITypeInfo*)This->next);
3675 HeapFree(GetProcessHeap(),0,This);
3676 return 0;
3678 return This->ref;
3681 /* ITypeInfo::GetTypeAttr
3683 * Retrieves a TYPEATTR structure that contains the attributes of the type
3684 * description.
3687 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3688 LPTYPEATTR *ppTypeAttr)
3690 ICOM_THIS( ITypeInfoImpl, iface);
3691 TRACE("(%p)\n",This);
3692 /* FIXME: must do a copy here */
3693 *ppTypeAttr=&This->TypeAttr;
3694 return S_OK;
3697 /* ITypeInfo::GetTypeComp
3699 * Retrieves the ITypeComp interface for the type description, which enables a
3700 * client compiler to bind to the type description's members.
3703 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3704 ITypeComp * *ppTComp)
3706 ICOM_THIS( ITypeInfoImpl, iface);
3707 FIXME("(%p) stub!\n", This);
3708 return S_OK;
3711 /* ITypeInfo::GetFuncDesc
3713 * Retrieves the FUNCDESC structure that contains information about a
3714 * specified function.
3717 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3718 LPFUNCDESC *ppFuncDesc)
3720 ICOM_THIS( ITypeInfoImpl, iface);
3721 int i;
3722 TLBFuncDesc * pFDesc;
3723 TRACE("(%p) index %d\n", This, index);
3724 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3726 if(pFDesc){
3727 /* FIXME: must do a copy here */
3728 *ppFuncDesc=&pFDesc->funcdesc;
3729 return S_OK;
3731 return E_INVALIDARG;
3734 /* ITypeInfo::GetVarDesc
3736 * Retrieves a VARDESC structure that describes the specified variable.
3739 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3740 LPVARDESC *ppVarDesc)
3742 ICOM_THIS( ITypeInfoImpl, iface);
3743 int i;
3744 TLBVarDesc * pVDesc;
3745 TRACE("(%p) index %d\n", This, index);
3746 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3748 if(pVDesc){
3749 /* FIXME: must do a copy here */
3750 *ppVarDesc=&pVDesc->vardesc;
3751 return S_OK;
3753 return E_INVALIDARG;
3756 /* ITypeInfo_GetNames
3758 * Retrieves the variable with the specified member ID (or the name of the
3759 * property or method and its parameters) that correspond to the specified
3760 * function ID.
3762 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3763 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3765 ICOM_THIS( ITypeInfoImpl, iface);
3766 TLBFuncDesc * pFDesc;
3767 TLBVarDesc * pVDesc;
3768 int i;
3769 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3770 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3771 if(pFDesc)
3773 /* function found, now return function and parameter names */
3774 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3776 if(!i)
3777 *rgBstrNames=SysAllocString(pFDesc->Name);
3778 else
3779 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3781 *pcNames=i;
3783 else
3785 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3786 if(pVDesc)
3788 *rgBstrNames=SysAllocString(pVDesc->Name);
3789 *pcNames=1;
3791 else
3793 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3795 /* recursive search */
3796 ITypeInfo *pTInfo;
3797 HRESULT result;
3798 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3799 &pTInfo);
3800 if(SUCCEEDED(result))
3802 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3803 ITypeInfo_Release(pTInfo);
3804 return result;
3806 WARN("Could not search inherited interface!\n");
3808 else
3810 WARN("no names found\n");
3812 *pcNames=0;
3813 return TYPE_E_ELEMENTNOTFOUND;
3816 return S_OK;
3820 /* ITypeInfo::GetRefTypeOfImplType
3822 * If a type description describes a COM class, it retrieves the type
3823 * description of the implemented interface types. For an interface,
3824 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3825 * if any exist.
3828 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3829 ITypeInfo2 *iface,
3830 UINT index,
3831 HREFTYPE *pRefType)
3833 ICOM_THIS( ITypeInfoImpl, iface);
3834 int(i);
3835 TLBImplType *pImpl = This->impltypelist;
3837 TRACE("(%p) index %d\n", This, index);
3838 dump_TypeInfo(This);
3840 if(index==(UINT)-1)
3842 /* only valid on dual interfaces;
3843 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3845 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3847 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3848 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3850 *pRefType = -1;
3852 else
3854 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3855 *pRefType = pImpl->hRef;
3858 else
3860 /* get element n from linked list */
3861 for(i=0; pImpl && i<index; i++)
3863 pImpl = pImpl->next;
3866 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3868 *pRefType = pImpl->hRef;
3870 TRACE("-- 0x%08lx\n", pImpl->hRef );
3873 return S_OK;
3877 /* ITypeInfo::GetImplTypeFlags
3879 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3880 * or base interface in a type description.
3882 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
3883 UINT index, INT *pImplTypeFlags)
3885 ICOM_THIS( ITypeInfoImpl, iface);
3886 int i;
3887 TLBImplType *pImpl;
3889 TRACE("(%p) index %d\n", This, index);
3890 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
3891 i++, pImpl=pImpl->next)
3893 if(i==index && pImpl){
3894 *pImplTypeFlags=pImpl->implflags;
3895 return S_OK;
3897 *pImplTypeFlags=0;
3898 return TYPE_E_ELEMENTNOTFOUND;
3901 /* GetIDsOfNames
3902 * Maps between member names and member IDs, and parameter names and
3903 * parameter IDs.
3905 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
3906 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
3908 ICOM_THIS( ITypeInfoImpl, iface);
3909 TLBFuncDesc * pFDesc;
3910 TLBVarDesc * pVDesc;
3911 HRESULT ret=S_OK;
3913 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
3914 cNames);
3915 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
3916 int i, j;
3917 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
3918 if(cNames) *pMemId=pFDesc->funcdesc.memid;
3919 for(i=1; i < cNames; i++){
3920 for(j=0; j<pFDesc->funcdesc.cParams; j++)
3921 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
3922 break;
3923 if( j<pFDesc->funcdesc.cParams)
3924 pMemId[i]=j;
3925 else
3926 ret=DISP_E_UNKNOWNNAME;
3928 return ret;
3931 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
3932 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
3933 if(cNames) *pMemId=pVDesc->vardesc.memid;
3934 return ret;
3937 /* not found, see if this is and interface with an inheritance */
3938 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
3939 This->TypeAttr.cImplTypes ){
3940 /* recursive search */
3941 ITypeInfo *pTInfo;
3942 ret=ITypeInfo_GetRefTypeInfo(iface,
3943 This->impltypelist->hRef, &pTInfo);
3944 if(SUCCEEDED(ret)){
3945 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
3946 ITypeInfo_Release(pTInfo);
3947 return ret;
3949 WARN("Could not search inherited interface!\n");
3950 } else
3951 WARN("no names found\n");
3952 return DISP_E_UNKNOWNNAME;
3955 /* ITypeInfo::Invoke
3957 * Invokes a method, or accesses a property of an object, that implements the
3958 * interface described by the type description.
3960 DWORD
3961 _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
3962 DWORD res;
3964 if (TRACE_ON(ole)) {
3965 int i;
3966 MESSAGE("Calling %p(",func);
3967 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
3968 MESSAGE(")\n");
3971 switch (callconv) {
3972 case CC_STDCALL:
3974 switch (nrargs) {
3975 case 0: {
3976 DWORD (WINAPI *xfunc)() = func;
3977 res = xfunc();
3978 break;
3980 case 1: {
3981 DWORD (WINAPI *xfunc)(DWORD) = func;
3982 res = xfunc(args[0]);
3983 break;
3985 case 2: {
3986 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
3987 res = xfunc(args[0],args[1]);
3988 break;
3990 case 3: {
3991 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
3992 res = xfunc(args[0],args[1],args[2]);
3993 break;
3995 case 4: {
3996 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD) = func;
3997 res = xfunc(args[0],args[1],args[2],args[3]);
3998 break;
4000 case 5: {
4001 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4002 res = xfunc(args[0],args[1],args[2],args[3],args[4]);
4003 break;
4005 case 6: {
4006 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4007 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5]);
4008 break;
4010 case 7: {
4011 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4012 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4013 break;
4015 default:
4016 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4017 res = -1;
4018 break;
4020 break;
4021 default:
4022 FIXME("unsupported calling convention %d\n",callconv);
4023 res = -1;
4024 break;
4026 TRACE("returns %08lx\n",res);
4027 return res;
4030 static HRESULT WINAPI ITypeInfo_fnInvoke(
4031 ITypeInfo2 *iface,
4032 VOID *pIUnk,
4033 MEMBERID memid,
4034 UINT16 dwFlags,
4035 DISPPARAMS *pDispParams,
4036 VARIANT *pVarResult,
4037 EXCEPINFO *pExcepInfo,
4038 UINT *pArgErr)
4040 ICOM_THIS( ITypeInfoImpl, iface);
4041 TLBFuncDesc * pFDesc;
4042 TLBVarDesc * pVDesc;
4043 int i;
4045 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4046 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4048 dump_DispParms(pDispParams);
4050 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4051 if (pFDesc->funcdesc.memid == memid) {
4052 if (pFDesc->funcdesc.invkind & dwFlags)
4053 break;
4055 if (pFDesc) {
4056 dump_TLBFuncDescOne(pFDesc);
4057 switch (pFDesc->funcdesc.funckind) {
4058 case FUNC_PUREVIRTUAL:
4059 case FUNC_VIRTUAL: {
4060 DWORD res;
4061 DWORD *args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*(pFDesc->funcdesc.cParams+1));
4062 DWORD *args2 = (DWORD*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*(pFDesc->funcdesc.cParams));
4063 args[0] = (DWORD)pIUnk;
4065 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4066 if (i<pDispParams->cArgs) {
4067 TRACE("set %d to disparg type %d vs %d\n",i,
4068 V_VT(&pDispParams->rgvarg[pDispParams->cArgs-i-1]),
4069 pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt
4071 args[i+1] = V_UNION(&pDispParams->rgvarg[pDispParams->cArgs-i-1],lVal);
4072 } else {
4073 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4074 TRACE("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4075 /*FIXME: give pointers for the rest, so propertyget works*/
4076 args[i+1] = (DWORD)&args2[i];
4078 /* If pointer to variant, pass reference to variant
4079 * in result variant array.
4081 if ((tdesc->vt == VT_PTR) &&
4082 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4083 pVarResult
4085 args[i+1] = (DWORD)(pVarResult+(i-pDispParams->cArgs));
4088 if (pFDesc->funcdesc.cParamsOpt)
4089 FIXME("Does not support optional parameters (%d)\n",
4090 pFDesc->funcdesc.cParamsOpt
4093 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4094 pFDesc->funcdesc.callconv,
4095 pFDesc->funcdesc.cParams+1,
4096 args
4098 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4099 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4100 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4101 /* If we are a pointer to a variant, we are done already */
4102 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4103 continue;
4105 VariantInit(&pVarResult[i]);
4106 V_UNION(pVarResult+i,intVal) = args2[i+pDispParams->cArgs];
4108 if (tdesc->vt == VT_PTR)
4109 tdesc = tdesc->u.lptdesc;
4110 V_VT(pVarResult+i) = tdesc->vt;
4112 /* HACK: VB5 likes this.
4113 * I do not know why. There is 1 example in MSDN which uses
4114 * this which appears broken (mixes int vals and
4115 * IDispatch*.).
4117 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4118 V_VT(pVarResult+i) = VT_DISPATCH;
4119 TRACE("storing into variant: [%d]\n", i);
4120 dump_Variant(pVarResult+i);
4123 HeapFree(GetProcessHeap(),0,args2);
4124 HeapFree(GetProcessHeap(),0,args);
4125 return S_OK;
4127 case FUNC_DISPATCH: {
4128 IDispatch *disp;
4129 HRESULT hr;
4131 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4132 if (hr) {
4133 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4134 return hr;
4136 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4137 hr = IDispatch_Invoke(
4138 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4139 pVarResult,pExcepInfo,pArgErr
4141 if (hr)
4142 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4143 IDispatch_Release(disp);
4144 return hr;
4146 default:
4147 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4148 return E_FAIL;
4150 } else {
4151 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4152 if (pVDesc->vardesc.memid == memid) {
4153 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4154 dump_TLBVarDesc(pVDesc);
4155 break;
4159 /* not found, look for it in inherited interfaces */
4160 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4161 /* recursive search */
4162 ITypeInfo *pTInfo;
4163 HRESULT hr;
4164 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4165 if(SUCCEEDED(hr)){
4166 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4167 ITypeInfo_Release(pTInfo);
4168 return hr;
4170 WARN("Could not search inherited interface!\n");
4172 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4173 return DISP_E_MEMBERNOTFOUND;
4176 /* ITypeInfo::GetDocumentation
4178 * Retrieves the documentation string, the complete Help file name and path,
4179 * and the context ID for the Help topic for a specified type description.
4181 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4182 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4183 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4185 ICOM_THIS( ITypeInfoImpl, iface);
4186 TLBFuncDesc * pFDesc;
4187 TLBVarDesc * pVDesc;
4188 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4189 " HelpContext(%p) HelpFile(%p)\n",
4190 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4191 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4192 if(pBstrName)
4193 *pBstrName=SysAllocString(This->Name);
4194 if(pBstrDocString)
4195 *pBstrDocString=SysAllocString(This->DocString);
4196 if(pdwHelpContext)
4197 *pdwHelpContext=This->dwHelpContext;
4198 if(pBstrHelpFile)
4199 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4200 return S_OK;
4201 }else {/* for a member */
4202 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4203 if(pFDesc->funcdesc.memid==memid){
4204 if(pBstrName)
4205 *pBstrName = SysAllocString(pFDesc->Name);
4206 if(pBstrDocString)
4207 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4208 if(pdwHelpContext)
4209 *pdwHelpContext=pFDesc->helpcontext;
4210 return S_OK;
4212 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4213 if(pVDesc->vardesc.memid==memid){
4214 FIXME("Not implemented\n");
4215 return S_OK;
4218 return TYPE_E_ELEMENTNOTFOUND;
4221 /* ITypeInfo::GetDllEntry
4223 * Retrieves a description or specification of an entry point for a function
4224 * in a DLL.
4226 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4227 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4228 WORD *pwOrdinal)
4230 ICOM_THIS( ITypeInfoImpl, iface);
4231 FIXME("(%p) stub!\n", This);
4232 return E_FAIL;
4235 /* ITypeInfo::GetRefTypeInfo
4237 * If a type description references other type descriptions, it retrieves
4238 * the referenced type descriptions.
4240 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4241 ITypeInfo2 *iface,
4242 HREFTYPE hRefType,
4243 ITypeInfo **ppTInfo)
4245 ICOM_THIS( ITypeInfoImpl, iface);
4246 HRESULT result = E_FAIL;
4249 if (hRefType == -1 &&
4250 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4251 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4253 /* when we meet a DUAL dispinterface, we must create the interface
4254 * version of it.
4256 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4259 /* the interface version contains the same information as the dispinterface
4260 * copy the contents of the structs.
4262 *pTypeInfoImpl = *This;
4263 pTypeInfoImpl->ref = 1;
4265 /* change the type to interface */
4266 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4268 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4270 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4272 result = S_OK;
4274 } else {
4275 TLBRefType *pRefType;
4276 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4277 if(pRefType->reference == hRefType)
4278 break;
4280 if(!pRefType)
4281 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4282 if(pRefType && hRefType != -1) {
4283 ITypeLib *pTLib = NULL;
4285 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4286 int Index;
4287 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4288 } else {
4289 if(pRefType->pImpTLInfo->pImpTypeLib) {
4290 TRACE("typeinfo in imported typelib that is already loaded\n");
4291 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4292 ITypeLib2_AddRef((ITypeLib*) pTLib);
4293 result = S_OK;
4294 } else {
4295 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4296 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4297 pRefType->pImpTLInfo->wVersionMajor,
4298 pRefType->pImpTLInfo->wVersionMinor,
4299 pRefType->pImpTLInfo->lcid,
4300 &pTLib);
4302 if(!SUCCEEDED(result)) {
4303 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4304 result=LoadTypeLib(libnam, &pTLib);
4305 SysFreeString(libnam);
4307 if(SUCCEEDED(result)) {
4308 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4309 ITypeLib2_AddRef(pTLib);
4313 if(SUCCEEDED(result)) {
4314 if(pRefType->index == TLB_REF_USE_GUID)
4315 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4316 &pRefType->guid,
4317 ppTInfo);
4318 else
4319 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4320 ppTInfo);
4322 if (pTLib != NULL)
4323 ITypeLib2_Release(pTLib);
4327 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4328 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4329 return result;
4332 /* ITypeInfo::AddressOfMember
4334 * Retrieves the addresses of static functions or variables, such as those
4335 * defined in a DLL.
4337 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4338 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4340 ICOM_THIS( ITypeInfoImpl, iface);
4341 FIXME("(%p) stub!\n", This);
4342 return S_OK;
4345 /* ITypeInfo::CreateInstance
4347 * Creates a new instance of a type that describes a component object class
4348 * (coclass).
4350 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4351 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4353 ICOM_THIS( ITypeInfoImpl, iface);
4354 FIXME("(%p) stub!\n", This);
4355 return S_OK;
4358 /* ITypeInfo::GetMops
4360 * Retrieves marshaling information.
4362 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4363 BSTR *pBstrMops)
4365 ICOM_THIS( ITypeInfoImpl, iface);
4366 FIXME("(%p) stub!\n", This);
4367 return S_OK;
4370 /* ITypeInfo::GetContainingTypeLib
4372 * Retrieves the containing type library and the index of the type description
4373 * within that type library.
4375 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4376 ITypeLib * *ppTLib, UINT *pIndex)
4378 ICOM_THIS( ITypeInfoImpl, iface);
4379 if (!pIndex)
4380 return E_INVALIDARG;
4381 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4382 *pIndex=This->index;
4383 ITypeLib2_AddRef(*ppTLib);
4384 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4385 return S_OK;
4388 /* ITypeInfo::ReleaseTypeAttr
4390 * Releases a TYPEATTR previously returned by GetTypeAttr.
4393 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4394 TYPEATTR* pTypeAttr)
4396 ICOM_THIS( ITypeInfoImpl, iface);
4397 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4398 return S_OK;
4401 /* ITypeInfo::ReleaseFuncDesc
4403 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4405 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4406 ITypeInfo2 *iface,
4407 FUNCDESC *pFuncDesc)
4409 ICOM_THIS( ITypeInfoImpl, iface);
4410 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4411 return S_OK;
4414 /* ITypeInfo::ReleaseVarDesc
4416 * Releases a VARDESC previously returned by GetVarDesc.
4418 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4419 VARDESC *pVarDesc)
4421 ICOM_THIS( ITypeInfoImpl, iface);
4422 TRACE("(%p)->(%p)\n", This, pVarDesc);
4423 return S_OK;
4426 /* ITypeInfo2::GetTypeKind
4428 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4431 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4432 TYPEKIND *pTypeKind)
4434 ICOM_THIS( ITypeInfoImpl, iface);
4435 *pTypeKind=This->TypeAttr.typekind;
4436 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4437 return S_OK;
4440 /* ITypeInfo2::GetTypeFlags
4442 * Returns the type flags without any allocations. This returns a DWORD type
4443 * flag, which expands the type flags without growing the TYPEATTR (type
4444 * attribute).
4447 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4448 UINT *pTypeFlags)
4450 ICOM_THIS( ITypeInfoImpl, iface);
4451 *pTypeFlags=This->TypeAttr.wTypeFlags;
4452 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4453 return S_OK;
4456 /* ITypeInfo2::GetFuncIndexOfMemId
4457 * Binds to a specific member based on a known DISPID, where the member name
4458 * is not known (for example, when binding to a default member).
4461 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4462 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4464 ICOM_THIS( ITypeInfoImpl, iface);
4465 TLBFuncDesc *pFuncInfo;
4466 int i;
4467 HRESULT result;
4468 /* FIXME: should check for invKind??? */
4469 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4470 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4471 if(pFuncInfo){
4472 *pFuncIndex=i;
4473 result= S_OK;
4474 }else{
4475 *pFuncIndex=0;
4476 result=E_INVALIDARG;
4478 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4479 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4480 return result;
4483 /* TypeInfo2::GetVarIndexOfMemId
4485 * Binds to a specific member based on a known DISPID, where the member name
4486 * is not known (for example, when binding to a default member).
4489 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4490 MEMBERID memid, UINT *pVarIndex)
4492 ICOM_THIS( ITypeInfoImpl, iface);
4493 TLBVarDesc *pVarInfo;
4494 int i;
4495 HRESULT result;
4496 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4497 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4499 if(pVarInfo){
4500 *pVarIndex=i;
4501 result= S_OK;
4502 }else{
4503 *pVarIndex=0;
4504 result=E_INVALIDARG;
4506 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4507 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4508 return result;
4511 /* ITypeInfo2::GetCustData
4513 * Gets the custom data
4515 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4516 ITypeInfo2 * iface,
4517 REFGUID guid,
4518 VARIANT *pVarVal)
4520 ICOM_THIS( ITypeInfoImpl, iface);
4521 TLBCustData *pCData;
4523 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4524 if( IsEqualIID(guid, &pCData->guid)) break;
4526 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4528 if(pCData)
4530 VariantInit( pVarVal);
4531 VariantCopy( pVarVal, &pCData->data);
4532 return S_OK;
4534 return E_INVALIDARG; /* FIXME: correct? */
4537 /* ITypeInfo2::GetFuncCustData
4539 * Gets the custom data
4541 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4542 ITypeInfo2 * iface,
4543 UINT index,
4544 REFGUID guid,
4545 VARIANT *pVarVal)
4547 ICOM_THIS( ITypeInfoImpl, iface);
4548 TLBCustData *pCData=NULL;
4549 TLBFuncDesc * pFDesc;
4550 int i;
4551 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4552 pFDesc=pFDesc->next);
4554 if(pFDesc)
4555 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4556 if( IsEqualIID(guid, &pCData->guid)) break;
4558 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4560 if(pCData){
4561 VariantInit( pVarVal);
4562 VariantCopy( pVarVal, &pCData->data);
4563 return S_OK;
4565 return E_INVALIDARG; /* FIXME: correct? */
4568 /* ITypeInfo2::GetParamCustData
4570 * Gets the custom data
4572 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4573 ITypeInfo2 * iface,
4574 UINT indexFunc,
4575 UINT indexParam,
4576 REFGUID guid,
4577 VARIANT *pVarVal)
4579 ICOM_THIS( ITypeInfoImpl, iface);
4580 TLBCustData *pCData=NULL;
4581 TLBFuncDesc * pFDesc;
4582 int i;
4584 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4586 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4587 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4588 pCData = pCData->next)
4589 if( IsEqualIID(guid, &pCData->guid)) break;
4591 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4593 if(pCData)
4595 VariantInit( pVarVal);
4596 VariantCopy( pVarVal, &pCData->data);
4597 return S_OK;
4599 return E_INVALIDARG; /* FIXME: correct? */
4602 /* ITypeInfo2::GetVarCustData
4604 * Gets the custom data
4606 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4607 ITypeInfo2 * iface,
4608 UINT index,
4609 REFGUID guid,
4610 VARIANT *pVarVal)
4612 ICOM_THIS( ITypeInfoImpl, iface);
4613 TLBCustData *pCData=NULL;
4614 TLBVarDesc * pVDesc;
4615 int i;
4617 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4619 if(pVDesc)
4621 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4623 if( IsEqualIID(guid, &pCData->guid)) break;
4627 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4629 if(pCData)
4631 VariantInit( pVarVal);
4632 VariantCopy( pVarVal, &pCData->data);
4633 return S_OK;
4635 return E_INVALIDARG; /* FIXME: correct? */
4638 /* ITypeInfo2::GetImplCustData
4640 * Gets the custom data
4642 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4643 ITypeInfo2 * iface,
4644 UINT index,
4645 REFGUID guid,
4646 VARIANT *pVarVal)
4648 ICOM_THIS( ITypeInfoImpl, iface);
4649 TLBCustData *pCData=NULL;
4650 TLBImplType * pRDesc;
4651 int i;
4653 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4655 if(pRDesc)
4657 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4659 if( IsEqualIID(guid, &pCData->guid)) break;
4663 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4665 if(pCData)
4667 VariantInit( pVarVal);
4668 VariantCopy( pVarVal, &pCData->data);
4669 return S_OK;
4671 return E_INVALIDARG; /* FIXME: correct? */
4674 /* ITypeInfo2::GetDocumentation2
4676 * Retrieves the documentation string, the complete Help file name and path,
4677 * the localization context to use, and the context ID for the library Help
4678 * topic in the Help file.
4681 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4682 ITypeInfo2 * iface,
4683 MEMBERID memid,
4684 LCID lcid,
4685 BSTR *pbstrHelpString,
4686 DWORD *pdwHelpStringContext,
4687 BSTR *pbstrHelpStringDll)
4689 ICOM_THIS( ITypeInfoImpl, iface);
4690 TLBFuncDesc * pFDesc;
4691 TLBVarDesc * pVDesc;
4692 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4693 "HelpStringContext(%p) HelpStringDll(%p)\n",
4694 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4695 pbstrHelpStringDll );
4696 /* the help string should be obtained from the helpstringdll,
4697 * using the _DLLGetDocumentation function, based on the supplied
4698 * lcid. Nice to do sometime...
4700 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4701 if(pbstrHelpString)
4702 *pbstrHelpString=SysAllocString(This->Name);
4703 if(pdwHelpStringContext)
4704 *pdwHelpStringContext=This->dwHelpStringContext;
4705 if(pbstrHelpStringDll)
4706 *pbstrHelpStringDll=
4707 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4708 return S_OK;
4709 }else {/* for a member */
4710 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4711 if(pFDesc->funcdesc.memid==memid){
4712 if(pbstrHelpString)
4713 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4714 if(pdwHelpStringContext)
4715 *pdwHelpStringContext=pFDesc->HelpStringContext;
4716 if(pbstrHelpStringDll)
4717 *pbstrHelpStringDll=
4718 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4719 return S_OK;
4721 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4722 if(pVDesc->vardesc.memid==memid){
4723 if(pbstrHelpString)
4724 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4725 if(pdwHelpStringContext)
4726 *pdwHelpStringContext=pVDesc->HelpStringContext;
4727 if(pbstrHelpStringDll)
4728 *pbstrHelpStringDll=
4729 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4730 return S_OK;
4733 return TYPE_E_ELEMENTNOTFOUND;
4736 /* ITypeInfo2::GetAllCustData
4738 * Gets all custom data items for the Type info.
4741 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4742 ITypeInfo2 * iface,
4743 CUSTDATA *pCustData)
4745 ICOM_THIS( ITypeInfoImpl, iface);
4746 TLBCustData *pCData;
4747 int i;
4749 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4751 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4752 if(pCustData->prgCustData ){
4753 pCustData->cCustData=This->ctCustData;
4754 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4755 pCustData->prgCustData[i].guid=pCData->guid;
4756 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4758 }else{
4759 ERR(" OUT OF MEMORY! \n");
4760 return E_OUTOFMEMORY;
4762 return S_OK;
4765 /* ITypeInfo2::GetAllFuncCustData
4767 * Gets all custom data items for the specified Function
4770 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4771 ITypeInfo2 * iface,
4772 UINT index,
4773 CUSTDATA *pCustData)
4775 ICOM_THIS( ITypeInfoImpl, iface);
4776 TLBCustData *pCData;
4777 TLBFuncDesc * pFDesc;
4778 int i;
4779 TRACE("(%p) index %d\n", This, index);
4780 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4781 pFDesc=pFDesc->next)
4783 if(pFDesc){
4784 pCustData->prgCustData =
4785 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4786 if(pCustData->prgCustData ){
4787 pCustData->cCustData=pFDesc->ctCustData;
4788 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4789 pCData = pCData->next){
4790 pCustData->prgCustData[i].guid=pCData->guid;
4791 VariantCopy(& pCustData->prgCustData[i].varValue,
4792 & pCData->data);
4794 }else{
4795 ERR(" OUT OF MEMORY! \n");
4796 return E_OUTOFMEMORY;
4798 return S_OK;
4800 return TYPE_E_ELEMENTNOTFOUND;
4803 /* ITypeInfo2::GetAllParamCustData
4805 * Gets all custom data items for the Functions
4808 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4809 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4811 ICOM_THIS( ITypeInfoImpl, iface);
4812 TLBCustData *pCData=NULL;
4813 TLBFuncDesc * pFDesc;
4814 int i;
4815 TRACE("(%p) index %d\n", This, indexFunc);
4816 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4817 pFDesc=pFDesc->next)
4819 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4820 pCustData->prgCustData =
4821 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4822 sizeof(CUSTDATAITEM));
4823 if(pCustData->prgCustData ){
4824 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
4825 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
4826 pCData; i++, pCData = pCData->next){
4827 pCustData->prgCustData[i].guid=pCData->guid;
4828 VariantCopy(& pCustData->prgCustData[i].varValue,
4829 & pCData->data);
4831 }else{
4832 ERR(" OUT OF MEMORY! \n");
4833 return E_OUTOFMEMORY;
4835 return S_OK;
4837 return TYPE_E_ELEMENTNOTFOUND;
4840 /* ITypeInfo2::GetAllVarCustData
4842 * Gets all custom data items for the specified Variable
4845 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
4846 UINT index, CUSTDATA *pCustData)
4848 ICOM_THIS( ITypeInfoImpl, iface);
4849 TLBCustData *pCData;
4850 TLBVarDesc * pVDesc;
4851 int i;
4852 TRACE("(%p) index %d\n", This, index);
4853 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
4854 pVDesc=pVDesc->next)
4856 if(pVDesc){
4857 pCustData->prgCustData =
4858 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
4859 if(pCustData->prgCustData ){
4860 pCustData->cCustData=pVDesc->ctCustData;
4861 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
4862 pCData = pCData->next){
4863 pCustData->prgCustData[i].guid=pCData->guid;
4864 VariantCopy(& pCustData->prgCustData[i].varValue,
4865 & pCData->data);
4867 }else{
4868 ERR(" OUT OF MEMORY! \n");
4869 return E_OUTOFMEMORY;
4871 return S_OK;
4873 return TYPE_E_ELEMENTNOTFOUND;
4876 /* ITypeInfo2::GetAllImplCustData
4878 * Gets all custom data items for the specified implementation type
4881 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
4882 ITypeInfo2 * iface,
4883 UINT index,
4884 CUSTDATA *pCustData)
4886 ICOM_THIS( ITypeInfoImpl, iface);
4887 TLBCustData *pCData;
4888 TLBImplType * pRDesc;
4889 int i;
4890 TRACE("(%p) index %d\n", This, index);
4891 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
4892 pRDesc=pRDesc->next)
4894 if(pRDesc){
4895 pCustData->prgCustData =
4896 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
4897 if(pCustData->prgCustData ){
4898 pCustData->cCustData=pRDesc->ctCustData;
4899 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
4900 pCData = pCData->next){
4901 pCustData->prgCustData[i].guid=pCData->guid;
4902 VariantCopy(& pCustData->prgCustData[i].varValue,
4903 & pCData->data);
4905 }else{
4906 ERR(" OUT OF MEMORY! \n");
4907 return E_OUTOFMEMORY;
4909 return S_OK;
4911 return TYPE_E_ELEMENTNOTFOUND;
4914 static ICOM_VTABLE(ITypeInfo2) tinfvt =
4916 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4918 ITypeInfo_fnQueryInterface,
4919 ITypeInfo_fnAddRef,
4920 ITypeInfo_fnRelease,
4922 ITypeInfo_fnGetTypeAttr,
4923 ITypeInfo_fnGetTypeComp,
4924 ITypeInfo_fnGetFuncDesc,
4925 ITypeInfo_fnGetVarDesc,
4926 ITypeInfo_fnGetNames,
4927 ITypeInfo_fnGetRefTypeOfImplType,
4928 ITypeInfo_fnGetImplTypeFlags,
4929 ITypeInfo_fnGetIDsOfNames,
4930 ITypeInfo_fnInvoke,
4931 ITypeInfo_fnGetDocumentation,
4932 ITypeInfo_fnGetDllEntry,
4933 ITypeInfo_fnGetRefTypeInfo,
4934 ITypeInfo_fnAddressOfMember,
4935 ITypeInfo_fnCreateInstance,
4936 ITypeInfo_fnGetMops,
4937 ITypeInfo_fnGetContainingTypeLib,
4938 ITypeInfo_fnReleaseTypeAttr,
4939 ITypeInfo_fnReleaseFuncDesc,
4940 ITypeInfo_fnReleaseVarDesc,
4942 ITypeInfo2_fnGetTypeKind,
4943 ITypeInfo2_fnGetTypeFlags,
4944 ITypeInfo2_fnGetFuncIndexOfMemId,
4945 ITypeInfo2_fnGetVarIndexOfMemId,
4946 ITypeInfo2_fnGetCustData,
4947 ITypeInfo2_fnGetFuncCustData,
4948 ITypeInfo2_fnGetParamCustData,
4949 ITypeInfo2_fnGetVarCustData,
4950 ITypeInfo2_fnGetImplTypeCustData,
4951 ITypeInfo2_fnGetDocumentation2,
4952 ITypeInfo2_fnGetAllCustData,
4953 ITypeInfo2_fnGetAllFuncCustData,
4954 ITypeInfo2_fnGetAllParamCustData,
4955 ITypeInfo2_fnGetAllVarCustData,
4956 ITypeInfo2_fnGetAllImplTypeCustData,