Remove some unnecessary AddRef's.
[wine/testsucceed.git] / dlls / oleaut32 / typelib.c
bloba578c9b7ef8e7b2f8574b504fd32e0847c6e635e
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 *
9 * --------------------------------------------------------------------------------------
10 * Known problems (2000, Francois Jacques)
12 * - Tested using OLEVIEW (Platform SDK tool) only.
14 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
15 * creating by doing a straight copy of the dispinterface instance and just changing
16 * its typekind. Pointed structures aren't copied - only the address of the pointers.
17 * So when you release the dispinterface, you delete the vtable-interface structures
18 * as well... fortunately, clean up of structures is not implemented.
20 * - locale stuff is partially implemented but hasn't been tested.
22 * - typelib file is still read in its entirety, but it is released now.
23 * - some garbage is read from function names on some very rare occasions.
25 * --------------------------------------------------------------------------------------
26 * Known problems left from previous implementation (1999, Rein Klazes) :
28 * -. Data structures are straightforward, but slow for look-ups.
29 * -. (related) nothing is hashed
30 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
31 * of them I don't know yet how to implement them.
32 * -. Most error return values are just guessed not checked with windows
33 * behaviour.
34 * -. didn't bother with a c++ interface
35 * -. lousy fatal error handling
36 * -. some methods just return pointers to internal data structures, this is
37 * partly laziness, partly I want to check how windows does it.
41 #include "config.h"
43 #include <stdlib.h>
44 #include <string.h>
45 #include <stdio.h>
46 #include <ctype.h>
48 #include "winerror.h"
49 #include "winnls.h" /* for PRIMARYLANGID */
50 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
52 #include "wine/unicode.h"
53 #include "wine/obj_base.h"
54 #include "heap.h"
55 #include "ole2disp.h"
56 #include "typelib.h"
57 #include "debugtools.h"
58 #include "ntddk.h"
60 DEFAULT_DEBUG_CHANNEL(ole);
61 DECLARE_DEBUG_CHANNEL(typelib);
63 /****************************************************************************
64 * QueryPathOfRegTypeLib [TYPELIB.14]
66 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
67 * RETURNS
68 * path of typelib
70 HRESULT WINAPI
71 QueryPathOfRegTypeLib16(
72 REFGUID guid, /* [in] referenced guid */
73 WORD wMaj, /* [in] major version */
74 WORD wMin, /* [in] minor version */
75 LCID lcid, /* [in] locale id */
76 LPBSTR16 path /* [out] path of typelib */
77 ) {
78 char xguid[80];
79 char typelibkey[100],pathname[260];
80 DWORD plen;
82 TRACE("\n");
84 if (HIWORD(guid)) {
85 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
86 guid->Data1, guid->Data2, guid->Data3,
87 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
88 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
89 wMaj,wMin,lcid);
90 } else {
91 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
92 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
93 return E_FAIL;
95 plen = sizeof(pathname);
96 if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
97 /* try again without lang specific id */
98 if (SUBLANGID(lcid))
99 return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
100 FIXME("key %s not found\n",typelibkey);
101 return E_FAIL;
103 *path = SysAllocString16(pathname);
104 return S_OK;
107 /****************************************************************************
108 * QueryPathOfRegTypeLib [OLEAUT32.164]
109 * RETURNS
110 * path of typelib
112 HRESULT WINAPI
113 QueryPathOfRegTypeLib(
114 REFGUID guid, /* [in] referenced guid */
115 WORD wMaj, /* [in] major version */
116 WORD wMin, /* [in] minor version */
117 LCID lcid, /* [in] locale id */
118 LPBSTR path ) /* [out] path of typelib */
120 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
121 string termination character on output strings */
123 HRESULT hr = E_FAIL;
125 DWORD dwPathLen = _MAX_PATH;
126 LCID myLCID = lcid;
128 char szXGUID[80];
129 char szTypeLibKey[100];
130 char szPath[dwPathLen];
132 if ( !HIWORD(guid) )
134 sprintf(szXGUID,
135 "<guid 0x%08lx>",
136 (DWORD) guid);
138 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
139 return E_FAIL;
142 while (hr != S_OK)
144 sprintf(szTypeLibKey,
145 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
146 guid->Data1, guid->Data2, guid->Data3,
147 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
148 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
149 wMaj,
150 wMin,
151 myLCID);
153 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
155 if (!lcid)
156 break;
157 else if (myLCID == lcid)
159 /* try with sub-langid */
160 myLCID = SUBLANGID(lcid);
162 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
164 /* try with system langid */
165 myLCID = 0;
167 else
169 break;
172 else
174 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
175 BSTR bstrPath = SysAllocStringLen(NULL,len);
177 MultiByteToWideChar(CP_ACP,
178 MB_PRECOMPOSED,
179 szPath,
180 dwPathLen,
181 bstrPath,
182 len);
183 *path = bstrPath;
184 hr = S_OK;
188 if (hr != S_OK)
189 TRACE_(typelib)("%s not found\n", szTypeLibKey);
191 return hr;
194 /******************************************************************************
195 * CreateTypeLib [OLEAUT32.160] creates a typelib
197 * RETURNS
198 * Success: S_OK
199 * Failure: Status
201 HRESULT WINAPI CreateTypeLib(
202 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
204 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
205 return E_FAIL;
207 /******************************************************************************
208 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
209 * NOTES
210 * Docs: OLECHAR FAR* szFile
211 * Docs: iTypeLib FAR* FAR* pptLib
213 * RETURNS
214 * Success: S_OK
215 * Failure: Status
217 HRESULT WINAPI LoadTypeLib16(
218 LPOLESTR szFile, /* [in] Name of file to load from */
219 ITypeLib** pptLib) /* [out] Pointer to pointer to loaded type library */
221 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
223 if (pptLib!=0)
224 *pptLib=0;
226 return E_FAIL;
229 /******************************************************************************
230 * LoadTypeLib [OLEAUT32.161]
231 * Loads and registers a type library
232 * NOTES
233 * Docs: OLECHAR FAR* szFile
234 * Docs: iTypeLib FAR* FAR* pptLib
236 * RETURNS
237 * Success: S_OK
238 * Failure: Status
240 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
242 HRESULT WINAPI LoadTypeLib(
243 const OLECHAR *szFile,/* [in] Name of file to load from */
244 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
246 TRACE("\n");
247 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
250 /******************************************************************************
251 * LoadTypeLibEx [OLEAUT32.183]
252 * Loads and optionally registers a type library
254 * RETURNS
255 * Success: S_OK
256 * Failure: Status
258 HRESULT WINAPI LoadTypeLibEx(
259 LPCOLESTR szFile, /* [in] Name of file to load from */
260 REGKIND regkind, /* [in] Specify kind of registration */
261 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
263 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
264 const WCHAR *pFile, *pIndexStr;
265 HRESULT res;
266 INT index = 1;
267 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
269 pFile = szFile;
270 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
271 NULL)) {
273 /* Look for a trailing '\\' followed by an index */
274 pIndexStr = strrchrW(szFile, '\\');
275 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
276 index = wcstol(pIndexStr, NULL, 10);
277 memcpy(szFileCopy, szFile,
278 (pIndexStr - szFile - 1) * sizeof(WCHAR));
279 szFileCopy[pIndexStr - szFile - 1] = '\0';
280 pFile = szFileCopy;
281 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
282 szPath,NULL))
283 return TYPE_E_CANTLOADLIBRARY;
284 } else
285 return TYPE_E_CANTLOADLIBRARY;
288 TRACE("File %s index %d\n", debugstr_w(pFile), index);
290 res = TLB_ReadTypeLib(pFile, index, (ITypeLib2**)pptLib);
292 if (SUCCEEDED(res))
293 switch(regkind)
295 case REGKIND_DEFAULT:
296 /* FIXME: is this correct? */
297 if (!szFile || !szFile[0] ||
298 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
299 break;
300 /* else fall-through */
301 case REGKIND_REGISTER:
302 /* FIXME: Help path? */
303 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
305 IUnknown_Release(*pptLib);
306 *pptLib = 0;
308 break;
309 case REGKIND_NONE:
310 break;
313 TRACE(" returns %08lx\n",res);
314 return res;
317 /******************************************************************************
318 * LoadRegTypeLib [OLEAUT32.162]
320 HRESULT WINAPI LoadRegTypeLib(
321 REFGUID rguid, /* [in] referenced guid */
322 WORD wVerMajor, /* [in] major version */
323 WORD wVerMinor, /* [in] minor version */
324 LCID lcid, /* [in] locale id */
325 ITypeLib **ppTLib) /* [out] path of typelib */
327 BSTR bstr=NULL;
328 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
330 if(SUCCEEDED(res))
332 res= LoadTypeLib(bstr, ppTLib);
333 SysFreeString(bstr);
336 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
338 return res;
342 /******************************************************************************
343 * RegisterTypeLib [OLEAUT32.163]
344 * Adds information about a type library to the System Registry
345 * NOTES
346 * Docs: ITypeLib FAR * ptlib
347 * Docs: OLECHAR FAR* szFullPath
348 * Docs: OLECHAR FAR* szHelpDir
350 * RETURNS
351 * Success: S_OK
352 * Failure: Status
354 HRESULT WINAPI RegisterTypeLib(
355 ITypeLib * ptlib, /* [in] Pointer to the library*/
356 OLECHAR * szFullPath, /* [in] full Path of the library*/
357 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
358 may be NULL*/
360 HRESULT res;
361 TLIBATTR *attr;
362 OLECHAR guid[80];
363 LPSTR guidA;
364 CHAR keyName[120];
365 HKEY key, subKey;
366 UINT types, tidx;
367 TYPEKIND kind;
368 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
370 if (ptlib == NULL || szFullPath == NULL)
371 return E_INVALIDARG;
373 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
374 return E_FAIL;
376 StringFromGUID2(&attr->guid, guid, 80);
377 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
378 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
379 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
380 HeapFree(GetProcessHeap(), 0, guidA);
382 res = S_OK;
383 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
384 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
386 LPOLESTR doc;
388 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
390 if (RegSetValueExW(key, NULL, 0, REG_SZ,
391 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
392 res = E_FAIL;
394 SysFreeString(doc);
396 else
397 res = E_FAIL;
399 /* FIXME: This *seems* to be 0 always, not sure though */
400 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
401 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
403 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
404 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
405 res = E_FAIL;
407 RegCloseKey(subKey);
409 else
410 res = E_FAIL;
412 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
413 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
415 CHAR buf[20];
416 /* FIXME: is %u correct? */
417 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
418 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
419 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
420 res = E_FAIL;
422 RegCloseKey(key);
424 else
425 res = E_FAIL;
427 /* register OLE Automation-compatible interfaces for this typelib */
428 types = ITypeLib_GetTypeInfoCount(ptlib);
429 for (tidx=0; tidx<types; tidx++) {
430 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
431 LPOLESTR name = NULL;
432 ITypeInfo *tinfo = NULL;
433 BOOL stop = FALSE;
434 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
435 switch (kind) {
436 case TKIND_INTERFACE:
437 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
438 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
439 break;
440 case TKIND_DISPATCH:
441 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
442 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
443 break;
444 case TKIND_COCLASS:
445 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
446 /* coclasses should probably not be registered? */
447 break;
448 default:
449 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
450 break;
452 if (tinfo) {
453 TYPEATTR *tattr = NULL;
454 ITypeInfo_GetTypeAttr(tinfo, &tattr);
455 if (tattr) {
456 TRACE_(typelib)("guid=%s, flags=%04x\n",
457 debugstr_guid(&tattr->guid),
458 tattr->wTypeFlags);
459 if (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION) {
460 /* register interface<->typelib coupling */
461 StringFromGUID2(&tattr->guid, guid, 80);
462 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
463 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
464 HeapFree(GetProcessHeap(), 0, guidA);
466 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
467 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
468 if (name)
469 RegSetValueExW(key, NULL, 0, REG_SZ,
470 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
472 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
473 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
474 RegSetValueExA(subKey, NULL, 0, REG_SZ,
475 PSOA, strlen(PSOA));
476 RegCloseKey(subKey);
478 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
479 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
480 RegSetValueExA(subKey, NULL, 0, REG_SZ,
481 PSOA, strlen(PSOA));
482 RegCloseKey(subKey);
485 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
486 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
487 CHAR ver[32];
488 StringFromGUID2(&attr->guid, guid, 80);
489 snprintf(ver, sizeof(ver), "%x.%x",
490 attr->wMajorVerNum, attr->wMinorVerNum);
491 RegSetValueExW(subKey, NULL, 0, REG_SZ,
492 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
493 RegSetValueExA(subKey, "Version", 0, REG_SZ,
494 ver, lstrlenA(ver));
495 RegCloseKey(subKey);
497 RegCloseKey(key);
500 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
502 ITypeInfo_Release(tinfo);
504 SysFreeString(name);
505 if (stop) break;
509 ITypeLib_ReleaseTLibAttr(ptlib, attr);
511 return res;
515 /******************************************************************************
516 * UnRegisterTypeLib [OLEAUT32.186]
517 * Removes information about a type library from the System Registry
518 * NOTES
520 * RETURNS
521 * Success: S_OK
522 * Failure: Status
524 HRESULT WINAPI UnRegisterTypeLib(
525 REFGUID libid, /* [in] Guid of the library */
526 WORD wVerMajor, /* [in] major version */
527 WORD wVerMinor, /* [in] minor version */
528 LCID lcid, /* [in] locale id */
529 SYSKIND syskind)
531 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
532 return S_OK; /* FIXME: pretend everything is OK */
535 /****************************************************************************
536 * OaBuildVersion (TYPELIB.15)
538 * known TYPELIB.DLL versions:
540 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
541 * OLE 2.02 1993-94 02 3002
542 * OLE 2.03 23 730
543 * OLE 2.03 03 3025
544 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
545 * OLE 2.1 NT 1993-95 ?? ???
546 * OLE 2.3.1 W95 23 700
547 * OLE2 4.0 NT4SP6 1993-98 40 4277
549 DWORD WINAPI OaBuildVersion16(void)
551 /* FIXME: I'd like to return the highest currently known version value
552 * in case the user didn't force a --winver, but I don't know how
553 * to retrieve the "versionForced" info from misc/version.c :(
554 * (this would be useful in other places, too) */
555 FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
556 switch(GetVersion() & 0x8000ffff) /* mask off build number */
558 case 0x80000a03: /* WIN31 */
559 return MAKELONG(3027, 3); /* WfW 3.11 */
560 case 0x80000004: /* WIN95 */
561 return MAKELONG(700, 23); /* Win95A */
562 case 0x80000a04: /* WIN98 */
563 return MAKELONG(3024, 10); /* W98 SE */
564 case 0x00000004: /* NT4 */
565 return MAKELONG(4277, 40); /* NT4 SP6 */
566 default:
567 FIXME("Version value not known yet. Please investigate it!\n");
568 return 0;
572 /* for better debugging info leave the static out for the time being */
573 #define static
575 /*======================= ITypeLib implementation =======================*/
577 typedef struct tagTLBCustData
579 GUID guid;
580 VARIANT data;
581 struct tagTLBCustData* next;
582 } TLBCustData;
584 /* data structure for import typelibs */
585 typedef struct tagTLBImpLib
587 int offset; /* offset in the file (MSFT)
588 offset in nametable (SLTG)
589 just used to identify library while reading
590 data from file */
591 GUID guid; /* libid */
592 BSTR name; /* name */
594 LCID lcid; /* lcid of imported typelib */
596 WORD wVersionMajor; /* major version number */
597 WORD wVersionMinor; /* minor version number */
599 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
600 NULL if not yet loaded */
601 struct tagTLBImpLib * next;
602 } TLBImpLib;
604 /* internal ITypeLib data */
605 typedef struct tagITypeLibImpl
607 ICOM_VFIELD(ITypeLib2);
608 UINT ref;
609 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
611 /* strings can be stored in tlb as multibyte strings BUT they are *always*
612 * exported to the application as a UNICODE string.
614 BSTR Name;
615 BSTR DocString;
616 BSTR HelpFile;
617 BSTR HelpStringDll;
618 unsigned long dwHelpContext;
619 int TypeInfoCount; /* nr of typeinfo's in librarry */
620 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
621 int ctCustData; /* number of items in cust data list */
622 TLBCustData * pCustData; /* linked list to cust data */
623 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
624 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
625 libary. Only used while read MSFT
626 typelibs */
627 } ITypeLibImpl;
629 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
631 /* ITypeLib methods */
632 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
633 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
635 /*======================= ITypeInfo implementation =======================*/
637 /* data for refernced types */
638 typedef struct tagTLBRefType
640 INT index; /* Type index for internal ref or for external ref
641 it the format is SLTG. -2 indicates to
642 use guid */
644 GUID guid; /* guid of the referenced type */
645 /* if index == TLB_REF_USE_GUID */
647 HREFTYPE reference; /* The href of this ref */
648 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
649 TLB_REF_INTERNAL for internal refs
650 TLB_REF_NOT_FOUND for broken refs */
652 struct tagTLBRefType * next;
653 } TLBRefType;
655 #define TLB_REF_USE_GUID -2
657 #define TLB_REF_INTERNAL (void*)-2
658 #define TLB_REF_NOT_FOUND (void*)-1
660 /* internal Parameter data */
661 typedef struct tagTLBParDesc
663 BSTR Name;
664 int ctCustData;
665 TLBCustData * pCustData; /* linked list to cust data */
666 } TLBParDesc;
668 /* internal Function data */
669 typedef struct tagTLBFuncDesc
671 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
672 BSTR Name; /* the name of this function */
673 TLBParDesc *pParamDesc; /* array with param names and custom data */
674 int helpcontext;
675 int HelpStringContext;
676 BSTR HelpString;
677 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
678 int ctCustData;
679 TLBCustData * pCustData; /* linked list to cust data; */
680 struct tagTLBFuncDesc * next;
681 } TLBFuncDesc;
683 /* internal Variable data */
684 typedef struct tagTLBVarDesc
686 VARDESC vardesc; /* lots of info on the variable and its attributes. */
687 BSTR Name; /* the name of this variable */
688 int HelpContext;
689 int HelpStringContext; /* fixme: where? */
690 BSTR HelpString;
691 int ctCustData;
692 TLBCustData * pCustData;/* linked list to cust data; */
693 struct tagTLBVarDesc * next;
694 } TLBVarDesc;
696 /* internal implemented interface data */
697 typedef struct tagTLBImplType
699 HREFTYPE hRef; /* hRef of interface */
700 int implflags; /* IMPLFLAG_*s */
701 int ctCustData;
702 TLBCustData * pCustData;/* linked list to custom data; */
703 struct tagTLBImplType *next;
704 } TLBImplType;
706 /* internal TypeInfo data */
707 typedef struct tagITypeInfoImpl
709 ICOM_VFIELD(ITypeInfo2);
710 UINT ref;
711 TYPEATTR TypeAttr ; /* _lots_ of type information. */
712 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
713 int index; /* index in this typelib; */
714 /* type libs seem to store the doc strings in ascii
715 * so why should we do it in unicode?
717 BSTR Name;
718 BSTR DocString;
719 unsigned long dwHelpContext;
720 unsigned long dwHelpStringContext;
722 /* functions */
723 TLBFuncDesc * funclist; /* linked list with function descriptions */
725 /* variables */
726 TLBVarDesc * varlist; /* linked list with variable descriptions */
728 /* Implemented Interfaces */
729 TLBImplType * impltypelist;
731 TLBRefType * reflist;
732 int ctCustData;
733 TLBCustData * pCustData; /* linked list to cust data; */
734 struct tagITypeInfoImpl * next;
735 } ITypeInfoImpl;
737 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
739 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
741 typedef struct tagTLBContext
743 unsigned int oStart; /* start of TLB in file */
744 unsigned int pos; /* current pos */
745 unsigned int length; /* total length */
746 void *mapping; /* memory mapping */
747 MSFT_SegDir * pTblDir;
748 ITypeLibImpl* pLibInfo;
749 } TLBContext;
752 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
755 debug
757 static void dump_VarType(VARTYPE vt,char *szVarType) {
758 /* FIXME : we could have better trace here, depending on the VARTYPE
759 * of the variant
761 switch(vt) {
762 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
763 case VT_I2: sprintf(szVarType, "VT_I2"); break;
764 case VT_I4: sprintf(szVarType, "VT_I4"); break;
765 case VT_R4: sprintf(szVarType, "VT_R4"); break;
766 case VT_R8: sprintf(szVarType, "VT_R8"); break;
767 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
768 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
769 case VT_CY: sprintf(szVarType, "VT_CY"); break;
770 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
771 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
772 case VT_BYREF: case VT_UNKNOWN: sprintf(szVarType, "VT_BYREF"); break;
773 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
774 case VT_ARRAY: sprintf(szVarType, "VT_ARRAY"); break;
775 case VT_I1: sprintf(szVarType, "VT_I1"); break;
776 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
777 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
778 case VT_INT: sprintf(szVarType, "VT_INT"); break;
779 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
780 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
781 default: sprintf(szVarType, "unknown");break;
785 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
786 switch(pTD->vt) {
787 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
788 case VT_I2: sprintf(szVarType, "VT_I2"); break;
789 case VT_I4: sprintf(szVarType, "VT_I4"); break;
790 case VT_R4: sprintf(szVarType, "VT_R4"); break;
791 case VT_R8: sprintf(szVarType, "VT_R8"); break;
792 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
793 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
794 case VT_CY: sprintf(szVarType, "VT_CY"); break;
795 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
796 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
797 case VT_BYREF: case VT_UNKNOWN: sprintf(szVarType, "VT_BYREF"); break;
798 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
799 case VT_ARRAY: sprintf(szVarType, "VT_ARRAY"); break;
800 case VT_I1: sprintf(szVarType, "VT_I1"); break;
801 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
802 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
803 case VT_INT: sprintf(szVarType, "VT_INT"); break;
804 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
805 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
806 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
807 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
808 pTD->u.hreftype); break;
809 case VT_PTR: sprintf(szVarType, "ptr to ");
810 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
811 break;
812 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
813 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
814 break;
815 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
816 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
817 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
818 break;
820 default: sprintf(szVarType, "unknown");break;
824 static void dump_ELEMDESC(ELEMDESC *edesc) {
825 char buf[200];
826 dump_TypeDesc(&edesc->tdesc,buf);
827 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
828 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
829 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
831 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
832 int i;
833 MESSAGE("memid is %08lx\n",funcdesc->memid);
834 for (i=0;i<funcdesc->cParams;i++) {
835 MESSAGE("Param %d:\n",i);
836 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
838 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
839 switch (funcdesc->funckind) {
840 case FUNC_VIRTUAL: MESSAGE("virtual");break;
841 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
842 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
843 case FUNC_STATIC: MESSAGE("static");break;
844 case FUNC_DISPATCH: MESSAGE("dispatch");break;
845 default: MESSAGE("unknown");break;
847 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
848 switch (funcdesc->invkind) {
849 case INVOKE_FUNC: MESSAGE("func");break;
850 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
851 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
852 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
854 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
855 switch (funcdesc->callconv) {
856 case CC_CDECL: MESSAGE("cdecl");break;
857 case CC_PASCAL: MESSAGE("pascal");break;
858 case CC_STDCALL: MESSAGE("stdcall");break;
859 case CC_SYSCALL: MESSAGE("syscall");break;
860 default:break;
862 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
863 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
864 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
866 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
868 int i;
869 if (!TRACE_ON(typelib))
870 return;
871 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
872 for (i=0;i<pfd->funcdesc.cParams;i++)
873 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
876 dump_FUNCDESC(&(pfd->funcdesc));
878 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
879 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
881 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
883 while (pfd)
885 dump_TLBFuncDescOne(pfd);
886 pfd = pfd->next;
889 static void dump_TLBVarDesc(TLBVarDesc * pvd)
891 while (pvd)
893 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
894 pvd = pvd->next;
898 static void dump_TLBImpLib(TLBImpLib *import)
900 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
901 debugstr_w(import->name));
902 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
903 import->wVersionMinor, import->lcid, import->offset);
906 static void dump_TLBRefType(TLBRefType * prt)
908 while (prt)
910 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
911 if(prt->index == -1)
912 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
913 else
914 TRACE_(typelib)("type no: %d\n", prt->index);
916 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
917 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
918 TRACE_(typelib)("in lib\n");
919 dump_TLBImpLib(prt->pImpTLInfo);
921 prt = prt->next;
925 static void dump_TLBImplType(TLBImplType * impl)
927 while (impl) {
928 TRACE_(typelib)(
929 "implementing/inheriting interface hRef = %lx implflags %x\n",
930 impl->hRef, impl->implflags);
931 impl = impl->next;
935 static void dump_Variant(VARIANT * pvar)
937 char szVarType[15];
939 TRACE("(%p)\n", pvar);
941 if (!pvar) return;
943 ZeroMemory(szVarType, sizeof(szVarType));
945 /* FIXME : we could have better trace here, depending on the VARTYPE
946 * of the variant
948 dump_VarType(V_VT(pvar),szVarType);
950 TRACE("VARTYPE: %s\n", szVarType);
952 switch (V_VT(pvar))
954 case VT_R4:
955 TRACE("%3.3e\n", V_UNION(pvar, fltVal));
956 break;
958 case VT_R8:
959 TRACE("%3.3e\n", V_UNION(pvar, dblVal));
960 break;
962 default:
963 TRACE("%ld\n", V_UNION(pvar, lVal));
964 break;
967 if (V_VT(pvar) & VT_BYREF)
968 return dump_Variant(V_UNION(pvar,pvarVal));
971 static void dump_DispParms(DISPPARAMS * pdp)
973 int index = 0;
975 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
977 while (index < pdp->cArgs)
979 dump_Variant( &pdp->rgvarg[index] );
980 ++index;
984 static char * typekind_desc[] =
986 "TKIND_ENUM",
987 "TKIND_RECORD",
988 "TKIND_MODULE",
989 "TKIND_INTERFACE",
990 "TKIND_DISPATCH",
991 "TKIND_COCLASS",
992 "TKIND_ALIAS",
993 "TKIND_UNION",
994 "TKIND_MAX"
997 static void dump_TypeInfo(ITypeInfoImpl * pty)
999 TRACE("%p ref=%u\n", pty, pty->ref);
1000 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1001 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1002 TRACE("fct:%u var:%u impl:%u\n",
1003 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1004 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1005 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1006 dump_TLBFuncDesc(pty->funclist);
1007 dump_TLBVarDesc(pty->varlist);
1008 dump_TLBImplType(pty->impltypelist);
1011 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1013 /* VT_LPWSTR is largest type that */
1014 /* may appear in type description*/
1015 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1016 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1017 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1018 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1019 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1020 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1021 {{0},30},{{0},31}
1024 static void TLB_abort()
1026 DebugBreak();
1028 static void * TLB_Alloc(unsigned size)
1030 void * ret;
1031 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1032 /* FIXME */
1033 ERR("cannot allocate memory\n");
1035 return ret;
1038 static void TLB_Free(void * ptr)
1040 HeapFree(GetProcessHeap(), 0, ptr);
1044 /**********************************************************************
1046 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1048 /* read function */
1049 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1051 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1052 pcx->pos, count, pcx->oStart, pcx->length, where);
1054 if (where != DO_NOT_SEEK)
1056 where += pcx->oStart;
1057 if (where > pcx->length)
1059 /* FIXME */
1060 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1061 TLB_abort();
1063 pcx->pos = where;
1065 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1066 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1067 pcx->pos += count;
1068 return count;
1071 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1073 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1075 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1076 memset(pGuid,0, sizeof(GUID));
1077 return;
1079 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1082 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1084 char * name;
1085 MSFT_NameIntro niName;
1086 int lengthInChars;
1087 WCHAR* pwstring = NULL;
1088 BSTR bstrName = NULL;
1090 MSFT_Read(&niName, sizeof(niName), pcx,
1091 pcx->pTblDir->pNametab.offset+offset);
1092 niName.namelen &= 0xFF; /* FIXME: correct ? */
1093 name=TLB_Alloc((niName.namelen & 0xff) +1);
1094 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1095 name[niName.namelen & 0xff]='\0';
1097 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1098 name, -1, NULL, 0);
1100 /* no invalid characters in string */
1101 if (lengthInChars)
1103 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1105 /* don't check for invalid character since this has been done previously */
1106 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1108 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1109 lengthInChars = SysStringLen(bstrName);
1110 HeapFree(GetProcessHeap(), 0, pwstring);
1113 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1114 return bstrName;
1117 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1119 char * string;
1120 INT16 length;
1121 int lengthInChars;
1122 BSTR bstr = NULL;
1124 if(offset<0) return NULL;
1125 MSFT_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1126 if(length <= 0) return 0;
1127 string=TLB_Alloc(length +1);
1128 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1129 string[length]='\0';
1131 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1132 string, -1, NULL, 0);
1134 /* no invalid characters in string */
1135 if (lengthInChars)
1137 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1139 /* don't check for invalid character since this has been done previously */
1140 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1142 bstr = SysAllocStringLen(pwstring, lengthInChars);
1143 lengthInChars = SysStringLen(bstr);
1144 HeapFree(GetProcessHeap(), 0, pwstring);
1147 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1148 return bstr;
1151 * read a value and fill a VARIANT structure
1153 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1155 int size;
1157 TRACE_(typelib)("\n");
1159 if(offset <0) { /* data are packed in here */
1160 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1161 V_UNION(pVar, iVal) = offset & 0xffff;
1162 return;
1164 MSFT_Read(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1165 pcx->pTblDir->pCustData.offset + offset );
1166 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1167 switch (V_VT(pVar)){
1168 case VT_EMPTY: /* FIXME: is this right? */
1169 case VT_NULL: /* FIXME: is this right? */
1170 case VT_I2 : /* this should not happen */
1171 case VT_I4 :
1172 case VT_R4 :
1173 case VT_ERROR :
1174 case VT_BOOL :
1175 case VT_I1 :
1176 case VT_UI1 :
1177 case VT_UI2 :
1178 case VT_UI4 :
1179 case VT_INT :
1180 case VT_UINT :
1181 case VT_VOID : /* FIXME: is this right? */
1182 case VT_HRESULT :
1183 size=4; break;
1184 case VT_R8 :
1185 case VT_CY :
1186 case VT_DATE :
1187 case VT_I8 :
1188 case VT_UI8 :
1189 case VT_DECIMAL : /* FIXME: is this right? */
1190 case VT_FILETIME :
1191 size=8;break;
1192 /* pointer types with known behaviour */
1193 case VT_BSTR :{
1194 char * ptr;
1195 MSFT_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1196 if(size <= 0) {
1197 FIXME("BSTR length = %d?\n", size);
1198 } else {
1199 ptr=TLB_Alloc(size);/* allocate temp buffer */
1200 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1201 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1202 /* FIXME: do we need a AtoW conversion here? */
1203 V_UNION(pVar, bstrVal[size])=L'\0';
1204 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1205 TLB_Free(ptr);
1208 size=-4; break;
1209 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1210 case VT_DISPATCH :
1211 case VT_VARIANT :
1212 case VT_UNKNOWN :
1213 case VT_PTR :
1214 case VT_SAFEARRAY :
1215 case VT_CARRAY :
1216 case VT_USERDEFINED :
1217 case VT_LPSTR :
1218 case VT_LPWSTR :
1219 case VT_BLOB :
1220 case VT_STREAM :
1221 case VT_STORAGE :
1222 case VT_STREAMED_OBJECT :
1223 case VT_STORED_OBJECT :
1224 case VT_BLOB_OBJECT :
1225 case VT_CF :
1226 case VT_CLSID :
1227 default:
1228 size=0;
1229 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1230 V_VT(pVar));
1233 if(size>0) /* (big|small) endian correct? */
1234 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1235 return;
1238 * create a linked list with custom data
1240 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1242 MSFT_CDGuid entry;
1243 TLBCustData* pNew;
1244 int count=0;
1246 TRACE_(typelib)("\n");
1248 while(offset >=0){
1249 count++;
1250 pNew=TLB_Alloc(sizeof(TLBCustData));
1251 MSFT_Read(&entry, sizeof(entry), pcx,
1252 pcx->pTblDir->pCDGuids.offset+offset);
1253 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1254 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1255 /* add new custom data at head of the list */
1256 pNew->next=*ppCustData;
1257 *ppCustData=pNew;
1258 offset = entry.next;
1260 return count;
1263 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1264 ITypeInfoImpl *pTI)
1266 if(type <0)
1267 pTd->vt=type & VT_TYPEMASK;
1268 else
1269 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1271 if(pTd->vt == VT_USERDEFINED)
1272 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1274 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1277 static void
1278 MSFT_DoFuncs(TLBContext* pcx,
1279 ITypeInfoImpl* pTI,
1280 int cFuncs,
1281 int cVars,
1282 int offset,
1283 TLBFuncDesc** pptfd)
1286 * member information is stored in a data structure at offset
1287 * indicated by the memoffset field of the typeinfo structure
1288 * There are several distinctive parts.
1289 * the first part starts with a field that holds the total length
1290 * of this (first) part excluding this field. Then follow the records,
1291 * for each member there is one record.
1293 * First entry is always the length of the record (excluding this
1294 * length word).
1295 * Rest of the record depends on the type of the member. If there is
1296 * a field indicating the member type (function variable intereface etc)
1297 * I have not found it yet. At this time we depend on the information
1298 * in the type info and the usual order how things are stored.
1300 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1301 * for each member;
1303 * Third is a equal sized array with file offsets to the name entry
1304 * of each member.
1306 * Forth and last (?) part is an array with offsets to the records in the
1307 * first part of this file segment.
1310 int infolen, nameoffset, reclength, nrattributes, i;
1311 int recoffset = offset + sizeof(INT);
1313 char recbuf[512];
1314 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1316 TRACE_(typelib)("\n");
1318 MSFT_Read(&infolen, sizeof(INT), pcx, offset);
1320 for ( i = 0; i < cFuncs ; i++ )
1322 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1324 /* name, eventually add to a hash table */
1325 MSFT_Read(&nameoffset,
1326 sizeof(INT),
1327 pcx,
1328 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1330 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1332 /* read the function information record */
1333 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1335 reclength &= 0x1ff;
1337 MSFT_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1339 /* do the attributes */
1340 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1341 / sizeof(int);
1343 if ( nrattributes > 0 )
1345 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1347 if ( nrattributes > 1 )
1349 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1350 pFuncRec->OptAttr[1]) ;
1352 if ( nrattributes > 2 )
1354 if ( pFuncRec->FKCCIC & 0x2000 )
1356 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1358 else
1360 (*pptfd)->Entry = MSFT_ReadString(pcx,
1361 pFuncRec->OptAttr[2]);
1363 if( nrattributes > 5 )
1365 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1367 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1369 MSFT_CustData(pcx,
1370 pFuncRec->OptAttr[6],
1371 &(*pptfd)->pCustData);
1378 /* fill the FuncDesc Structure */
1379 MSFT_Read( & (*pptfd)->funcdesc.memid,
1380 sizeof(INT), pcx,
1381 offset + infolen + ( i + 1) * sizeof(INT));
1383 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1384 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1385 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1386 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1387 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1388 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1389 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1391 MSFT_GetTdesc(pcx,
1392 pFuncRec->DataType,
1393 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1394 pTI);
1396 /* do the parameters/arguments */
1397 if(pFuncRec->nrargs)
1399 int j = 0;
1400 MSFT_ParameterInfo paraminfo;
1402 (*pptfd)->funcdesc.lprgelemdescParam =
1403 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1405 (*pptfd)->pParamDesc =
1406 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1408 MSFT_Read(&paraminfo,
1409 sizeof(paraminfo),
1410 pcx,
1411 recoffset + reclength -
1412 pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1414 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1416 TYPEDESC* lpArgTypeDesc = 0;
1418 MSFT_GetTdesc(pcx,
1419 paraminfo.DataType,
1420 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1421 pTI);
1423 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1425 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1427 /* SEEK value = jump to offset,
1428 * from there jump to the end of record,
1429 * go back by (j-1) arguments
1431 MSFT_Read( &paraminfo ,
1432 sizeof(MSFT_ParameterInfo), pcx,
1433 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1434 * sizeof(MSFT_ParameterInfo)));
1435 lpArgTypeDesc =
1436 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1438 while ( lpArgTypeDesc != NULL )
1440 switch ( lpArgTypeDesc->vt )
1442 case VT_PTR:
1443 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1444 break;
1446 case VT_CARRAY:
1447 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1448 break;
1450 case VT_USERDEFINED:
1451 MSFT_DoRefType(pcx, pTI,
1452 lpArgTypeDesc->u.hreftype);
1454 lpArgTypeDesc = NULL;
1455 break;
1457 default:
1458 lpArgTypeDesc = NULL;
1464 /* parameter is the return value! */
1465 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1467 TYPEDESC* lpArgTypeDesc;
1469 (*pptfd)->funcdesc.elemdescFunc =
1470 (*pptfd)->funcdesc.lprgelemdescParam[j];
1472 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1474 while ( lpArgTypeDesc != NULL )
1476 switch ( lpArgTypeDesc->vt )
1478 case VT_PTR:
1479 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1480 break;
1481 case VT_CARRAY:
1482 lpArgTypeDesc =
1483 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1485 break;
1487 case VT_USERDEFINED:
1488 MSFT_DoRefType(pcx,
1489 pTI,
1490 lpArgTypeDesc->u.hreftype);
1492 lpArgTypeDesc = NULL;
1493 break;
1495 default:
1496 lpArgTypeDesc = NULL;
1501 /* second time around */
1502 for(j=0;j<pFuncRec->nrargs;j++)
1504 /* name */
1505 (*pptfd)->pParamDesc[j].Name =
1506 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1508 /* default value */
1509 if ( (PARAMFLAG_FHASDEFAULT &
1510 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1511 ((pFuncRec->FKCCIC) & 0x1000) )
1513 INT* pInt = (INT *)((char *)pFuncRec +
1514 reclength -
1515 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1517 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1519 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1520 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1522 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1523 pInt[j], pcx);
1525 /* custom info */
1526 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1528 MSFT_CustData(pcx,
1529 pFuncRec->OptAttr[7+j],
1530 &(*pptfd)->pParamDesc[j].pCustData);
1535 /* scode is not used: archaic win16 stuff FIXME: right? */
1536 (*pptfd)->funcdesc.cScodes = 0 ;
1537 (*pptfd)->funcdesc.lprgscode = NULL ;
1539 pptfd = & ((*pptfd)->next);
1540 recoffset += reclength;
1543 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1544 int cVars, int offset, TLBVarDesc ** pptvd)
1546 int infolen, nameoffset, reclength;
1547 char recbuf[256];
1548 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1549 int i;
1550 int recoffset;
1552 TRACE_(typelib)("\n");
1554 MSFT_Read(&infolen,sizeof(INT), pcx, offset);
1555 MSFT_Read(&recoffset,sizeof(INT), pcx, offset + infolen +
1556 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1557 recoffset += offset+sizeof(INT);
1558 for(i=0;i<cVars;i++){
1559 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1560 /* name, eventually add to a hash table */
1561 MSFT_Read(&nameoffset, sizeof(INT), pcx,
1562 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1563 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1564 /* read the variable information record */
1565 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1566 reclength &=0xff;
1567 MSFT_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1568 /* Optional data */
1569 if(reclength >(6*sizeof(INT)) )
1570 (*pptvd)->HelpContext=pVarRec->HelpContext;
1571 if(reclength >(7*sizeof(INT)) )
1572 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1573 if(reclength >(8*sizeof(INT)) )
1574 if(reclength >(9*sizeof(INT)) )
1575 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1576 /* fill the VarDesc Structure */
1577 MSFT_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1578 offset + infolen + ( i + 1) * sizeof(INT));
1579 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1580 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1581 MSFT_GetTdesc(pcx, pVarRec->DataType,
1582 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1583 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) fixme?? */
1584 if(pVarRec->VarKind == VAR_CONST ){
1585 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1586 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1587 pVarRec->OffsValue, pcx);
1588 } else
1589 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1590 pptvd=&((*pptvd)->next);
1591 recoffset += reclength;
1594 /* fill in data for a hreftype (offset). When the refernced type is contained
1595 * in the typelib, it's just an (file) offset in the type info base dir.
1596 * If comes from import, it's an offset+1 in the ImpInfo table
1597 * */
1598 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1599 int offset)
1601 int j;
1602 TLBRefType **ppRefType = &pTI->reflist;
1604 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1606 while(*ppRefType) {
1607 if((*ppRefType)->reference == offset)
1608 return;
1609 ppRefType = &(*ppRefType)->next;
1612 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1613 sizeof(**ppRefType));
1615 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1616 /* external typelib */
1617 MSFT_ImpInfo impinfo;
1618 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1620 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1622 MSFT_Read(&impinfo, sizeof(impinfo), pcx,
1623 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1624 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1625 if(pImpLib->offset==impinfo.oImpFile) break;
1626 pImpLib=pImpLib->next;
1628 if(pImpLib){
1629 (*ppRefType)->reference=offset;
1630 (*ppRefType)->pImpTLInfo = pImpLib;
1631 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1632 (*ppRefType)->index = TLB_REF_USE_GUID;
1633 }else{
1634 ERR("Cannot find a reference\n");
1635 (*ppRefType)->reference=-1;
1636 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1638 }else{
1639 /* in this typelib */
1640 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1641 (*ppRefType)->reference=offset;
1642 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1646 /* process Implemented Interfaces of a com class */
1647 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1648 int offset)
1650 int i;
1651 MSFT_RefRecord refrec;
1652 TLBImplType **ppImpl = &pTI->impltypelist;
1654 TRACE_(typelib)("\n");
1656 for(i=0;i<count;i++){
1657 if(offset<0) break; /* paranoia */
1658 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1659 MSFT_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1660 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1661 (*ppImpl)->hRef = refrec.reftype;
1662 (*ppImpl)->implflags=refrec.flags;
1663 (*ppImpl)->ctCustData=
1664 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1665 offset=refrec.onext;
1666 ppImpl=&((*ppImpl)->next);
1670 * process a typeinfo record
1672 ITypeInfoImpl * MSFT_DoTypeInfo(
1673 TLBContext *pcx,
1674 int count,
1675 ITypeLibImpl * pLibInfo)
1677 MSFT_TypeInfoBase tiBase;
1678 ITypeInfoImpl *ptiRet;
1680 TRACE_(typelib)("count=%u\n", count);
1682 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1683 MSFT_Read(&tiBase, sizeof(tiBase) ,pcx ,
1684 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1685 /* this is where we are coming from */
1686 ptiRet->pTypeLib = pLibInfo;
1687 ptiRet->index=count;
1688 /* fill in the typeattr fields */
1689 FIXME("Assign constructor/destructor memid\n");
1691 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1692 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1693 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1694 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1695 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1696 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1697 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1698 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1699 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1700 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1701 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1702 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1703 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1704 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1705 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1706 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1707 MSFT_GetTdesc(pcx, tiBase.datatype1,
1708 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1710 /* FIXME: */
1711 /* IDLDESC idldescType; *//* never saw this one != zero */
1713 /* name, eventually add to a hash table */
1714 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1715 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1716 /* help info */
1717 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1718 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1719 ptiRet->dwHelpContext=tiBase.helpcontext;
1720 /* note: InfoType's Help file and HelpStringDll come from the containing
1721 * library. Further HelpString and Docstring appear to be the same thing :(
1723 /* functions */
1724 if(ptiRet->TypeAttr.cFuncs >0 )
1725 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1726 ptiRet->TypeAttr.cVars,
1727 tiBase.memoffset, & ptiRet->funclist);
1728 /* variables */
1729 if(ptiRet->TypeAttr.cVars >0 )
1730 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1731 ptiRet->TypeAttr.cVars,
1732 tiBase.memoffset, & ptiRet->varlist);
1733 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1734 switch(ptiRet->TypeAttr.typekind)
1736 case TKIND_COCLASS:
1737 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1738 tiBase.datatype1);
1739 break;
1740 case TKIND_DISPATCH:
1741 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1743 if (tiBase.datatype1 != -1)
1745 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1746 ptiRet->impltypelist->hRef = tiBase.datatype1;
1748 else
1749 { /* FIXME: This is a really bad hack to add IDispatch */
1750 char* szStdOle = "stdole2.tlb\0";
1751 int nStdOleLen = strlen(szStdOle);
1752 TLBRefType **ppRef = &ptiRet->reflist;
1754 while(*ppRef) {
1755 if((*ppRef)->reference == -1)
1756 break;
1757 ppRef = &(*ppRef)->next;
1759 if(!*ppRef) {
1760 *ppRef = TLB_Alloc(sizeof(**ppRef));
1761 (*ppRef)->guid = IID_IDispatch;
1762 (*ppRef)->reference = -1;
1763 (*ppRef)->index = TLB_REF_USE_GUID;
1764 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1765 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1766 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1767 nStdOleLen + 1);
1769 MultiByteToWideChar(CP_ACP,
1770 MB_PRECOMPOSED,
1771 szStdOle,
1773 (*ppRef)->pImpTLInfo->name,
1774 SysStringLen((*ppRef)->pImpTLInfo->name));
1776 (*ppRef)->pImpTLInfo->lcid = 0;
1777 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1778 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1781 break;
1782 default:
1783 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1784 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1785 ptiRet->impltypelist->hRef = tiBase.datatype1;
1786 break;
1789 ptiRet->ctCustData=
1790 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1792 TRACE_(typelib)("%s guid: %s kind:%s\n",
1793 debugstr_w(ptiRet->Name),
1794 debugstr_guid(&ptiRet->TypeAttr.guid),
1795 typekind_desc[ptiRet->TypeAttr.typekind]);
1797 return ptiRet;
1800 /****************************************************************************
1801 * TLB_ReadTypeLib
1803 * find the type of the typelib file and map the typelib resource into
1804 * the memory
1806 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1807 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1808 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1810 int ret = TYPE_E_CANTLOADLIBRARY;
1811 DWORD dwSignature = 0;
1812 HFILE hFile;
1814 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1816 *ppTypeLib = NULL;
1818 /* check the signature of the file */
1819 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1820 if (INVALID_HANDLE_VALUE != hFile)
1822 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1823 if (hMapping)
1825 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1826 if(pBase)
1828 /* retrieve file size */
1829 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1831 /* first try to load as *.tlb */
1832 dwSignature = *((DWORD*) pBase);
1833 if ( dwSignature == MSFT_SIGNATURE)
1835 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1837 else if ( dwSignature == SLTG_SIGNATURE)
1839 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1841 UnmapViewOfFile(pBase);
1843 CloseHandle(hMapping);
1845 CloseHandle(hFile);
1848 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1850 /* find the typelibrary resource*/
1851 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
1852 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1853 if (hinstDLL)
1855 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
1856 "TYPELIB");
1857 if (hrsrc)
1859 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1860 if (hGlobal)
1862 LPVOID pBase = LockResource(hGlobal);
1863 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1865 if (pBase)
1867 /* try to load as incore resource */
1868 dwSignature = *((DWORD*) pBase);
1869 if ( dwSignature == MSFT_SIGNATURE)
1871 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1873 else if ( dwSignature == SLTG_SIGNATURE)
1875 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1877 else
1879 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
1882 FreeResource( hGlobal );
1885 FreeLibrary(hinstDLL);
1889 if(*ppTypeLib)
1890 ret = S_OK;
1891 else
1892 ERR("Loading of typelib %s failed with error 0x%08lx\n",
1893 debugstr_w(pszFileName), GetLastError());
1895 return ret;
1898 /*================== ITypeLib(2) Methods ===================================*/
1900 /****************************************************************************
1901 * ITypeLib2_Constructor_MSFT
1903 * loading an MSFT typelib from an in-memory image
1905 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
1907 TLBContext cx;
1908 long lPSegDir;
1909 MSFT_Header tlbHeader;
1910 MSFT_SegDir tlbSegDir;
1911 ITypeLibImpl * pTypeLibImpl;
1913 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
1915 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
1916 if (!pTypeLibImpl) return NULL;
1918 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
1919 pTypeLibImpl->ref = 1;
1921 /* get pointer to beginning of typelib data */
1922 cx.pos = 0;
1923 cx.oStart=0;
1924 cx.mapping = pLib;
1925 cx.pLibInfo = pTypeLibImpl;
1926 cx.length = dwTLBLength;
1928 /* read header */
1929 MSFT_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
1930 TRACE("header:\n");
1931 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
1932 if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
1933 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
1934 return NULL;
1936 /* there is a small amount of information here until the next important
1937 * part:
1938 * the segment directory . Try to calculate the amount of data */
1939 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
1941 /* now read the segment directory */
1942 TRACE("read segment directory (at %ld)\n",lPSegDir);
1943 MSFT_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
1944 cx.pTblDir = &tlbSegDir;
1946 /* just check two entries */
1947 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
1949 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
1950 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
1951 return NULL;
1954 /* now fill our internal data */
1955 /* TLIBATTR fields */
1956 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
1957 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;
1958 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
1959 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
1960 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
1961 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
1963 /* name, eventually add to a hash table */
1964 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
1966 /* help info */
1967 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
1968 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
1970 if( tlbHeader.varflags & HELPDLLFLAG)
1972 int offset;
1973 MSFT_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
1974 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
1977 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
1979 /* custom data */
1980 if(tlbHeader.CustomDataOffset >= 0)
1982 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
1985 /* fill in typedescriptions */
1986 if(tlbSegDir.pTypdescTab.length > 0)
1988 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
1989 INT16 td[4];
1990 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
1991 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
1992 for(i=0; i<cTD; )
1994 /* FIXME: add several sanity checks here */
1995 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
1996 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
1998 /* FIXME: check safearray */
1999 if(td[3] < 0)
2000 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2001 else
2002 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2004 else if(td[0] == VT_CARRAY)
2006 /* array descr table here */
2007 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2009 else if(td[0] == VT_USERDEFINED)
2011 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2013 if(++i<cTD) MSFT_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
2016 /* second time around to fill the array subscript info */
2017 for(i=0;i<cTD;i++)
2019 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2020 if(tlbSegDir.pArrayDescriptions.offset>0)
2022 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2023 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2025 if(td[1]<0)
2026 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2027 else
2028 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2030 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2032 for(j = 0; j<td[2]; j++)
2034 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2035 sizeof(INT), &cx, DO_NOT_SEEK);
2036 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2037 sizeof(INT), &cx, DO_NOT_SEEK);
2040 else
2042 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2043 ERR("didn't find array description data\n");
2048 /* imported type libs */
2049 if(tlbSegDir.pImpFiles.offset>0)
2051 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2052 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2053 UINT16 size;
2055 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2057 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2058 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2059 MSFT_Read(&oGuid, sizeof(INT), &cx, offset);
2061 MSFT_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2062 MSFT_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2063 MSFT_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2064 MSFT_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2066 size >>= 2;
2067 (*ppImpLib)->name = TLB_Alloc(size+1);
2068 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2069 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2070 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2072 ppImpLib = &(*ppImpLib)->next;
2076 /* type info's */
2077 if(tlbHeader.nrtypeinfos >= 0 )
2079 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2080 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2081 int i;
2083 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2085 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2087 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2088 ppTI = &((*ppTI)->next);
2089 (pTypeLibImpl->TypeInfoCount)++;
2093 TRACE("(%p)\n", pTypeLibImpl);
2094 return (ITypeLib2*) pTypeLibImpl;
2098 static BSTR TLB_MultiByteToBSTR(char *ptr)
2100 DWORD len;
2101 WCHAR *nameW;
2102 BSTR ret;
2104 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2105 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2106 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2107 ret = SysAllocString(nameW);
2108 HeapFree(GetProcessHeap(), 0, nameW);
2109 return ret;
2112 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2114 char b[3];
2115 int i;
2116 short s;
2118 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2119 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2120 return FALSE;
2123 guid->Data4[0] = s >> 8;
2124 guid->Data4[1] = s & 0xff;
2126 b[2] = '\0';
2127 for(i = 0; i < 6; i++) {
2128 memcpy(b, str + 24 + 2 * i, 2);
2129 guid->Data4[i + 2] = strtol(b, NULL, 16);
2131 return TRUE;
2134 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2136 WORD bytelen;
2137 DWORD len;
2138 WCHAR *nameW;
2140 *pBstr = NULL;
2141 bytelen = *(WORD*)ptr;
2142 if(bytelen == 0xffff) return 2;
2143 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2144 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2145 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2146 *pBstr = SysAllocStringLen(nameW, len);
2147 HeapFree(GetProcessHeap(), 0, nameW);
2148 return bytelen + 2;
2151 static WORD SLTG_ReadStringA(char *ptr, char **str)
2153 WORD bytelen;
2155 *str = NULL;
2156 bytelen = *(WORD*)ptr;
2157 if(bytelen == 0xffff) return 2;
2158 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2159 memcpy(*str, ptr + 2, bytelen);
2160 (*str)[bytelen] = '\0';
2161 return bytelen + 2;
2164 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2166 char *ptr = pLibBlk;
2167 WORD w;
2169 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2170 FIXME("libblk magic = %04x\n", w);
2171 return 0;
2174 ptr += 6;
2175 if((w = *(WORD*)ptr) != 0xffff) {
2176 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2177 ptr += w;
2179 ptr += 2;
2181 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2183 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2185 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2186 ptr += 4;
2188 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2189 ptr += 2;
2191 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2192 ptr += 2;
2194 ptr += 4; /* skip res12 */
2196 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2197 ptr += 2;
2199 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2200 ptr += 2;
2202 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2203 ptr += 2;
2205 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2206 ptr += sizeof(GUID);
2208 return ptr - (char*)pLibBlk;
2211 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2213 BOOL done = FALSE;
2214 TYPEDESC *pTD = &pElem->tdesc;
2216 /* Handle [in/out] first */
2217 if((*pType & 0xc000) == 0xc000)
2218 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2219 else if(*pType & 0x8000)
2220 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2221 else if(*pType & 0x4000)
2222 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2223 else
2224 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2226 if(*pType & 0x2000)
2227 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2229 if(*pType & 0x80)
2230 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2232 while(!done) {
2233 if((*pType & 0xe00) == 0xe00) {
2234 pTD->vt = VT_PTR;
2235 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2236 sizeof(TYPEDESC));
2237 pTD = pTD->u.lptdesc;
2239 switch(*pType & 0x7f) {
2240 case VT_PTR:
2241 pTD->vt = VT_PTR;
2242 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2243 sizeof(TYPEDESC));
2244 pTD = pTD->u.lptdesc;
2245 break;
2247 case VT_USERDEFINED:
2248 pTD->vt = VT_USERDEFINED;
2249 pTD->u.hreftype = *(++pType) / 4;
2250 done = TRUE;
2251 break;
2253 case VT_CARRAY:
2255 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2256 array */
2258 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2260 pTD->vt = VT_CARRAY;
2261 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2262 sizeof(ARRAYDESC) +
2263 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2264 pTD->u.lpadesc->cDims = pSA->cDims;
2265 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2266 pSA->cDims * sizeof(SAFEARRAYBOUND));
2268 pTD = &pTD->u.lpadesc->tdescElem;
2269 break;
2272 case VT_SAFEARRAY:
2274 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2275 useful? */
2277 pType++;
2278 pTD->vt = VT_SAFEARRAY;
2279 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2280 sizeof(TYPEDESC));
2281 pTD = pTD->u.lptdesc;
2282 break;
2284 default:
2285 pTD->vt = *pType & 0x7f;
2286 done = TRUE;
2287 break;
2289 pType++;
2291 return pType;
2295 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2296 char *pNameTable)
2298 int ref;
2299 char *name;
2300 TLBRefType **ppRefType;
2302 if(pRef->magic != SLTG_REF_MAGIC) {
2303 FIXME("Ref magic = %x\n", pRef->magic);
2304 return;
2306 name = ( (char*)(&pRef->names) + pRef->number);
2308 ppRefType = &pTI->reflist;
2309 for(ref = 0; ref < pRef->number >> 3; ref++) {
2310 char *refname;
2311 unsigned int lib_offs, type_num;
2313 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2314 sizeof(**ppRefType));
2316 name += SLTG_ReadStringA(name, &refname);
2317 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2318 FIXME("Can't sscanf ref\n");
2319 if(lib_offs != 0xffff) {
2320 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2322 while(*import) {
2323 if((*import)->offset == lib_offs)
2324 break;
2325 import = &(*import)->next;
2327 if(!*import) {
2328 char fname[MAX_PATH+1];
2329 int len;
2331 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2332 sizeof(**import));
2333 (*import)->offset = lib_offs;
2334 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2335 &(*import)->guid);
2336 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2337 &(*import)->wVersionMajor,
2338 &(*import)->wVersionMinor,
2339 &(*import)->lcid, fname) != 4) {
2340 FIXME("can't sscanf ref %s\n",
2341 pNameTable + lib_offs + 40);
2343 len = strlen(fname);
2344 if(fname[len-1] != '#')
2345 FIXME("fname = %s\n", fname);
2346 fname[len-1] = '\0';
2347 (*import)->name = TLB_MultiByteToBSTR(fname);
2349 (*ppRefType)->pImpTLInfo = *import;
2350 } else { /* internal ref */
2351 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2353 (*ppRefType)->reference = ref;
2354 (*ppRefType)->index = type_num;
2356 HeapFree(GetProcessHeap(), 0, refname);
2357 ppRefType = &(*ppRefType)->next;
2359 if((BYTE)*name != SLTG_REF_MAGIC)
2360 FIXME("End of ref block magic = %x\n", *name);
2361 dump_TLBRefType(pTI->reflist);
2364 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2365 BOOL OneOnly)
2367 SLTG_ImplInfo *info;
2368 TLBImplType **ppImplType = &pTI->impltypelist;
2369 /* I don't really get this structure, usually it's 0x16 bytes
2370 long, but iuser.tlb contains some that are 0x18 bytes long.
2371 That's ok because we can use the next ptr to jump to the next
2372 one. But how do we know the length of the last one? The WORD
2373 at offs 0x8 might be the clue. For now I'm just assuming that
2374 the last one is the regular 0x16 bytes. */
2376 info = (SLTG_ImplInfo*)pBlk;
2377 while(1) {
2378 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2379 sizeof(**ppImplType));
2380 (*ppImplType)->hRef = info->ref;
2381 (*ppImplType)->implflags = info->impltypeflags;
2382 pTI->TypeAttr.cImplTypes++;
2383 ppImplType = &(*ppImplType)->next;
2385 if(info->next == 0xffff)
2386 break;
2387 if(OneOnly)
2388 FIXME("Interface inheriting more than one interface\n");
2389 info = (SLTG_ImplInfo*)(pBlk + info->next);
2391 info++; /* see comment at top of function */
2392 return (char*)info;
2395 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2396 char *pNameTable)
2398 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2399 SLTG_MemberHeader *pMemHeader;
2400 char *pFirstItem, *pNextItem;
2402 if(pTIHeader->href_table != 0xffffffff) {
2403 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2404 pNameTable);
2408 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2410 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2412 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2413 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2416 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2420 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2421 char *pNameTable)
2423 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2424 SLTG_MemberHeader *pMemHeader;
2425 SLTG_Function *pFunc;
2426 char *pFirstItem, *pNextItem;
2427 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2428 int num = 0;
2430 if(pTIHeader->href_table != 0xffffffff) {
2431 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2432 pNameTable);
2435 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2437 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2439 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2440 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2443 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2444 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2446 int param;
2447 WORD *pType, *pArg;
2449 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2450 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2451 FIXME("func magic = %02x\n", pFunc->magic);
2452 return NULL;
2454 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2455 sizeof(**ppFuncDesc));
2456 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2458 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2459 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2460 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2461 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2462 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2463 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2465 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2466 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2468 if(pFunc->retnextopt & 0x80)
2469 pType = &pFunc->rettype;
2470 else
2471 pType = (WORD*)(pFirstItem + pFunc->rettype);
2474 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2476 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2477 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2478 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2479 (*ppFuncDesc)->pParamDesc =
2480 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2481 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2483 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2485 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2486 char *paramName = pNameTable + *pArg;
2487 BOOL HaveOffs;
2488 /* If arg type follows then paramName points to the 2nd
2489 letter of the name, else the next WORD is an offset to
2490 the arg type and paramName points to the first letter.
2491 So let's take one char off paramName and see if we're
2492 pointing at an alpha-numeric char. However if *pArg is
2493 0xffff or 0xfffe then the param has no name, the former
2494 meaning that the next WORD is the type, the latter
2495 meaning the the next WORD is an offset to the type. */
2497 HaveOffs = FALSE;
2498 if(*pArg == 0xffff)
2499 paramName = NULL;
2500 else if(*pArg == 0xfffe) {
2501 paramName = NULL;
2502 HaveOffs = TRUE;
2504 else if(!isalnum(*(paramName-1)))
2505 HaveOffs = TRUE;
2507 pArg++;
2509 if(HaveOffs) { /* the next word is an offset to type */
2510 pType = (WORD*)(pFirstItem + *pArg);
2511 SLTG_DoType(pType, pFirstItem,
2512 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2513 pArg++;
2514 } else {
2515 if(paramName)
2516 paramName--;
2517 pArg = SLTG_DoType(pArg, pFirstItem,
2518 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2521 /* Are we an optional param ? */
2522 if((*ppFuncDesc)->funcdesc.cParams - param <=
2523 (*ppFuncDesc)->funcdesc.cParamsOpt)
2524 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2526 if(paramName) {
2527 (*ppFuncDesc)->pParamDesc[param].Name =
2528 TLB_MultiByteToBSTR(paramName);
2532 ppFuncDesc = &((*ppFuncDesc)->next);
2533 if(pFunc->next == 0xffff) break;
2535 pTI->TypeAttr.cFuncs = num;
2536 dump_TLBFuncDesc(pTI->funclist);
2537 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2540 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2541 char *pNameTable)
2543 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2544 SLTG_MemberHeader *pMemHeader;
2545 SLTG_RecordItem *pItem;
2546 char *pFirstItem;
2547 TLBVarDesc **ppVarDesc = &pTI->varlist;
2548 int num = 0;
2549 WORD *pType;
2550 char buf[300];
2552 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2554 pFirstItem = (char*)(pMemHeader + 1);
2555 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2556 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2557 if(pItem->magic != SLTG_RECORD_MAGIC) {
2558 FIXME("record magic = %02x\n", pItem->magic);
2559 return NULL;
2561 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2562 sizeof(**ppVarDesc));
2563 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2564 (*ppVarDesc)->vardesc.memid = pItem->memid;
2565 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2566 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2568 if(pItem->typepos == 0x02)
2569 pType = &pItem->type;
2570 else if(pItem->typepos == 0x00)
2571 pType = (WORD*)(pFirstItem + pItem->type);
2572 else {
2573 FIXME("typepos = %02x\n", pItem->typepos);
2574 break;
2577 SLTG_DoType(pType, pFirstItem,
2578 &(*ppVarDesc)->vardesc.elemdescVar);
2580 /* FIXME("helpcontext, helpstring\n"); */
2582 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2584 ppVarDesc = &((*ppVarDesc)->next);
2585 if(pItem->next == 0xffff) break;
2587 pTI->TypeAttr.cVars = num;
2588 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2591 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2592 char *pNameTable)
2594 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2595 SLTG_MemberHeader *pMemHeader;
2596 SLTG_EnumItem *pItem;
2597 char *pFirstItem;
2598 TLBVarDesc **ppVarDesc = &pTI->varlist;
2599 int num = 0;
2601 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2603 pFirstItem = (char*)(pMemHeader + 1);
2604 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2605 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2606 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2607 FIXME("enumitem magic = %04x\n", pItem->magic);
2608 return NULL;
2610 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2611 sizeof(**ppVarDesc));
2612 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2613 (*ppVarDesc)->vardesc.memid = pItem->memid;
2614 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2615 sizeof(VARIANT));
2616 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2617 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2618 *(INT*)(pItem->value + pFirstItem);
2619 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2620 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2621 /* FIXME("helpcontext, helpstring\n"); */
2623 ppVarDesc = &((*ppVarDesc)->next);
2624 if(pItem->next == 0xffff) break;
2626 pTI->TypeAttr.cVars = num;
2627 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2630 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2631 managable copy of it into this */
2632 typedef struct {
2633 WORD small_no;
2634 char *index_name;
2635 char *other_name;
2636 WORD res1a;
2637 WORD name_offs;
2638 WORD more_bytes;
2639 char *extra;
2640 WORD res20;
2641 DWORD helpcontext;
2642 WORD res26;
2643 GUID uuid;
2644 } SLTG_InternalOtherTypeInfo;
2646 /****************************************************************************
2647 * ITypeLib2_Constructor_SLTG
2649 * loading a SLTG typelib from an in-memory image
2651 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2653 ITypeLibImpl *pTypeLibImpl;
2654 SLTG_Header *pHeader;
2655 SLTG_BlkEntry *pBlkEntry;
2656 SLTG_Magic *pMagic;
2657 SLTG_Index *pIndex;
2658 SLTG_Pad9 *pPad9;
2659 LPVOID pBlk, pFirstBlk;
2660 SLTG_LibBlk *pLibBlk;
2661 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2662 char *pAfterOTIBlks = NULL;
2663 char *pNameTable, *ptr;
2664 int i;
2665 DWORD len, order;
2666 ITypeInfoImpl **ppTypeInfoImpl;
2668 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2670 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2671 if (!pTypeLibImpl) return NULL;
2673 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2674 pTypeLibImpl->ref = 1;
2676 pHeader = pLib;
2678 TRACE("header:\n");
2679 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2680 pHeader->nrOfFileBlks );
2681 if (memcmp(&pHeader->SLTG_magic, TLBMAGIC1, 4)) {
2682 FIXME("Header type magic 0x%08lx not supported.\n",
2683 pHeader->SLTG_magic);
2684 return NULL;
2687 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2688 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2690 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2691 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2693 /* Next we have a magic block */
2694 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2696 /* Let's see if we're still in sync */
2697 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2698 sizeof(SLTG_COMPOBJ_MAGIC))) {
2699 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2700 return NULL;
2702 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2703 sizeof(SLTG_DIR_MAGIC))) {
2704 FIXME("dir magic = %s\n", pMagic->dir_magic);
2705 return NULL;
2708 pIndex = (SLTG_Index*)(pMagic+1);
2710 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2712 pFirstBlk = (LPVOID)(pPad9 + 1);
2714 /* We'll set up a ptr to the main library block, which is the last one. */
2716 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2717 pBlkEntry[order].next != 0;
2718 order = pBlkEntry[order].next - 1, i++) {
2719 pBlk += pBlkEntry[order].len;
2721 pLibBlk = pBlk;
2723 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2725 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2726 interspersed */
2728 len += 0x40;
2730 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2732 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2733 sizeof(*pOtherTypeInfoBlks) *
2734 pTypeLibImpl->TypeInfoCount);
2737 ptr = (char*)pLibBlk + len;
2739 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2740 WORD w, extra;
2741 len = 0;
2743 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2745 w = *(WORD*)(ptr + 2);
2746 if(w != 0xffff) {
2747 len += w;
2748 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2749 w+1);
2750 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2751 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2753 w = *(WORD*)(ptr + 4 + len);
2754 if(w != 0xffff) {
2755 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2756 len += w;
2757 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2758 w+1);
2759 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2760 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2762 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2763 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2764 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2765 if(extra) {
2766 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2767 extra);
2768 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2769 len += extra;
2771 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2772 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2773 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2774 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2775 len += sizeof(SLTG_OtherTypeInfo);
2776 ptr += len;
2779 pAfterOTIBlks = ptr;
2781 /* Skip this WORD and get the next DWORD */
2782 len = *(DWORD*)(pAfterOTIBlks + 2);
2784 /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a
2785 magic dust and we should be pointing at the beginning of the name
2786 table */
2788 pNameTable = (char*)pLibBlk + len + 0x216;
2790 pNameTable += 2;
2792 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
2794 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
2797 /* Hopefully we now have enough ptrs set up to actually read in
2798 some TypeInfos. It's not clear which order to do them in, so
2799 I'll just follow the links along the BlkEntry chain and read
2800 them in in the order in which they're in the file */
2802 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
2804 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2805 pBlkEntry[order].next != 0;
2806 order = pBlkEntry[order].next - 1, i++) {
2808 SLTG_TypeInfoHeader *pTIHeader;
2809 SLTG_TypeInfoTail *pTITail;
2811 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
2812 pOtherTypeInfoBlks[i].index_name)) {
2813 FIXME("Index strings don't match\n");
2814 return NULL;
2817 pTIHeader = pBlk;
2818 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
2819 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
2820 return NULL;
2822 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
2823 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
2824 (*ppTypeInfoImpl)->index = i;
2825 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
2826 pOtherTypeInfoBlks[i].name_offs +
2827 pNameTable);
2828 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
2829 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
2830 sizeof(GUID));
2831 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
2832 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
2833 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
2834 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
2835 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
2837 if((pTIHeader->typeflags1 & 7) != 2)
2838 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
2839 if(pTIHeader->typeflags3 != 2)
2840 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
2842 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2843 debugstr_w((*ppTypeInfoImpl)->Name),
2844 typekind_desc[pTIHeader->typekind],
2845 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
2846 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
2848 switch(pTIHeader->typekind) {
2849 case TKIND_ENUM:
2850 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
2851 break;
2853 case TKIND_RECORD:
2854 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
2855 break;
2857 case TKIND_INTERFACE:
2858 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
2859 break;
2861 case TKIND_COCLASS:
2862 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
2863 break;
2865 default:
2866 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
2867 pTITail = NULL;
2868 break;
2872 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
2873 but we've already set those */
2874 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
2875 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
2876 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
2878 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
2879 pBlk += pBlkEntry[order].len;
2882 if(i != pTypeLibImpl->TypeInfoCount) {
2883 FIXME("Somehow processed %d TypeInfos\n", i);
2884 return NULL;
2887 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
2888 return (ITypeLib2*)pTypeLibImpl;
2891 /* ITypeLib::QueryInterface
2893 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
2894 ITypeLib2 * iface,
2895 REFIID riid,
2896 VOID **ppvObject)
2898 ICOM_THIS( ITypeLibImpl, iface);
2900 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
2902 *ppvObject=NULL;
2903 if(IsEqualIID(riid, &IID_IUnknown) ||
2904 IsEqualIID(riid,&IID_ITypeLib)||
2905 IsEqualIID(riid,&IID_ITypeLib2))
2907 *ppvObject = This;
2910 if(*ppvObject)
2912 ITypeLib2_AddRef(iface);
2913 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
2914 return S_OK;
2916 TRACE("-- Interface: E_NOINTERFACE\n");
2917 return E_NOINTERFACE;
2920 /* ITypeLib::AddRef
2922 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
2924 ICOM_THIS( ITypeLibImpl, iface);
2926 TRACE("(%p)->ref is %u\n",This, This->ref);
2928 return ++(This->ref);
2931 /* ITypeLib::Release
2933 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
2935 ICOM_THIS( ITypeLibImpl, iface);
2937 --(This->ref);
2939 TRACE("(%p)->(%u)\n",This, This->ref);
2941 if (!This->ref)
2943 /* fixme destroy child objects */
2945 TRACE(" destroying ITypeLib(%p)\n",This);
2947 if (This->Name)
2949 SysFreeString(This->Name);
2950 This->Name = NULL;
2953 if (This->DocString)
2955 SysFreeString(This->DocString);
2956 This->DocString = NULL;
2959 if (This->HelpFile)
2961 SysFreeString(This->HelpFile);
2962 This->HelpFile = NULL;
2965 if (This->HelpStringDll)
2967 SysFreeString(This->HelpStringDll);
2968 This->HelpStringDll = NULL;
2971 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
2972 HeapFree(GetProcessHeap(),0,This);
2973 return 0;
2976 return This->ref;
2979 /* ITypeLib::GetTypeInfoCount
2981 * Returns the number of type descriptions in the type library
2983 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
2985 ICOM_THIS( ITypeLibImpl, iface);
2986 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
2987 return This->TypeInfoCount;
2990 /* ITypeLib::GetTypeInfo
2992 * retrieves the specified type description in the library.
2994 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
2995 ITypeLib2 *iface,
2996 UINT index,
2997 ITypeInfo **ppTInfo)
2999 int i;
3001 ICOM_THIS( ITypeLibImpl, iface);
3002 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3004 TRACE("(%p)->(index=%d) \n", This, index);
3006 if (!ppTInfo) return E_INVALIDARG;
3008 /* search element n in list */
3009 for(i=0; i < index; i++)
3011 pTypeInfo = pTypeInfo->next;
3012 if (!pTypeInfo)
3014 TRACE("-- element not found\n");
3015 return TYPE_E_ELEMENTNOTFOUND;
3019 *ppTInfo = (ITypeInfo *) pTypeInfo;
3021 ITypeInfo_AddRef(*ppTInfo);
3022 TRACE("-- found (%p)\n",*ppTInfo);
3023 return S_OK;
3027 /* ITypeLibs::GetTypeInfoType
3029 * Retrieves the type of a type description.
3031 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3032 ITypeLib2 *iface,
3033 UINT index,
3034 TYPEKIND *pTKind)
3036 ICOM_THIS( ITypeLibImpl, iface);
3037 int i;
3038 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3040 TRACE("(%p) index %d \n",This, index);
3042 if(!pTKind) return E_INVALIDARG;
3044 /* search element n in list */
3045 for(i=0; i < index; i++)
3047 if(!pTInfo)
3049 TRACE("-- element not found\n");
3050 return TYPE_E_ELEMENTNOTFOUND;
3052 pTInfo = pTInfo->next;
3055 *pTKind = pTInfo->TypeAttr.typekind;
3056 TRACE("-- found Type (%d)\n", *pTKind);
3057 return S_OK;
3060 /* ITypeLib::GetTypeInfoOfGuid
3062 * Retrieves the type description that corresponds to the specified GUID.
3065 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3066 ITypeLib2 *iface,
3067 REFGUID guid,
3068 ITypeInfo **ppTInfo)
3070 ICOM_THIS( ITypeLibImpl, iface);
3071 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3073 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3075 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3077 /* search linked list for guid */
3078 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3080 pTypeInfo = pTypeInfo->next;
3082 if (!pTypeInfo)
3084 /* end of list reached */
3085 TRACE("-- element not found\n");
3086 return TYPE_E_ELEMENTNOTFOUND;
3090 TRACE("-- found (%p, %s)\n",
3091 pTypeInfo,
3092 debugstr_w(pTypeInfo->Name));
3094 *ppTInfo = (ITypeInfo*)pTypeInfo;
3095 ITypeInfo_AddRef(*ppTInfo);
3096 return S_OK;
3099 /* ITypeLib::GetLibAttr
3101 * Retrieves the structure that contains the library's attributes.
3104 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3105 ITypeLib2 *iface,
3106 LPTLIBATTR *ppTLibAttr)
3108 ICOM_THIS( ITypeLibImpl, iface);
3109 TRACE("(%p)\n",This);
3110 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3111 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3112 return S_OK;
3115 /* ITypeLib::GetTypeComp
3117 * Enables a client compiler to bind to a library's types, variables,
3118 * constants, and global functions.
3121 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3122 ITypeLib2 *iface,
3123 ITypeComp **ppTComp)
3125 ICOM_THIS( ITypeLibImpl, iface);
3126 FIXME("(%p): stub!\n",This);
3127 return E_NOTIMPL;
3130 /* ITypeLib::GetDocumentation
3132 * Retrieves the library's documentation string, the complete Help file name
3133 * and path, and the context identifier for the library Help topic in the Help
3134 * file.
3137 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3138 ITypeLib2 *iface,
3139 INT index,
3140 BSTR *pBstrName,
3141 BSTR *pBstrDocString,
3142 DWORD *pdwHelpContext,
3143 BSTR *pBstrHelpFile)
3145 ICOM_THIS( ITypeLibImpl, iface);
3147 HRESULT result = E_INVALIDARG;
3149 ITypeInfo *pTInfo;
3152 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3153 This, index,
3154 pBstrName, pBstrDocString,
3155 pdwHelpContext, pBstrHelpFile);
3157 if(index<0)
3159 /* documentation for the typelib */
3160 if(pBstrName && This->Name)
3162 *pBstrName = SysAllocString(This->Name);
3164 if (!(*pBstrName)) return STG_E_INSUFFICIENTMEMORY;
3166 if(pBstrDocString && This->DocString)
3168 *pBstrDocString = SysAllocString(This->DocString);
3170 if (!(*pBstrDocString)) return STG_E_INSUFFICIENTMEMORY;
3173 if(pdwHelpContext)
3175 *pdwHelpContext = This->dwHelpContext;
3177 if(pBstrHelpFile && This->HelpFile)
3179 *pBstrHelpFile = SysAllocString(This->HelpFile);
3181 if (!(*pBstrHelpFile)) return STG_E_INSUFFICIENTMEMORY;
3184 result = S_OK;
3186 else
3188 /* for a typeinfo */
3189 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3191 if(SUCCEEDED(result))
3193 result = ITypeInfo_GetDocumentation(pTInfo,
3194 MEMBERID_NIL,
3195 pBstrName,
3196 pBstrDocString,
3197 pdwHelpContext, pBstrHelpFile);
3199 ITypeInfo_Release(pTInfo);
3202 return result;
3205 /* ITypeLib::IsName
3207 * Indicates whether a passed-in string contains the name of a type or member
3208 * described in the library.
3211 static HRESULT WINAPI ITypeLib2_fnIsName(
3212 ITypeLib2 *iface,
3213 LPOLESTR szNameBuf,
3214 ULONG lHashVal,
3215 BOOL *pfName)
3217 ICOM_THIS( ITypeLibImpl, iface);
3218 ITypeInfoImpl *pTInfo;
3219 TLBFuncDesc *pFInfo;
3220 TLBVarDesc *pVInfo;
3221 int i;
3222 UINT nNameBufLen = SysStringLen(szNameBuf);
3224 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3225 pfName);
3227 *pfName=TRUE;
3228 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3229 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3230 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3231 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3232 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3233 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3234 goto ITypeLib2_fnIsName_exit;
3236 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3237 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3240 *pfName=FALSE;
3242 ITypeLib2_fnIsName_exit:
3243 TRACE("(%p)slow! search for %s: %s found!\n", This,
3244 debugstr_w(szNameBuf), *pfName?"NOT":"");
3246 return S_OK;
3249 /* ITypeLib::FindName
3251 * Finds occurrences of a type description in a type library. This may be used
3252 * to quickly verify that a name exists in a type library.
3255 static HRESULT WINAPI ITypeLib2_fnFindName(
3256 ITypeLib2 *iface,
3257 LPOLESTR szNameBuf,
3258 ULONG lHashVal,
3259 ITypeInfo **ppTInfo,
3260 MEMBERID *rgMemId,
3261 UINT16 *pcFound)
3263 ICOM_THIS( ITypeLibImpl, iface);
3264 ITypeInfoImpl *pTInfo;
3265 TLBFuncDesc *pFInfo;
3266 TLBVarDesc *pVInfo;
3267 int i,j = 0;
3269 UINT nNameBufLen = SysStringLen(szNameBuf);
3271 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3272 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3273 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3274 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3275 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3276 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3277 goto ITypeLib2_fnFindName_exit;
3279 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3280 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3281 continue;
3282 ITypeLib2_fnFindName_exit:
3283 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3284 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3285 j++;
3287 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3288 This, *pcFound, debugstr_w(szNameBuf), j);
3290 *pcFound=j;
3292 return S_OK;
3295 /* ITypeLib::ReleaseTLibAttr
3297 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3300 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3301 ITypeLib2 *iface,
3302 TLIBATTR *pTLibAttr)
3304 ICOM_THIS( ITypeLibImpl, iface);
3305 TRACE("freeing (%p)\n",This);
3306 HeapFree(GetProcessHeap(),0,pTLibAttr);
3310 /* ITypeLib2::GetCustData
3312 * gets the custom data
3314 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3315 ITypeLib2 * iface,
3316 REFGUID guid,
3317 VARIANT *pVarVal)
3319 ICOM_THIS( ITypeLibImpl, iface);
3320 TLBCustData *pCData;
3322 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3324 if( IsEqualIID(guid, &pCData->guid)) break;
3327 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3329 if(pCData)
3331 VariantInit( pVarVal);
3332 VariantCopy( pVarVal, &pCData->data);
3333 return S_OK;
3335 return E_INVALIDARG; /* FIXME: correct? */
3338 /* ITypeLib2::GetLibStatistics
3340 * Returns statistics about a type library that are required for efficient
3341 * sizing of hash tables.
3344 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3345 ITypeLib2 * iface,
3346 ULONG *pcUniqueNames,
3347 ULONG *pcchUniqueNames)
3349 ICOM_THIS( ITypeLibImpl, iface);
3351 FIXME("(%p): stub!\n", This);
3353 if(pcUniqueNames) *pcUniqueNames=1;
3354 if(pcchUniqueNames) *pcchUniqueNames=1;
3355 return S_OK;
3358 /* ITypeLib2::GetDocumentation2
3360 * Retrieves the library's documentation string, the complete Help file name
3361 * and path, the localization context to use, and the context ID for the
3362 * library Help topic in the Help file.
3365 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3366 ITypeLib2 * iface,
3367 INT index,
3368 LCID lcid,
3369 BSTR *pbstrHelpString,
3370 DWORD *pdwHelpStringContext,
3371 BSTR *pbstrHelpStringDll)
3373 ICOM_THIS( ITypeLibImpl, iface);
3374 HRESULT result;
3375 ITypeInfo *pTInfo;
3377 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3379 /* the help string should be obtained from the helpstringdll,
3380 * using the _DLLGetDocumentation function, based on the supplied
3381 * lcid. Nice to do sometime...
3383 if(index<0)
3385 /* documentation for the typelib */
3386 if(pbstrHelpString)
3387 *pbstrHelpString=SysAllocString(This->DocString);
3388 if(pdwHelpStringContext)
3389 *pdwHelpStringContext=This->dwHelpContext;
3390 if(pbstrHelpStringDll)
3391 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3393 result = S_OK;
3395 else
3397 /* for a typeinfo */
3398 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3400 if(SUCCEEDED(result))
3402 ITypeInfo2 * pTInfo2;
3403 result = ITypeInfo_QueryInterface(pTInfo,
3404 &IID_ITypeInfo2,
3405 (LPVOID*) &pTInfo2);
3407 if(SUCCEEDED(result))
3409 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3410 MEMBERID_NIL,
3411 lcid,
3412 pbstrHelpString,
3413 pdwHelpStringContext,
3414 pbstrHelpStringDll);
3416 ITypeInfo2_Release(pTInfo2);
3419 ITypeInfo_Release(pTInfo);
3422 return result;
3425 /* ITypeLib2::GetAllCustData
3427 * Gets all custom data items for the library.
3430 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3431 ITypeLib2 * iface,
3432 CUSTDATA *pCustData)
3434 ICOM_THIS( ITypeLibImpl, iface);
3435 TLBCustData *pCData;
3436 int i;
3437 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3438 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3439 if(pCustData->prgCustData ){
3440 pCustData->cCustData=This->ctCustData;
3441 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3442 pCustData->prgCustData[i].guid=pCData->guid;
3443 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3445 }else{
3446 ERR(" OUT OF MEMORY! \n");
3447 return E_OUTOFMEMORY;
3449 return S_OK;
3452 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3453 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3454 ITypeLib2_fnQueryInterface,
3455 ITypeLib2_fnAddRef,
3456 ITypeLib2_fnRelease,
3457 ITypeLib2_fnGetTypeInfoCount,
3458 ITypeLib2_fnGetTypeInfo,
3459 ITypeLib2_fnGetTypeInfoType,
3460 ITypeLib2_fnGetTypeInfoOfGuid,
3461 ITypeLib2_fnGetLibAttr,
3462 ITypeLib2_fnGetTypeComp,
3463 ITypeLib2_fnGetDocumentation,
3464 ITypeLib2_fnIsName,
3465 ITypeLib2_fnFindName,
3466 ITypeLib2_fnReleaseTLibAttr,
3468 ITypeLib2_fnGetCustData,
3469 ITypeLib2_fnGetLibStatistics,
3470 ITypeLib2_fnGetDocumentation2,
3471 ITypeLib2_fnGetAllCustData
3474 /*================== ITypeInfo(2) Methods ===================================*/
3475 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3477 ITypeInfoImpl * pTypeInfoImpl;
3479 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3480 if (pTypeInfoImpl)
3482 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3483 pTypeInfoImpl->ref=1;
3485 TRACE("(%p)\n", pTypeInfoImpl);
3486 return (ITypeInfo2*) pTypeInfoImpl;
3489 /* ITypeInfo::QueryInterface
3491 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3492 ITypeInfo2 *iface,
3493 REFIID riid,
3494 VOID **ppvObject)
3496 ICOM_THIS( ITypeLibImpl, iface);
3498 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3500 *ppvObject=NULL;
3501 if(IsEqualIID(riid, &IID_IUnknown) ||
3502 IsEqualIID(riid,&IID_ITypeInfo)||
3503 IsEqualIID(riid,&IID_ITypeInfo2))
3504 *ppvObject = This;
3506 if(*ppvObject){
3507 ITypeInfo_AddRef(iface);
3508 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3509 return S_OK;
3511 TRACE("-- Interface: E_NOINTERFACE\n");
3512 return E_NOINTERFACE;
3515 /* ITypeInfo::AddRef
3517 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3519 ICOM_THIS( ITypeInfoImpl, iface);
3521 ++(This->ref);
3523 TRACE("(%p)->ref is %u\n",This, This->ref);
3524 return This->ref;
3527 /* ITypeInfo::Release
3529 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3531 ICOM_THIS( ITypeInfoImpl, iface);
3533 --(This->ref);
3535 TRACE("(%p)->(%u)\n",This, This->ref);
3537 if (!This->ref)
3539 FIXME("destroy child objects\n");
3541 TRACE("destroying ITypeInfo(%p)\n",This);
3542 if (This->Name)
3544 SysFreeString(This->Name);
3545 This->Name = 0;
3548 if (This->DocString)
3550 SysFreeString(This->DocString);
3551 This->DocString = 0;
3554 if (This->next)
3556 ITypeInfo_Release((ITypeInfo*)This->next);
3559 HeapFree(GetProcessHeap(),0,This);
3560 return 0;
3562 return This->ref;
3565 /* ITypeInfo::GetTypeAttr
3567 * Retrieves a TYPEATTR structure that contains the attributes of the type
3568 * description.
3571 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3572 LPTYPEATTR *ppTypeAttr)
3574 ICOM_THIS( ITypeInfoImpl, iface);
3575 TRACE("(%p)\n",This);
3576 /* FIXME: must do a copy here */
3577 *ppTypeAttr=&This->TypeAttr;
3578 return S_OK;
3581 /* ITypeInfo::GetTypeComp
3583 * Retrieves the ITypeComp interface for the type description, which enables a
3584 * client compiler to bind to the type description's members.
3587 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3588 ITypeComp * *ppTComp)
3590 ICOM_THIS( ITypeInfoImpl, iface);
3591 FIXME("(%p) stub!\n", This);
3592 return S_OK;
3595 /* ITypeInfo::GetFuncDesc
3597 * Retrieves the FUNCDESC structure that contains information about a
3598 * specified function.
3601 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3602 LPFUNCDESC *ppFuncDesc)
3604 ICOM_THIS( ITypeInfoImpl, iface);
3605 int i;
3606 TLBFuncDesc * pFDesc;
3607 TRACE("(%p) index %d\n", This, index);
3608 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3610 if(pFDesc){
3611 /* FIXME: must do a copy here */
3612 *ppFuncDesc=&pFDesc->funcdesc;
3613 return S_OK;
3615 return E_INVALIDARG;
3618 /* ITypeInfo::GetVarDesc
3620 * Retrieves a VARDESC structure that describes the specified variable.
3623 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3624 LPVARDESC *ppVarDesc)
3626 ICOM_THIS( ITypeInfoImpl, iface);
3627 int i;
3628 TLBVarDesc * pVDesc;
3629 TRACE("(%p) index %d\n", This, index);
3630 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3632 if(pVDesc){
3633 /* FIXME: must do a copy here */
3634 *ppVarDesc=&pVDesc->vardesc;
3635 return S_OK;
3637 return E_INVALIDARG;
3640 /* ITypeInfo_GetNames
3642 * Retrieves the variable with the specified member ID (or the name of the
3643 * property or method and its parameters) that correspond to the specified
3644 * function ID.
3646 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3647 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3649 ICOM_THIS( ITypeInfoImpl, iface);
3650 TLBFuncDesc * pFDesc;
3651 TLBVarDesc * pVDesc;
3652 int i;
3653 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3654 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3655 if(pFDesc)
3657 /* function found, now return function and parameter names */
3658 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3660 if(!i)
3661 *rgBstrNames=SysAllocString(pFDesc->Name);
3662 else
3663 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3665 *pcNames=i;
3667 else
3669 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3670 if(pVDesc)
3672 *rgBstrNames=SysAllocString(pVDesc->Name);
3673 *pcNames=1;
3675 else
3677 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3679 /* recursive search */
3680 ITypeInfo *pTInfo;
3681 HRESULT result;
3682 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3683 &pTInfo);
3684 if(SUCCEEDED(result))
3686 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3687 ITypeInfo_Release(pTInfo);
3688 return result;
3690 WARN("Could not search inherited interface!\n");
3692 else
3694 WARN("no names found\n");
3696 *pcNames=0;
3697 return TYPE_E_ELEMENTNOTFOUND;
3700 return S_OK;
3704 /* ITypeInfo::GetRefTypeOfImplType
3706 * If a type description describes a COM class, it retrieves the type
3707 * description of the implemented interface types. For an interface,
3708 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3709 * if any exist.
3712 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3713 ITypeInfo2 *iface,
3714 UINT index,
3715 HREFTYPE *pRefType)
3717 ICOM_THIS( ITypeInfoImpl, iface);
3718 int(i);
3719 TLBImplType *pImpl = This->impltypelist;
3721 TRACE("(%p) index %d\n", This, index);
3722 dump_TypeInfo(This);
3724 if(index==(UINT)-1)
3726 /* only valid on dual interfaces;
3727 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3729 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3731 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3732 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3734 *pRefType = -1;
3736 else
3738 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3739 *pRefType = pImpl->hRef;
3742 else
3744 /* get element n from linked list */
3745 for(i=0; pImpl && i<index; i++)
3747 pImpl = pImpl->next;
3750 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3752 *pRefType = pImpl->hRef;
3754 TRACE("-- 0x%08lx\n", pImpl->hRef );
3757 return S_OK;
3761 /* ITypeInfo::GetImplTypeFlags
3763 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3764 * or base interface in a type description.
3766 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
3767 UINT index, INT *pImplTypeFlags)
3769 ICOM_THIS( ITypeInfoImpl, iface);
3770 int i;
3771 TLBImplType *pImpl;
3773 TRACE("(%p) index %d\n", This, index);
3774 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
3775 i++, pImpl=pImpl->next)
3777 if(i==index && pImpl){
3778 *pImplTypeFlags=pImpl->implflags;
3779 return S_OK;
3781 *pImplTypeFlags=0;
3782 return TYPE_E_ELEMENTNOTFOUND;
3785 /* GetIDsOfNames
3786 * Maps between member names and member IDs, and parameter names and
3787 * parameter IDs.
3789 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
3790 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
3792 ICOM_THIS( ITypeInfoImpl, iface);
3793 TLBFuncDesc * pFDesc;
3794 TLBVarDesc * pVDesc;
3795 HRESULT ret=S_OK;
3797 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
3798 cNames);
3799 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
3800 int i, j;
3801 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
3802 if(cNames) *pMemId=pFDesc->funcdesc.memid;
3803 for(i=1; i < cNames; i++){
3804 for(j=0; j<pFDesc->funcdesc.cParams; j++)
3805 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
3806 break;
3807 if( j<pFDesc->funcdesc.cParams)
3808 pMemId[i]=j;
3809 else
3810 ret=DISP_E_UNKNOWNNAME;
3812 return ret;
3815 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
3816 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
3817 if(cNames) *pMemId=pVDesc->vardesc.memid;
3818 return ret;
3821 /* not found, see if this is and interface with an inheritance */
3822 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
3823 This->TypeAttr.cImplTypes ){
3824 /* recursive search */
3825 ITypeInfo *pTInfo;
3826 ret=ITypeInfo_GetRefTypeInfo(iface,
3827 This->impltypelist->hRef, &pTInfo);
3828 if(SUCCEEDED(ret)){
3829 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
3830 ITypeInfo_Release(pTInfo);
3831 return ret;
3833 WARN("Could not search inherited interface!\n");
3834 } else
3835 WARN("no names found\n");
3836 return DISP_E_UNKNOWNNAME;
3839 /* ITypeInfo::Invoke
3841 * Invokes a method, or accesses a property of an object, that implements the
3842 * interface described by the type description.
3844 static DWORD _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
3845 DWORD res;
3847 if (TRACE_ON(ole)) {
3848 int i;
3849 MESSAGE("Calling %p(",func);
3850 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
3851 MESSAGE(")\n");
3854 switch (callconv) {
3855 case CC_STDCALL:
3857 switch (nrargs) {
3858 case 0: {
3859 DWORD (WINAPI *xfunc)() = func;
3860 res = xfunc();
3861 break;
3863 case 1: {
3864 DWORD (WINAPI *xfunc)(DWORD) = func;
3865 res = xfunc(args[0]);
3866 break;
3868 case 2: {
3869 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
3870 res = xfunc(args[0],args[1]);
3871 break;
3873 case 3: {
3874 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
3875 res = xfunc(args[0],args[1],args[2]);
3876 break;
3878 default:
3879 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
3880 res = -1;
3881 break;
3883 break;
3884 default:
3885 FIXME("unsupported calling convention %d\n",callconv);
3886 res = -1;
3887 break;
3889 TRACE("returns %08lx\n",res);
3890 return res;
3893 static HRESULT WINAPI ITypeInfo_fnInvoke(
3894 ITypeInfo2 *iface,
3895 VOID *pIUnk,
3896 MEMBERID memid,
3897 UINT16 dwFlags,
3898 DISPPARAMS *pDispParams,
3899 VARIANT *pVarResult,
3900 EXCEPINFO *pExcepInfo,
3901 UINT *pArgErr)
3903 ICOM_THIS( ITypeInfoImpl, iface);
3904 TLBFuncDesc * pFDesc;
3905 TLBVarDesc * pVDesc;
3906 int i;
3908 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
3909 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
3911 dump_DispParms(pDispParams);
3913 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
3914 if (pFDesc->funcdesc.memid == memid) {
3915 if (pFDesc->funcdesc.invkind & dwFlags)
3916 break;
3918 if (pFDesc) {
3919 dump_TLBFuncDescOne(pFDesc);
3920 switch (pFDesc->funcdesc.funckind) {
3921 case FUNC_PUREVIRTUAL:
3922 case FUNC_VIRTUAL: {
3923 DWORD res;
3924 DWORD *args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*(pFDesc->funcdesc.cParams+1));
3925 DWORD *args2 = (DWORD*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*(pFDesc->funcdesc.cParams));
3926 args[0] = (DWORD)pIUnk;
3928 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
3929 if (i<pDispParams->cArgs) {
3930 TRACE("set %d to disparg type %d vs %d\n",i,
3931 V_VT(&pDispParams->rgvarg[pDispParams->cArgs-i-1]),
3932 pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt
3934 args[i+1] = V_UNION(&pDispParams->rgvarg[pDispParams->cArgs-i-1],lVal);
3935 } else {
3936 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
3937 TRACE("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
3938 /*FIXME: give pointers for the rest, so propertyget works*/
3939 args[i+1] = (DWORD)&args2[i];
3941 /* If pointer to variant, pass reference to variant
3942 * in result variant array.
3944 if ((tdesc->vt == VT_PTR) &&
3945 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
3946 pVarResult
3948 args[i+1] = (DWORD)(pVarResult+(i-pDispParams->cArgs));
3951 if (pFDesc->funcdesc.cParamsOpt)
3952 FIXME("Does not support optional parameters (%d)\n",
3953 pFDesc->funcdesc.cParamsOpt
3956 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
3957 pFDesc->funcdesc.callconv,
3958 pFDesc->funcdesc.cParams+1,
3959 args
3961 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
3962 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
3963 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
3964 /* If we are a pointer to a variant, we are done already */
3965 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
3966 continue;
3968 VariantInit(&pVarResult[i]);
3969 V_UNION(pVarResult+i,intVal) = args2[i];
3971 if (tdesc->vt == VT_PTR)
3972 tdesc = tdesc->u.lptdesc;
3973 V_VT(pVarResult+i) = tdesc->vt;
3975 /* HACK: VB5 likes this.
3976 * I do not know why. There is 1 example in MSDN which uses
3977 * this which appears broken (mixes int vals and
3978 * IDispatch*.).
3980 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
3981 V_VT(pVarResult+i) = VT_DISPATCH;
3982 TRACE("storing into variant: [%d] type %d, val %08x\n",
3983 i,V_VT(pVarResult+i),V_UNION(pVarResult+i,intVal)
3987 HeapFree(GetProcessHeap(),0,args2);
3988 HeapFree(GetProcessHeap(),0,args);
3989 return S_OK;
3991 case FUNC_DISPATCH: {
3992 IDispatch *disp;
3993 HRESULT hr;
3995 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
3996 if (hr) {
3997 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
3998 return hr;
4000 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4001 hr = IDispatch_Invoke(
4002 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4003 pVarResult,pExcepInfo,pArgErr
4005 if (hr)
4006 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4007 IDispatch_Release(disp);
4008 return hr;
4010 default:
4011 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4012 return E_FAIL;
4014 } else {
4015 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4016 if (pVDesc->vardesc.memid == memid) {
4017 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4018 dump_TLBVarDesc(pVDesc);
4019 break;
4023 /* not found, look for it in inherited interfaces */
4024 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4025 /* recursive search */
4026 ITypeInfo *pTInfo;
4027 HRESULT hr;
4028 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4029 if(SUCCEEDED(hr)){
4030 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4031 ITypeInfo_Release(pTInfo);
4032 return hr;
4034 WARN("Could not search inherited interface!\n");
4036 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4037 return DISP_E_MEMBERNOTFOUND;
4040 /* ITypeInfo::GetDocumentation
4042 * Retrieves the documentation string, the complete Help file name and path,
4043 * and the context ID for the Help topic for a specified type description.
4045 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4046 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4047 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4049 ICOM_THIS( ITypeInfoImpl, iface);
4050 TLBFuncDesc * pFDesc;
4051 TLBVarDesc * pVDesc;
4052 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4053 " HelpContext(%p) HelpFile(%p)\n",
4054 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4055 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4056 if(pBstrName)
4057 *pBstrName=SysAllocString(This->Name);
4058 if(pBstrDocString)
4059 *pBstrDocString=SysAllocString(This->DocString);
4060 if(pdwHelpContext)
4061 *pdwHelpContext=This->dwHelpContext;
4062 if(pBstrHelpFile)
4063 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4064 return S_OK;
4065 }else {/* for a member */
4066 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4067 if(pFDesc->funcdesc.memid==memid){
4068 if(pBstrName)
4069 *pBstrName = SysAllocString(pFDesc->Name);
4070 if(pBstrDocString)
4071 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4072 if(pdwHelpContext)
4073 *pdwHelpContext=pFDesc->helpcontext;
4074 return S_OK;
4076 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4077 if(pVDesc->vardesc.memid==memid){
4078 FIXME("Not implemented\n");
4079 return S_OK;
4082 return TYPE_E_ELEMENTNOTFOUND;
4085 /* ITypeInfo::GetDllEntry
4087 * Retrieves a description or specification of an entry point for a function
4088 * in a DLL.
4090 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4091 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4092 WORD *pwOrdinal)
4094 ICOM_THIS( ITypeInfoImpl, iface);
4095 FIXME("(%p) stub!\n", This);
4096 return E_FAIL;
4099 /* ITypeInfo::GetRefTypeInfo
4101 * If a type description references other type descriptions, it retrieves
4102 * the referenced type descriptions.
4104 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4105 ITypeInfo2 *iface,
4106 HREFTYPE hRefType,
4107 ITypeInfo **ppTInfo)
4109 ICOM_THIS( ITypeInfoImpl, iface);
4110 HRESULT result = E_FAIL;
4113 if (hRefType == -1 &&
4114 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4115 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4117 /* when we meet a DUAL dispinterface, we must create the interface
4118 * version of it.
4120 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4123 /* the interface version contains the same information as the dispinterface
4124 * copy the contents of the structs.
4126 *pTypeInfoImpl = *This;
4127 pTypeInfoImpl->ref = 1;
4129 /* change the type to interface */
4130 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4132 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4134 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4136 result = S_OK;
4138 } else {
4139 TLBRefType *pRefType;
4140 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4141 if(pRefType->reference == hRefType)
4142 break;
4144 if(!pRefType)
4145 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4146 if(pRefType && hRefType != -1) {
4147 ITypeLib *pTLib;
4149 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4150 int Index;
4151 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4152 } else {
4153 if(pRefType->pImpTLInfo->pImpTypeLib) {
4154 TRACE("typeinfo in imported typelib that is already loaded\n");
4155 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4156 ITypeLib2_AddRef((ITypeLib*) pTLib);
4157 result = S_OK;
4158 } else {
4159 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4160 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4161 pRefType->pImpTLInfo->wVersionMajor,
4162 pRefType->pImpTLInfo->wVersionMinor,
4163 pRefType->pImpTLInfo->lcid,
4164 &pTLib);
4166 if(!SUCCEEDED(result)) {
4167 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4168 result=LoadTypeLib(libnam, &pTLib);
4169 SysFreeString(libnam);
4171 if(SUCCEEDED(result)) {
4172 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4173 ITypeLib2_AddRef(pTLib);
4177 if(SUCCEEDED(result)) {
4178 if(pRefType->index == TLB_REF_USE_GUID)
4179 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4180 &pRefType->guid,
4181 ppTInfo);
4182 else
4183 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4184 ppTInfo);
4189 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4190 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4191 return result;
4194 /* ITypeInfo::AddressOfMember
4196 * Retrieves the addresses of static functions or variables, such as those
4197 * defined in a DLL.
4199 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4200 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4202 ICOM_THIS( ITypeInfoImpl, iface);
4203 FIXME("(%p) stub!\n", This);
4204 return S_OK;
4207 /* ITypeInfo::CreateInstance
4209 * Creates a new instance of a type that describes a component object class
4210 * (coclass).
4212 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4213 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4215 ICOM_THIS( ITypeInfoImpl, iface);
4216 FIXME("(%p) stub!\n", This);
4217 return S_OK;
4220 /* ITypeInfo::GetMops
4222 * Retrieves marshaling information.
4224 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4225 BSTR *pBstrMops)
4227 ICOM_THIS( ITypeInfoImpl, iface);
4228 FIXME("(%p) stub!\n", This);
4229 return S_OK;
4232 /* ITypeInfo::GetContainingTypeLib
4234 * Retrieves the containing type library and the index of the type description
4235 * within that type library.
4237 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4238 ITypeLib * *ppTLib, UINT *pIndex)
4240 ICOM_THIS( ITypeInfoImpl, iface);
4241 if (!pIndex)
4242 return E_INVALIDARG;
4243 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4244 *pIndex=This->index;
4245 ITypeLib2_AddRef(*ppTLib);
4246 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4247 return S_OK;
4250 /* ITypeInfo::ReleaseTypeAttr
4252 * Releases a TYPEATTR previously returned by GetTypeAttr.
4255 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4256 TYPEATTR* pTypeAttr)
4258 ICOM_THIS( ITypeInfoImpl, iface);
4259 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4260 return S_OK;
4263 /* ITypeInfo::ReleaseFuncDesc
4265 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4267 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4268 ITypeInfo2 *iface,
4269 FUNCDESC *pFuncDesc)
4271 ICOM_THIS( ITypeInfoImpl, iface);
4272 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4273 return S_OK;
4276 /* ITypeInfo::ReleaseVarDesc
4278 * Releases a VARDESC previously returned by GetVarDesc.
4280 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4281 VARDESC *pVarDesc)
4283 ICOM_THIS( ITypeInfoImpl, iface);
4284 TRACE("(%p)->(%p)\n", This, pVarDesc);
4285 return S_OK;
4288 /* ITypeInfo2::GetTypeKind
4290 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4293 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4294 TYPEKIND *pTypeKind)
4296 ICOM_THIS( ITypeInfoImpl, iface);
4297 *pTypeKind=This->TypeAttr.typekind;
4298 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4299 return S_OK;
4302 /* ITypeInfo2::GetTypeFlags
4304 * Returns the type flags without any allocations. This returns a DWORD type
4305 * flag, which expands the type flags without growing the TYPEATTR (type
4306 * attribute).
4309 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4310 UINT *pTypeFlags)
4312 ICOM_THIS( ITypeInfoImpl, iface);
4313 *pTypeFlags=This->TypeAttr.wTypeFlags;
4314 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4315 return S_OK;
4318 /* ITypeInfo2::GetFuncIndexOfMemId
4319 * Binds to a specific member based on a known DISPID, where the member name
4320 * is not known (for example, when binding to a default member).
4323 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4324 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4326 ICOM_THIS( ITypeInfoImpl, iface);
4327 TLBFuncDesc *pFuncInfo;
4328 int i;
4329 HRESULT result;
4330 /* FIXME: should check for invKind??? */
4331 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4332 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4333 if(pFuncInfo){
4334 *pFuncIndex=i;
4335 result= S_OK;
4336 }else{
4337 *pFuncIndex=0;
4338 result=E_INVALIDARG;
4340 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4341 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4342 return result;
4345 /* TypeInfo2::GetVarIndexOfMemId
4347 * Binds to a specific member based on a known DISPID, where the member name
4348 * is not known (for example, when binding to a default member).
4351 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4352 MEMBERID memid, UINT *pVarIndex)
4354 ICOM_THIS( ITypeInfoImpl, iface);
4355 TLBVarDesc *pVarInfo;
4356 int i;
4357 HRESULT result;
4358 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4359 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4361 if(pVarInfo){
4362 *pVarIndex=i;
4363 result= S_OK;
4364 }else{
4365 *pVarIndex=0;
4366 result=E_INVALIDARG;
4368 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4369 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4370 return result;
4373 /* ITypeInfo2::GetCustData
4375 * Gets the custom data
4377 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4378 ITypeInfo2 * iface,
4379 REFGUID guid,
4380 VARIANT *pVarVal)
4382 ICOM_THIS( ITypeInfoImpl, iface);
4383 TLBCustData *pCData;
4385 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4386 if( IsEqualIID(guid, &pCData->guid)) break;
4388 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4390 if(pCData)
4392 VariantInit( pVarVal);
4393 VariantCopy( pVarVal, &pCData->data);
4394 return S_OK;
4396 return E_INVALIDARG; /* FIXME: correct? */
4399 /* ITypeInfo2::GetFuncCustData
4401 * Gets the custom data
4403 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4404 ITypeInfo2 * iface,
4405 UINT index,
4406 REFGUID guid,
4407 VARIANT *pVarVal)
4409 ICOM_THIS( ITypeInfoImpl, iface);
4410 TLBCustData *pCData=NULL;
4411 TLBFuncDesc * pFDesc;
4412 int i;
4413 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4414 pFDesc=pFDesc->next);
4416 if(pFDesc)
4417 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4418 if( IsEqualIID(guid, &pCData->guid)) break;
4420 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4422 if(pCData){
4423 VariantInit( pVarVal);
4424 VariantCopy( pVarVal, &pCData->data);
4425 return S_OK;
4427 return E_INVALIDARG; /* FIXME: correct? */
4430 /* ITypeInfo2::GetParamCustData
4432 * Gets the custom data
4434 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4435 ITypeInfo2 * iface,
4436 UINT indexFunc,
4437 UINT indexParam,
4438 REFGUID guid,
4439 VARIANT *pVarVal)
4441 ICOM_THIS( ITypeInfoImpl, iface);
4442 TLBCustData *pCData=NULL;
4443 TLBFuncDesc * pFDesc;
4444 int i;
4446 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4448 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4449 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4450 pCData = pCData->next)
4451 if( IsEqualIID(guid, &pCData->guid)) break;
4453 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4455 if(pCData)
4457 VariantInit( pVarVal);
4458 VariantCopy( pVarVal, &pCData->data);
4459 return S_OK;
4461 return E_INVALIDARG; /* FIXME: correct? */
4464 /* ITypeInfo2::GetVarCustData
4466 * Gets the custom data
4468 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4469 ITypeInfo2 * iface,
4470 UINT index,
4471 REFGUID guid,
4472 VARIANT *pVarVal)
4474 ICOM_THIS( ITypeInfoImpl, iface);
4475 TLBCustData *pCData=NULL;
4476 TLBVarDesc * pVDesc;
4477 int i;
4479 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4481 if(pVDesc)
4483 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4485 if( IsEqualIID(guid, &pCData->guid)) break;
4489 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4491 if(pCData)
4493 VariantInit( pVarVal);
4494 VariantCopy( pVarVal, &pCData->data);
4495 return S_OK;
4497 return E_INVALIDARG; /* FIXME: correct? */
4500 /* ITypeInfo2::GetImplCustData
4502 * Gets the custom data
4504 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4505 ITypeInfo2 * iface,
4506 UINT index,
4507 REFGUID guid,
4508 VARIANT *pVarVal)
4510 ICOM_THIS( ITypeInfoImpl, iface);
4511 TLBCustData *pCData=NULL;
4512 TLBImplType * pRDesc;
4513 int i;
4515 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4517 if(pRDesc)
4519 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4521 if( IsEqualIID(guid, &pCData->guid)) break;
4525 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4527 if(pCData)
4529 VariantInit( pVarVal);
4530 VariantCopy( pVarVal, &pCData->data);
4531 return S_OK;
4533 return E_INVALIDARG; /* FIXME: correct? */
4536 /* ITypeInfo2::GetDocumentation2
4538 * Retrieves the documentation string, the complete Help file name and path,
4539 * the localization context to use, and the context ID for the library Help
4540 * topic in the Help file.
4543 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4544 ITypeInfo2 * iface,
4545 MEMBERID memid,
4546 LCID lcid,
4547 BSTR *pbstrHelpString,
4548 DWORD *pdwHelpStringContext,
4549 BSTR *pbstrHelpStringDll)
4551 ICOM_THIS( ITypeInfoImpl, iface);
4552 TLBFuncDesc * pFDesc;
4553 TLBVarDesc * pVDesc;
4554 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4555 "HelpStringContext(%p) HelpStringDll(%p)\n",
4556 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4557 pbstrHelpStringDll );
4558 /* the help string should be obtained from the helpstringdll,
4559 * using the _DLLGetDocumentation function, based on the supplied
4560 * lcid. Nice to do sometime...
4562 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4563 if(pbstrHelpString)
4564 *pbstrHelpString=SysAllocString(This->Name);
4565 if(pdwHelpStringContext)
4566 *pdwHelpStringContext=This->dwHelpStringContext;
4567 if(pbstrHelpStringDll)
4568 *pbstrHelpStringDll=
4569 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4570 return S_OK;
4571 }else {/* for a member */
4572 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4573 if(pFDesc->funcdesc.memid==memid){
4574 if(pbstrHelpString)
4575 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4576 if(pdwHelpStringContext)
4577 *pdwHelpStringContext=pFDesc->HelpStringContext;
4578 if(pbstrHelpStringDll)
4579 *pbstrHelpStringDll=
4580 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4581 return S_OK;
4583 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4584 if(pVDesc->vardesc.memid==memid){
4585 if(pbstrHelpString)
4586 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4587 if(pdwHelpStringContext)
4588 *pdwHelpStringContext=pVDesc->HelpStringContext;
4589 if(pbstrHelpStringDll)
4590 *pbstrHelpStringDll=
4591 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4592 return S_OK;
4595 return TYPE_E_ELEMENTNOTFOUND;
4598 /* ITypeInfo2::GetAllCustData
4600 * Gets all custom data items for the Type info.
4603 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4604 ITypeInfo2 * iface,
4605 CUSTDATA *pCustData)
4607 ICOM_THIS( ITypeInfoImpl, iface);
4608 TLBCustData *pCData;
4609 int i;
4611 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4613 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4614 if(pCustData->prgCustData ){
4615 pCustData->cCustData=This->ctCustData;
4616 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4617 pCustData->prgCustData[i].guid=pCData->guid;
4618 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4620 }else{
4621 ERR(" OUT OF MEMORY! \n");
4622 return E_OUTOFMEMORY;
4624 return S_OK;
4627 /* ITypeInfo2::GetAllFuncCustData
4629 * Gets all custom data items for the specified Function
4632 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4633 ITypeInfo2 * iface,
4634 UINT index,
4635 CUSTDATA *pCustData)
4637 ICOM_THIS( ITypeInfoImpl, iface);
4638 TLBCustData *pCData;
4639 TLBFuncDesc * pFDesc;
4640 int i;
4641 TRACE("(%p) index %d\n", This, index);
4642 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4643 pFDesc=pFDesc->next)
4645 if(pFDesc){
4646 pCustData->prgCustData =
4647 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4648 if(pCustData->prgCustData ){
4649 pCustData->cCustData=pFDesc->ctCustData;
4650 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4651 pCData = pCData->next){
4652 pCustData->prgCustData[i].guid=pCData->guid;
4653 VariantCopy(& pCustData->prgCustData[i].varValue,
4654 & pCData->data);
4656 }else{
4657 ERR(" OUT OF MEMORY! \n");
4658 return E_OUTOFMEMORY;
4660 return S_OK;
4662 return TYPE_E_ELEMENTNOTFOUND;
4665 /* ITypeInfo2::GetAllParamCustData
4667 * Gets all custom data items for the Functions
4670 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4671 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4673 ICOM_THIS( ITypeInfoImpl, iface);
4674 TLBCustData *pCData=NULL;
4675 TLBFuncDesc * pFDesc;
4676 int i;
4677 TRACE("(%p) index %d\n", This, indexFunc);
4678 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4679 pFDesc=pFDesc->next)
4681 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4682 pCustData->prgCustData =
4683 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4684 sizeof(CUSTDATAITEM));
4685 if(pCustData->prgCustData ){
4686 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
4687 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
4688 pCData; i++, pCData = pCData->next){
4689 pCustData->prgCustData[i].guid=pCData->guid;
4690 VariantCopy(& pCustData->prgCustData[i].varValue,
4691 & pCData->data);
4693 }else{
4694 ERR(" OUT OF MEMORY! \n");
4695 return E_OUTOFMEMORY;
4697 return S_OK;
4699 return TYPE_E_ELEMENTNOTFOUND;
4702 /* ITypeInfo2::GetAllVarCustData
4704 * Gets all custom data items for the specified Variable
4707 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
4708 UINT index, CUSTDATA *pCustData)
4710 ICOM_THIS( ITypeInfoImpl, iface);
4711 TLBCustData *pCData;
4712 TLBVarDesc * pVDesc;
4713 int i;
4714 TRACE("(%p) index %d\n", This, index);
4715 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
4716 pVDesc=pVDesc->next)
4718 if(pVDesc){
4719 pCustData->prgCustData =
4720 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
4721 if(pCustData->prgCustData ){
4722 pCustData->cCustData=pVDesc->ctCustData;
4723 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
4724 pCData = pCData->next){
4725 pCustData->prgCustData[i].guid=pCData->guid;
4726 VariantCopy(& pCustData->prgCustData[i].varValue,
4727 & pCData->data);
4729 }else{
4730 ERR(" OUT OF MEMORY! \n");
4731 return E_OUTOFMEMORY;
4733 return S_OK;
4735 return TYPE_E_ELEMENTNOTFOUND;
4738 /* ITypeInfo2::GetAllImplCustData
4740 * Gets all custom data items for the specified implementation type
4743 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
4744 ITypeInfo2 * iface,
4745 UINT index,
4746 CUSTDATA *pCustData)
4748 ICOM_THIS( ITypeInfoImpl, iface);
4749 TLBCustData *pCData;
4750 TLBImplType * pRDesc;
4751 int i;
4752 TRACE("(%p) index %d\n", This, index);
4753 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
4754 pRDesc=pRDesc->next)
4756 if(pRDesc){
4757 pCustData->prgCustData =
4758 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
4759 if(pCustData->prgCustData ){
4760 pCustData->cCustData=pRDesc->ctCustData;
4761 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
4762 pCData = pCData->next){
4763 pCustData->prgCustData[i].guid=pCData->guid;
4764 VariantCopy(& pCustData->prgCustData[i].varValue,
4765 & pCData->data);
4767 }else{
4768 ERR(" OUT OF MEMORY! \n");
4769 return E_OUTOFMEMORY;
4771 return S_OK;
4773 return TYPE_E_ELEMENTNOTFOUND;
4776 static ICOM_VTABLE(ITypeInfo2) tinfvt =
4778 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4780 ITypeInfo_fnQueryInterface,
4781 ITypeInfo_fnAddRef,
4782 ITypeInfo_fnRelease,
4784 ITypeInfo_fnGetTypeAttr,
4785 ITypeInfo_fnGetTypeComp,
4786 ITypeInfo_fnGetFuncDesc,
4787 ITypeInfo_fnGetVarDesc,
4788 ITypeInfo_fnGetNames,
4789 ITypeInfo_fnGetRefTypeOfImplType,
4790 ITypeInfo_fnGetImplTypeFlags,
4791 ITypeInfo_fnGetIDsOfNames,
4792 ITypeInfo_fnInvoke,
4793 ITypeInfo_fnGetDocumentation,
4794 ITypeInfo_fnGetDllEntry,
4795 ITypeInfo_fnGetRefTypeInfo,
4796 ITypeInfo_fnAddressOfMember,
4797 ITypeInfo_fnCreateInstance,
4798 ITypeInfo_fnGetMops,
4799 ITypeInfo_fnGetContainingTypeLib,
4800 ITypeInfo_fnReleaseTypeAttr,
4801 ITypeInfo_fnReleaseFuncDesc,
4802 ITypeInfo_fnReleaseVarDesc,
4804 ITypeInfo2_fnGetTypeKind,
4805 ITypeInfo2_fnGetTypeFlags,
4806 ITypeInfo2_fnGetFuncIndexOfMemId,
4807 ITypeInfo2_fnGetVarIndexOfMemId,
4808 ITypeInfo2_fnGetCustData,
4809 ITypeInfo2_fnGetFuncCustData,
4810 ITypeInfo2_fnGetParamCustData,
4811 ITypeInfo2_fnGetVarCustData,
4812 ITypeInfo2_fnGetImplTypeCustData,
4813 ITypeInfo2_fnGetDocumentation2,
4814 ITypeInfo2_fnGetAllCustData,
4815 ITypeInfo2_fnGetAllFuncCustData,
4816 ITypeInfo2_fnGetAllParamCustData,
4817 ITypeInfo2_fnGetAllVarCustData,
4818 ITypeInfo2_fnGetAllImplTypeCustData,