The DISPPARAMS parameter array is a reverse-order array.
[wine/hacks.git] / dlls / oleaut32 / typelib.c
blob5e070e37179f46d8644655c4216de7f2c0ccae5e
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);
1836 ITypeLib2_AddRef(*ppTypeLib);
1838 else if ( dwSignature == SLTG_SIGNATURE)
1840 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1841 ITypeLib2_AddRef(*ppTypeLib);
1843 UnmapViewOfFile(pBase);
1845 CloseHandle(hMapping);
1847 CloseHandle(hFile);
1850 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1852 /* find the typelibrary resource*/
1853 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
1854 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1855 if (hinstDLL)
1857 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
1858 "TYPELIB");
1859 if (hrsrc)
1861 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1862 if (hGlobal)
1864 LPVOID pBase = LockResource(hGlobal);
1865 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1867 if (pBase)
1869 /* try to load as incore resource */
1870 dwSignature = *((DWORD*) pBase);
1871 if ( dwSignature == MSFT_SIGNATURE)
1873 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1874 ITypeLib2_AddRef(*ppTypeLib);
1876 else if ( dwSignature == SLTG_SIGNATURE)
1878 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1879 ITypeLib2_AddRef(*ppTypeLib);
1881 else
1883 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
1886 FreeResource( hGlobal );
1889 FreeLibrary(hinstDLL);
1893 if(*ppTypeLib)
1894 ret = S_OK;
1895 else
1896 ERR("Loading of typelib %s failed with error 0x%08lx\n",
1897 debugstr_w(pszFileName), GetLastError());
1899 return ret;
1902 /*================== ITypeLib(2) Methods ===================================*/
1904 /****************************************************************************
1905 * ITypeLib2_Constructor_MSFT
1907 * loading an MSFT typelib from an in-memory image
1909 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
1911 TLBContext cx;
1912 long lPSegDir;
1913 MSFT_Header tlbHeader;
1914 MSFT_SegDir tlbSegDir;
1915 ITypeLibImpl * pTypeLibImpl;
1917 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
1919 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
1920 if (!pTypeLibImpl) return NULL;
1922 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
1923 pTypeLibImpl->ref = 1;
1925 /* get pointer to beginning of typelib data */
1926 cx.pos = 0;
1927 cx.oStart=0;
1928 cx.mapping = pLib;
1929 cx.pLibInfo = pTypeLibImpl;
1930 cx.length = dwTLBLength;
1932 /* read header */
1933 MSFT_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
1934 TRACE("header:\n");
1935 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
1936 if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
1937 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
1938 return NULL;
1940 /* there is a small amount of information here until the next important
1941 * part:
1942 * the segment directory . Try to calculate the amount of data */
1943 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
1945 /* now read the segment directory */
1946 TRACE("read segment directory (at %ld)\n",lPSegDir);
1947 MSFT_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
1948 cx.pTblDir = &tlbSegDir;
1950 /* just check two entries */
1951 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
1953 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
1954 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
1955 return NULL;
1958 /* now fill our internal data */
1959 /* TLIBATTR fields */
1960 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
1961 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;
1962 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
1963 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
1964 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
1965 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
1967 /* name, eventually add to a hash table */
1968 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
1970 /* help info */
1971 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
1972 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
1974 if( tlbHeader.varflags & HELPDLLFLAG)
1976 int offset;
1977 MSFT_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
1978 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
1981 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
1983 /* custom data */
1984 if(tlbHeader.CustomDataOffset >= 0)
1986 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
1989 /* fill in typedescriptions */
1990 if(tlbSegDir.pTypdescTab.length > 0)
1992 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
1993 INT16 td[4];
1994 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
1995 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
1996 for(i=0; i<cTD; )
1998 /* FIXME: add several sanity checks here */
1999 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2000 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2002 /* FIXME: check safearray */
2003 if(td[3] < 0)
2004 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2005 else
2006 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2008 else if(td[0] == VT_CARRAY)
2010 /* array descr table here */
2011 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2013 else if(td[0] == VT_USERDEFINED)
2015 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2017 if(++i<cTD) MSFT_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
2020 /* second time around to fill the array subscript info */
2021 for(i=0;i<cTD;i++)
2023 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2024 if(tlbSegDir.pArrayDescriptions.offset>0)
2026 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2027 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2029 if(td[1]<0)
2030 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2031 else
2032 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2034 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2036 for(j = 0; j<td[2]; j++)
2038 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2039 sizeof(INT), &cx, DO_NOT_SEEK);
2040 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2041 sizeof(INT), &cx, DO_NOT_SEEK);
2044 else
2046 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2047 ERR("didn't find array description data\n");
2052 /* imported type libs */
2053 if(tlbSegDir.pImpFiles.offset>0)
2055 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2056 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2057 UINT16 size;
2059 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2061 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2062 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2063 MSFT_Read(&oGuid, sizeof(INT), &cx, offset);
2065 MSFT_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2066 MSFT_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2067 MSFT_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2068 MSFT_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2070 size >>= 2;
2071 (*ppImpLib)->name = TLB_Alloc(size+1);
2072 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2073 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2074 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2076 ppImpLib = &(*ppImpLib)->next;
2080 /* type info's */
2081 if(tlbHeader.nrtypeinfos >= 0 )
2083 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2084 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2085 int i;
2087 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2089 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2091 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2092 ppTI = &((*ppTI)->next);
2093 (pTypeLibImpl->TypeInfoCount)++;
2097 TRACE("(%p)\n", pTypeLibImpl);
2098 return (ITypeLib2*) pTypeLibImpl;
2102 static BSTR TLB_MultiByteToBSTR(char *ptr)
2104 DWORD len;
2105 WCHAR *nameW;
2106 BSTR ret;
2108 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2109 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2110 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2111 ret = SysAllocString(nameW);
2112 HeapFree(GetProcessHeap(), 0, nameW);
2113 return ret;
2116 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2118 char b[3];
2119 int i;
2120 short s;
2122 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2123 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2124 return FALSE;
2127 guid->Data4[0] = s >> 8;
2128 guid->Data4[1] = s & 0xff;
2130 b[2] = '\0';
2131 for(i = 0; i < 6; i++) {
2132 memcpy(b, str + 24 + 2 * i, 2);
2133 guid->Data4[i + 2] = strtol(b, NULL, 16);
2135 return TRUE;
2138 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2140 WORD bytelen;
2141 DWORD len;
2142 WCHAR *nameW;
2144 *pBstr = NULL;
2145 bytelen = *(WORD*)ptr;
2146 if(bytelen == 0xffff) return 2;
2147 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2148 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2149 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2150 *pBstr = SysAllocStringLen(nameW, len);
2151 HeapFree(GetProcessHeap(), 0, nameW);
2152 return bytelen + 2;
2155 static WORD SLTG_ReadStringA(char *ptr, char **str)
2157 WORD bytelen;
2159 *str = NULL;
2160 bytelen = *(WORD*)ptr;
2161 if(bytelen == 0xffff) return 2;
2162 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2163 memcpy(*str, ptr + 2, bytelen);
2164 (*str)[bytelen] = '\0';
2165 return bytelen + 2;
2168 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2170 char *ptr = pLibBlk;
2171 WORD w;
2173 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2174 FIXME("libblk magic = %04x\n", w);
2175 return 0;
2178 ptr += 6;
2179 if((w = *(WORD*)ptr) != 0xffff) {
2180 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2181 ptr += w;
2183 ptr += 2;
2185 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2187 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2189 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2190 ptr += 4;
2192 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2193 ptr += 2;
2195 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2196 ptr += 2;
2198 ptr += 4; /* skip res12 */
2200 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2201 ptr += 2;
2203 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2204 ptr += 2;
2206 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2207 ptr += 2;
2209 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2210 ptr += sizeof(GUID);
2212 return ptr - (char*)pLibBlk;
2215 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2217 BOOL done = FALSE;
2218 TYPEDESC *pTD = &pElem->tdesc;
2220 /* Handle [in/out] first */
2221 if((*pType & 0xc000) == 0xc000)
2222 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2223 else if(*pType & 0x8000)
2224 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2225 else if(*pType & 0x4000)
2226 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2227 else
2228 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2230 if(*pType & 0x2000)
2231 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2233 if(*pType & 0x80)
2234 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2236 while(!done) {
2237 if((*pType & 0xe00) == 0xe00) {
2238 pTD->vt = VT_PTR;
2239 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2240 sizeof(TYPEDESC));
2241 pTD = pTD->u.lptdesc;
2243 switch(*pType & 0x7f) {
2244 case VT_PTR:
2245 pTD->vt = VT_PTR;
2246 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2247 sizeof(TYPEDESC));
2248 pTD = pTD->u.lptdesc;
2249 break;
2251 case VT_USERDEFINED:
2252 pTD->vt = VT_USERDEFINED;
2253 pTD->u.hreftype = *(++pType) / 4;
2254 done = TRUE;
2255 break;
2257 case VT_CARRAY:
2259 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2260 array */
2262 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2264 pTD->vt = VT_CARRAY;
2265 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2266 sizeof(ARRAYDESC) +
2267 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2268 pTD->u.lpadesc->cDims = pSA->cDims;
2269 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2270 pSA->cDims * sizeof(SAFEARRAYBOUND));
2272 pTD = &pTD->u.lpadesc->tdescElem;
2273 break;
2276 case VT_SAFEARRAY:
2278 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2279 useful? */
2281 pType++;
2282 pTD->vt = VT_SAFEARRAY;
2283 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2284 sizeof(TYPEDESC));
2285 pTD = pTD->u.lptdesc;
2286 break;
2288 default:
2289 pTD->vt = *pType & 0x7f;
2290 done = TRUE;
2291 break;
2293 pType++;
2295 return pType;
2299 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2300 char *pNameTable)
2302 int ref;
2303 char *name;
2304 TLBRefType **ppRefType;
2306 if(pRef->magic != SLTG_REF_MAGIC) {
2307 FIXME("Ref magic = %x\n", pRef->magic);
2308 return;
2310 name = ( (char*)(&pRef->names) + pRef->number);
2312 ppRefType = &pTI->reflist;
2313 for(ref = 0; ref < pRef->number >> 3; ref++) {
2314 char *refname;
2315 unsigned int lib_offs, type_num;
2317 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2318 sizeof(**ppRefType));
2320 name += SLTG_ReadStringA(name, &refname);
2321 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2322 FIXME("Can't sscanf ref\n");
2323 if(lib_offs != 0xffff) {
2324 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2326 while(*import) {
2327 if((*import)->offset == lib_offs)
2328 break;
2329 import = &(*import)->next;
2331 if(!*import) {
2332 char fname[MAX_PATH+1];
2333 int len;
2335 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2336 sizeof(**import));
2337 (*import)->offset = lib_offs;
2338 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2339 &(*import)->guid);
2340 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2341 &(*import)->wVersionMajor,
2342 &(*import)->wVersionMinor,
2343 &(*import)->lcid, fname) != 4) {
2344 FIXME("can't sscanf ref %s\n",
2345 pNameTable + lib_offs + 40);
2347 len = strlen(fname);
2348 if(fname[len-1] != '#')
2349 FIXME("fname = %s\n", fname);
2350 fname[len-1] = '\0';
2351 (*import)->name = TLB_MultiByteToBSTR(fname);
2353 (*ppRefType)->pImpTLInfo = *import;
2354 } else { /* internal ref */
2355 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2357 (*ppRefType)->reference = ref;
2358 (*ppRefType)->index = type_num;
2360 HeapFree(GetProcessHeap(), 0, refname);
2361 ppRefType = &(*ppRefType)->next;
2363 if((BYTE)*name != SLTG_REF_MAGIC)
2364 FIXME("End of ref block magic = %x\n", *name);
2365 dump_TLBRefType(pTI->reflist);
2368 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2369 BOOL OneOnly)
2371 SLTG_ImplInfo *info;
2372 TLBImplType **ppImplType = &pTI->impltypelist;
2373 /* I don't really get this structure, usually it's 0x16 bytes
2374 long, but iuser.tlb contains some that are 0x18 bytes long.
2375 That's ok because we can use the next ptr to jump to the next
2376 one. But how do we know the length of the last one? The WORD
2377 at offs 0x8 might be the clue. For now I'm just assuming that
2378 the last one is the regular 0x16 bytes. */
2380 info = (SLTG_ImplInfo*)pBlk;
2381 while(1) {
2382 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2383 sizeof(**ppImplType));
2384 (*ppImplType)->hRef = info->ref;
2385 (*ppImplType)->implflags = info->impltypeflags;
2386 pTI->TypeAttr.cImplTypes++;
2387 ppImplType = &(*ppImplType)->next;
2389 if(info->next == 0xffff)
2390 break;
2391 if(OneOnly)
2392 FIXME("Interface inheriting more than one interface\n");
2393 info = (SLTG_ImplInfo*)(pBlk + info->next);
2395 info++; /* see comment at top of function */
2396 return (char*)info;
2399 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2400 char *pNameTable)
2402 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2403 SLTG_MemberHeader *pMemHeader;
2404 char *pFirstItem, *pNextItem;
2406 if(pTIHeader->href_table != 0xffffffff) {
2407 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2408 pNameTable);
2412 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2414 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2416 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2417 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2420 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2424 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2425 char *pNameTable)
2427 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2428 SLTG_MemberHeader *pMemHeader;
2429 SLTG_Function *pFunc;
2430 char *pFirstItem, *pNextItem;
2431 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2432 int num = 0;
2434 if(pTIHeader->href_table != 0xffffffff) {
2435 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2436 pNameTable);
2439 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2441 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2443 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2444 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2447 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2448 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2450 int param;
2451 WORD *pType, *pArg;
2453 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2454 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2455 FIXME("func magic = %02x\n", pFunc->magic);
2456 return NULL;
2458 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2459 sizeof(**ppFuncDesc));
2460 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2462 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2463 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2464 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2465 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2466 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2467 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2469 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2470 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2472 if(pFunc->retnextopt & 0x80)
2473 pType = &pFunc->rettype;
2474 else
2475 pType = (WORD*)(pFirstItem + pFunc->rettype);
2478 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2480 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2481 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2482 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2483 (*ppFuncDesc)->pParamDesc =
2484 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2485 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2487 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2489 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2490 char *paramName = pNameTable + *pArg;
2491 BOOL HaveOffs;
2492 /* If arg type follows then paramName points to the 2nd
2493 letter of the name, else the next WORD is an offset to
2494 the arg type and paramName points to the first letter.
2495 So let's take one char off paramName and see if we're
2496 pointing at an alpha-numeric char. However if *pArg is
2497 0xffff or 0xfffe then the param has no name, the former
2498 meaning that the next WORD is the type, the latter
2499 meaning the the next WORD is an offset to the type. */
2501 HaveOffs = FALSE;
2502 if(*pArg == 0xffff)
2503 paramName = NULL;
2504 else if(*pArg == 0xfffe) {
2505 paramName = NULL;
2506 HaveOffs = TRUE;
2508 else if(!isalnum(*(paramName-1)))
2509 HaveOffs = TRUE;
2511 pArg++;
2513 if(HaveOffs) { /* the next word is an offset to type */
2514 pType = (WORD*)(pFirstItem + *pArg);
2515 SLTG_DoType(pType, pFirstItem,
2516 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2517 pArg++;
2518 } else {
2519 if(paramName)
2520 paramName--;
2521 pArg = SLTG_DoType(pArg, pFirstItem,
2522 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2525 /* Are we an optional param ? */
2526 if((*ppFuncDesc)->funcdesc.cParams - param <=
2527 (*ppFuncDesc)->funcdesc.cParamsOpt)
2528 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2530 if(paramName) {
2531 (*ppFuncDesc)->pParamDesc[param].Name =
2532 TLB_MultiByteToBSTR(paramName);
2536 ppFuncDesc = &((*ppFuncDesc)->next);
2537 if(pFunc->next == 0xffff) break;
2539 pTI->TypeAttr.cFuncs = num;
2540 dump_TLBFuncDesc(pTI->funclist);
2541 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2544 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2545 char *pNameTable)
2547 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2548 SLTG_MemberHeader *pMemHeader;
2549 SLTG_RecordItem *pItem;
2550 char *pFirstItem;
2551 TLBVarDesc **ppVarDesc = &pTI->varlist;
2552 int num = 0;
2553 WORD *pType;
2554 char buf[300];
2556 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2558 pFirstItem = (char*)(pMemHeader + 1);
2559 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2560 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2561 if(pItem->magic != SLTG_RECORD_MAGIC) {
2562 FIXME("record magic = %02x\n", pItem->magic);
2563 return NULL;
2565 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2566 sizeof(**ppVarDesc));
2567 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2568 (*ppVarDesc)->vardesc.memid = pItem->memid;
2569 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2570 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2572 if(pItem->typepos == 0x02)
2573 pType = &pItem->type;
2574 else if(pItem->typepos == 0x00)
2575 pType = (WORD*)(pFirstItem + pItem->type);
2576 else {
2577 FIXME("typepos = %02x\n", pItem->typepos);
2578 break;
2581 SLTG_DoType(pType, pFirstItem,
2582 &(*ppVarDesc)->vardesc.elemdescVar);
2584 /* FIXME("helpcontext, helpstring\n"); */
2586 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2588 ppVarDesc = &((*ppVarDesc)->next);
2589 if(pItem->next == 0xffff) break;
2591 pTI->TypeAttr.cVars = num;
2592 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2595 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2596 char *pNameTable)
2598 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2599 SLTG_MemberHeader *pMemHeader;
2600 SLTG_EnumItem *pItem;
2601 char *pFirstItem;
2602 TLBVarDesc **ppVarDesc = &pTI->varlist;
2603 int num = 0;
2605 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2607 pFirstItem = (char*)(pMemHeader + 1);
2608 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2609 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2610 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2611 FIXME("enumitem magic = %04x\n", pItem->magic);
2612 return NULL;
2614 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2615 sizeof(**ppVarDesc));
2616 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2617 (*ppVarDesc)->vardesc.memid = pItem->memid;
2618 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2619 sizeof(VARIANT));
2620 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2621 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2622 *(INT*)(pItem->value + pFirstItem);
2623 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2624 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2625 /* FIXME("helpcontext, helpstring\n"); */
2627 ppVarDesc = &((*ppVarDesc)->next);
2628 if(pItem->next == 0xffff) break;
2630 pTI->TypeAttr.cVars = num;
2631 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2634 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2635 managable copy of it into this */
2636 typedef struct {
2637 WORD small_no;
2638 char *index_name;
2639 char *other_name;
2640 WORD res1a;
2641 WORD name_offs;
2642 WORD more_bytes;
2643 char *extra;
2644 WORD res20;
2645 DWORD helpcontext;
2646 WORD res26;
2647 GUID uuid;
2648 } SLTG_InternalOtherTypeInfo;
2650 /****************************************************************************
2651 * ITypeLib2_Constructor_SLTG
2653 * loading a SLTG typelib from an in-memory image
2655 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2657 ITypeLibImpl *pTypeLibImpl;
2658 SLTG_Header *pHeader;
2659 SLTG_BlkEntry *pBlkEntry;
2660 SLTG_Magic *pMagic;
2661 SLTG_Index *pIndex;
2662 SLTG_Pad9 *pPad9;
2663 LPVOID pBlk, pFirstBlk;
2664 SLTG_LibBlk *pLibBlk;
2665 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2666 char *pAfterOTIBlks = NULL;
2667 char *pNameTable, *ptr;
2668 int i;
2669 DWORD len, order;
2670 ITypeInfoImpl **ppTypeInfoImpl;
2672 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2674 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2675 if (!pTypeLibImpl) return NULL;
2677 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2678 pTypeLibImpl->ref = 1;
2680 pHeader = pLib;
2682 TRACE("header:\n");
2683 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2684 pHeader->nrOfFileBlks );
2685 if (memcmp(&pHeader->SLTG_magic, TLBMAGIC1, 4)) {
2686 FIXME("Header type magic 0x%08lx not supported.\n",
2687 pHeader->SLTG_magic);
2688 return NULL;
2691 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2692 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2694 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2695 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2697 /* Next we have a magic block */
2698 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2700 /* Let's see if we're still in sync */
2701 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2702 sizeof(SLTG_COMPOBJ_MAGIC))) {
2703 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2704 return NULL;
2706 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2707 sizeof(SLTG_DIR_MAGIC))) {
2708 FIXME("dir magic = %s\n", pMagic->dir_magic);
2709 return NULL;
2712 pIndex = (SLTG_Index*)(pMagic+1);
2714 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2716 pFirstBlk = (LPVOID)(pPad9 + 1);
2718 /* We'll set up a ptr to the main library block, which is the last one. */
2720 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2721 pBlkEntry[order].next != 0;
2722 order = pBlkEntry[order].next - 1, i++) {
2723 pBlk += pBlkEntry[order].len;
2725 pLibBlk = pBlk;
2727 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2729 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2730 interspersed */
2732 len += 0x40;
2734 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2736 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2737 sizeof(*pOtherTypeInfoBlks) *
2738 pTypeLibImpl->TypeInfoCount);
2741 ptr = (char*)pLibBlk + len;
2743 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2744 WORD w, extra;
2745 len = 0;
2747 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2749 w = *(WORD*)(ptr + 2);
2750 if(w != 0xffff) {
2751 len += w;
2752 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2753 w+1);
2754 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2755 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2757 w = *(WORD*)(ptr + 4 + len);
2758 if(w != 0xffff) {
2759 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2760 len += w;
2761 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2762 w+1);
2763 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2764 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2766 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2767 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2768 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2769 if(extra) {
2770 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2771 extra);
2772 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2773 len += extra;
2775 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2776 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2777 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2778 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2779 len += sizeof(SLTG_OtherTypeInfo);
2780 ptr += len;
2783 pAfterOTIBlks = ptr;
2785 /* Skip this WORD and get the next DWORD */
2786 len = *(DWORD*)(pAfterOTIBlks + 2);
2788 /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a
2789 magic dust and we should be pointing at the beginning of the name
2790 table */
2792 pNameTable = (char*)pLibBlk + len + 0x216;
2794 pNameTable += 2;
2796 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
2798 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
2801 /* Hopefully we now have enough ptrs set up to actually read in
2802 some TypeInfos. It's not clear which order to do them in, so
2803 I'll just follow the links along the BlkEntry chain and read
2804 them in in the order in which they're in the file */
2806 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
2808 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2809 pBlkEntry[order].next != 0;
2810 order = pBlkEntry[order].next - 1, i++) {
2812 SLTG_TypeInfoHeader *pTIHeader;
2813 SLTG_TypeInfoTail *pTITail;
2815 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
2816 pOtherTypeInfoBlks[i].index_name)) {
2817 FIXME("Index strings don't match\n");
2818 return NULL;
2821 pTIHeader = pBlk;
2822 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
2823 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
2824 return NULL;
2826 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
2827 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
2828 (*ppTypeInfoImpl)->index = i;
2829 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
2830 pOtherTypeInfoBlks[i].name_offs +
2831 pNameTable);
2832 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
2833 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
2834 sizeof(GUID));
2835 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
2836 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
2837 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
2838 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
2839 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
2841 if((pTIHeader->typeflags1 & 7) != 2)
2842 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
2843 if(pTIHeader->typeflags3 != 2)
2844 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
2846 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2847 debugstr_w((*ppTypeInfoImpl)->Name),
2848 typekind_desc[pTIHeader->typekind],
2849 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
2850 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
2852 switch(pTIHeader->typekind) {
2853 case TKIND_ENUM:
2854 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
2855 break;
2857 case TKIND_RECORD:
2858 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
2859 break;
2861 case TKIND_INTERFACE:
2862 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
2863 break;
2865 case TKIND_COCLASS:
2866 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
2867 break;
2869 default:
2870 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
2871 pTITail = NULL;
2872 break;
2876 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
2877 but we've already set those */
2878 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
2879 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
2880 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
2882 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
2883 pBlk += pBlkEntry[order].len;
2886 if(i != pTypeLibImpl->TypeInfoCount) {
2887 FIXME("Somehow processed %d TypeInfos\n", i);
2888 return NULL;
2891 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
2892 return (ITypeLib2*)pTypeLibImpl;
2895 /* ITypeLib::QueryInterface
2897 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
2898 ITypeLib2 * iface,
2899 REFIID riid,
2900 VOID **ppvObject)
2902 ICOM_THIS( ITypeLibImpl, iface);
2904 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
2906 *ppvObject=NULL;
2907 if(IsEqualIID(riid, &IID_IUnknown) ||
2908 IsEqualIID(riid,&IID_ITypeLib)||
2909 IsEqualIID(riid,&IID_ITypeLib2))
2911 *ppvObject = This;
2914 if(*ppvObject)
2916 ITypeLib2_AddRef(iface);
2917 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
2918 return S_OK;
2920 TRACE("-- Interface: E_NOINTERFACE\n");
2921 return E_NOINTERFACE;
2924 /* ITypeLib::AddRef
2926 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
2928 ICOM_THIS( ITypeLibImpl, iface);
2930 TRACE("(%p)->ref is %u\n",This, This->ref);
2932 return ++(This->ref);
2935 /* ITypeLib::Release
2937 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
2939 ICOM_THIS( ITypeLibImpl, iface);
2941 --(This->ref);
2943 TRACE("(%p)->(%u)\n",This, This->ref);
2945 if (!This->ref)
2947 /* fixme destroy child objects */
2949 TRACE(" destroying ITypeLib(%p)\n",This);
2951 if (This->Name)
2953 SysFreeString(This->Name);
2954 This->Name = NULL;
2957 if (This->DocString)
2959 SysFreeString(This->DocString);
2960 This->DocString = NULL;
2963 if (This->HelpFile)
2965 SysFreeString(This->HelpFile);
2966 This->HelpFile = NULL;
2969 if (This->HelpStringDll)
2971 SysFreeString(This->HelpStringDll);
2972 This->HelpStringDll = NULL;
2975 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
2976 HeapFree(GetProcessHeap(),0,This);
2977 return 0;
2980 return This->ref;
2983 /* ITypeLib::GetTypeInfoCount
2985 * Returns the number of type descriptions in the type library
2987 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
2989 ICOM_THIS( ITypeLibImpl, iface);
2990 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
2991 return This->TypeInfoCount;
2994 /* ITypeLib::GetTypeInfo
2996 * retrieves the specified type description in the library.
2998 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
2999 ITypeLib2 *iface,
3000 UINT index,
3001 ITypeInfo **ppTInfo)
3003 int i;
3005 ICOM_THIS( ITypeLibImpl, iface);
3006 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3008 TRACE("(%p)->(index=%d) \n", This, index);
3010 if (!ppTInfo) return E_INVALIDARG;
3012 /* search element n in list */
3013 for(i=0; i < index; i++)
3015 pTypeInfo = pTypeInfo->next;
3016 if (!pTypeInfo)
3018 TRACE("-- element not found\n");
3019 return TYPE_E_ELEMENTNOTFOUND;
3023 *ppTInfo = (ITypeInfo *) pTypeInfo;
3025 ITypeInfo_AddRef(*ppTInfo);
3026 TRACE("-- found (%p)\n",*ppTInfo);
3027 return S_OK;
3031 /* ITypeLibs::GetTypeInfoType
3033 * Retrieves the type of a type description.
3035 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3036 ITypeLib2 *iface,
3037 UINT index,
3038 TYPEKIND *pTKind)
3040 ICOM_THIS( ITypeLibImpl, iface);
3041 int i;
3042 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3044 TRACE("(%p) index %d \n",This, index);
3046 if(!pTKind) return E_INVALIDARG;
3048 /* search element n in list */
3049 for(i=0; i < index; i++)
3051 if(!pTInfo)
3053 TRACE("-- element not found\n");
3054 return TYPE_E_ELEMENTNOTFOUND;
3056 pTInfo = pTInfo->next;
3059 *pTKind = pTInfo->TypeAttr.typekind;
3060 TRACE("-- found Type (%d)\n", *pTKind);
3061 return S_OK;
3064 /* ITypeLib::GetTypeInfoOfGuid
3066 * Retrieves the type description that corresponds to the specified GUID.
3069 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3070 ITypeLib2 *iface,
3071 REFGUID guid,
3072 ITypeInfo **ppTInfo)
3074 ICOM_THIS( ITypeLibImpl, iface);
3075 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3077 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3079 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3081 /* search linked list for guid */
3082 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3084 pTypeInfo = pTypeInfo->next;
3086 if (!pTypeInfo)
3088 /* end of list reached */
3089 TRACE("-- element not found\n");
3090 return TYPE_E_ELEMENTNOTFOUND;
3094 TRACE("-- found (%p, %s)\n",
3095 pTypeInfo,
3096 debugstr_w(pTypeInfo->Name));
3098 *ppTInfo = (ITypeInfo*)pTypeInfo;
3099 ITypeInfo_AddRef(*ppTInfo);
3100 return S_OK;
3103 /* ITypeLib::GetLibAttr
3105 * Retrieves the structure that contains the library's attributes.
3108 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3109 ITypeLib2 *iface,
3110 LPTLIBATTR *ppTLibAttr)
3112 ICOM_THIS( ITypeLibImpl, iface);
3113 TRACE("(%p)\n",This);
3114 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3115 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3116 return S_OK;
3119 /* ITypeLib::GetTypeComp
3121 * Enables a client compiler to bind to a library's types, variables,
3122 * constants, and global functions.
3125 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3126 ITypeLib2 *iface,
3127 ITypeComp **ppTComp)
3129 ICOM_THIS( ITypeLibImpl, iface);
3130 FIXME("(%p): stub!\n",This);
3131 return E_NOTIMPL;
3134 /* ITypeLib::GetDocumentation
3136 * Retrieves the library's documentation string, the complete Help file name
3137 * and path, and the context identifier for the library Help topic in the Help
3138 * file.
3141 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3142 ITypeLib2 *iface,
3143 INT index,
3144 BSTR *pBstrName,
3145 BSTR *pBstrDocString,
3146 DWORD *pdwHelpContext,
3147 BSTR *pBstrHelpFile)
3149 ICOM_THIS( ITypeLibImpl, iface);
3151 HRESULT result = E_INVALIDARG;
3153 ITypeInfo *pTInfo;
3156 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3157 This, index,
3158 pBstrName, pBstrDocString,
3159 pdwHelpContext, pBstrHelpFile);
3161 if(index<0)
3163 /* documentation for the typelib */
3164 if(pBstrName && This->Name)
3166 *pBstrName = SysAllocString(This->Name);
3168 if (!(*pBstrName)) return STG_E_INSUFFICIENTMEMORY;
3170 if(pBstrDocString && This->DocString)
3172 *pBstrDocString = SysAllocString(This->DocString);
3174 if (!(*pBstrDocString)) return STG_E_INSUFFICIENTMEMORY;
3177 if(pdwHelpContext)
3179 *pdwHelpContext = This->dwHelpContext;
3181 if(pBstrHelpFile && This->HelpFile)
3183 *pBstrHelpFile = SysAllocString(This->HelpFile);
3185 if (!(*pBstrHelpFile)) return STG_E_INSUFFICIENTMEMORY;
3188 result = S_OK;
3190 else
3192 /* for a typeinfo */
3193 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3195 if(SUCCEEDED(result))
3197 result = ITypeInfo_GetDocumentation(pTInfo,
3198 MEMBERID_NIL,
3199 pBstrName,
3200 pBstrDocString,
3201 pdwHelpContext, pBstrHelpFile);
3203 ITypeInfo_Release(pTInfo);
3206 return result;
3209 /* ITypeLib::IsName
3211 * Indicates whether a passed-in string contains the name of a type or member
3212 * described in the library.
3215 static HRESULT WINAPI ITypeLib2_fnIsName(
3216 ITypeLib2 *iface,
3217 LPOLESTR szNameBuf,
3218 ULONG lHashVal,
3219 BOOL *pfName)
3221 ICOM_THIS( ITypeLibImpl, iface);
3222 ITypeInfoImpl *pTInfo;
3223 TLBFuncDesc *pFInfo;
3224 TLBVarDesc *pVInfo;
3225 int i;
3226 UINT nNameBufLen = SysStringLen(szNameBuf);
3228 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3229 pfName);
3231 *pfName=TRUE;
3232 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3233 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3234 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3235 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3236 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3237 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3238 goto ITypeLib2_fnIsName_exit;
3240 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3241 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3244 *pfName=FALSE;
3246 ITypeLib2_fnIsName_exit:
3247 TRACE("(%p)slow! search for %s: %s found!\n", This,
3248 debugstr_w(szNameBuf), *pfName?"NOT":"");
3250 return S_OK;
3253 /* ITypeLib::FindName
3255 * Finds occurrences of a type description in a type library. This may be used
3256 * to quickly verify that a name exists in a type library.
3259 static HRESULT WINAPI ITypeLib2_fnFindName(
3260 ITypeLib2 *iface,
3261 LPOLESTR szNameBuf,
3262 ULONG lHashVal,
3263 ITypeInfo **ppTInfo,
3264 MEMBERID *rgMemId,
3265 UINT16 *pcFound)
3267 ICOM_THIS( ITypeLibImpl, iface);
3268 ITypeInfoImpl *pTInfo;
3269 TLBFuncDesc *pFInfo;
3270 TLBVarDesc *pVInfo;
3271 int i,j = 0;
3273 UINT nNameBufLen = SysStringLen(szNameBuf);
3275 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3276 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3277 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3278 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3279 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3280 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3281 goto ITypeLib2_fnFindName_exit;
3283 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3284 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3285 continue;
3286 ITypeLib2_fnFindName_exit:
3287 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3288 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3289 j++;
3291 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3292 This, *pcFound, debugstr_w(szNameBuf), j);
3294 *pcFound=j;
3296 return S_OK;
3299 /* ITypeLib::ReleaseTLibAttr
3301 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3304 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3305 ITypeLib2 *iface,
3306 TLIBATTR *pTLibAttr)
3308 ICOM_THIS( ITypeLibImpl, iface);
3309 TRACE("freeing (%p)\n",This);
3310 HeapFree(GetProcessHeap(),0,pTLibAttr);
3314 /* ITypeLib2::GetCustData
3316 * gets the custom data
3318 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3319 ITypeLib2 * iface,
3320 REFGUID guid,
3321 VARIANT *pVarVal)
3323 ICOM_THIS( ITypeLibImpl, iface);
3324 TLBCustData *pCData;
3326 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3328 if( IsEqualIID(guid, &pCData->guid)) break;
3331 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3333 if(pCData)
3335 VariantInit( pVarVal);
3336 VariantCopy( pVarVal, &pCData->data);
3337 return S_OK;
3339 return E_INVALIDARG; /* FIXME: correct? */
3342 /* ITypeLib2::GetLibStatistics
3344 * Returns statistics about a type library that are required for efficient
3345 * sizing of hash tables.
3348 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3349 ITypeLib2 * iface,
3350 ULONG *pcUniqueNames,
3351 ULONG *pcchUniqueNames)
3353 ICOM_THIS( ITypeLibImpl, iface);
3355 FIXME("(%p): stub!\n", This);
3357 if(pcUniqueNames) *pcUniqueNames=1;
3358 if(pcchUniqueNames) *pcchUniqueNames=1;
3359 return S_OK;
3362 /* ITypeLib2::GetDocumentation2
3364 * Retrieves the library's documentation string, the complete Help file name
3365 * and path, the localization context to use, and the context ID for the
3366 * library Help topic in the Help file.
3369 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3370 ITypeLib2 * iface,
3371 INT index,
3372 LCID lcid,
3373 BSTR *pbstrHelpString,
3374 DWORD *pdwHelpStringContext,
3375 BSTR *pbstrHelpStringDll)
3377 ICOM_THIS( ITypeLibImpl, iface);
3378 HRESULT result;
3379 ITypeInfo *pTInfo;
3381 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3383 /* the help string should be obtained from the helpstringdll,
3384 * using the _DLLGetDocumentation function, based on the supplied
3385 * lcid. Nice to do sometime...
3387 if(index<0)
3389 /* documentation for the typelib */
3390 if(pbstrHelpString)
3391 *pbstrHelpString=SysAllocString(This->DocString);
3392 if(pdwHelpStringContext)
3393 *pdwHelpStringContext=This->dwHelpContext;
3394 if(pbstrHelpStringDll)
3395 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3397 result = S_OK;
3399 else
3401 /* for a typeinfo */
3402 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3404 if(SUCCEEDED(result))
3406 ITypeInfo2 * pTInfo2;
3407 result = ITypeInfo_QueryInterface(pTInfo,
3408 &IID_ITypeInfo2,
3409 (LPVOID*) &pTInfo2);
3411 if(SUCCEEDED(result))
3413 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3414 MEMBERID_NIL,
3415 lcid,
3416 pbstrHelpString,
3417 pdwHelpStringContext,
3418 pbstrHelpStringDll);
3420 ITypeInfo2_Release(pTInfo2);
3423 ITypeInfo_Release(pTInfo);
3426 return result;
3429 /* ITypeLib2::GetAllCustData
3431 * Gets all custom data items for the library.
3434 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3435 ITypeLib2 * iface,
3436 CUSTDATA *pCustData)
3438 ICOM_THIS( ITypeLibImpl, iface);
3439 TLBCustData *pCData;
3440 int i;
3441 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3442 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3443 if(pCustData->prgCustData ){
3444 pCustData->cCustData=This->ctCustData;
3445 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3446 pCustData->prgCustData[i].guid=pCData->guid;
3447 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3449 }else{
3450 ERR(" OUT OF MEMORY! \n");
3451 return E_OUTOFMEMORY;
3453 return S_OK;
3456 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3457 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3458 ITypeLib2_fnQueryInterface,
3459 ITypeLib2_fnAddRef,
3460 ITypeLib2_fnRelease,
3461 ITypeLib2_fnGetTypeInfoCount,
3462 ITypeLib2_fnGetTypeInfo,
3463 ITypeLib2_fnGetTypeInfoType,
3464 ITypeLib2_fnGetTypeInfoOfGuid,
3465 ITypeLib2_fnGetLibAttr,
3466 ITypeLib2_fnGetTypeComp,
3467 ITypeLib2_fnGetDocumentation,
3468 ITypeLib2_fnIsName,
3469 ITypeLib2_fnFindName,
3470 ITypeLib2_fnReleaseTLibAttr,
3472 ITypeLib2_fnGetCustData,
3473 ITypeLib2_fnGetLibStatistics,
3474 ITypeLib2_fnGetDocumentation2,
3475 ITypeLib2_fnGetAllCustData
3478 /*================== ITypeInfo(2) Methods ===================================*/
3479 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3481 ITypeInfoImpl * pTypeInfoImpl;
3483 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3484 if (pTypeInfoImpl)
3486 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3487 pTypeInfoImpl->ref=1;
3489 TRACE("(%p)\n", pTypeInfoImpl);
3490 return (ITypeInfo2*) pTypeInfoImpl;
3493 /* ITypeInfo::QueryInterface
3495 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3496 ITypeInfo2 *iface,
3497 REFIID riid,
3498 VOID **ppvObject)
3500 ICOM_THIS( ITypeLibImpl, iface);
3502 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3504 *ppvObject=NULL;
3505 if(IsEqualIID(riid, &IID_IUnknown) ||
3506 IsEqualIID(riid,&IID_ITypeInfo)||
3507 IsEqualIID(riid,&IID_ITypeInfo2))
3508 *ppvObject = This;
3510 if(*ppvObject){
3511 ITypeInfo_AddRef(iface);
3512 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3513 return S_OK;
3515 TRACE("-- Interface: E_NOINTERFACE\n");
3516 return E_NOINTERFACE;
3519 /* ITypeInfo::AddRef
3521 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3523 ICOM_THIS( ITypeInfoImpl, iface);
3525 ++(This->ref);
3527 TRACE("(%p)->ref is %u\n",This, This->ref);
3528 return This->ref;
3531 /* ITypeInfo::Release
3533 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3535 ICOM_THIS( ITypeInfoImpl, iface);
3537 --(This->ref);
3539 TRACE("(%p)->(%u)\n",This, This->ref);
3541 if (!This->ref)
3543 FIXME("destroy child objects\n");
3545 TRACE("destroying ITypeInfo(%p)\n",This);
3546 if (This->Name)
3548 SysFreeString(This->Name);
3549 This->Name = 0;
3552 if (This->DocString)
3554 SysFreeString(This->DocString);
3555 This->DocString = 0;
3558 if (This->next)
3560 ITypeInfo_Release((ITypeInfo*)This->next);
3563 HeapFree(GetProcessHeap(),0,This);
3564 return 0;
3566 return This->ref;
3569 /* ITypeInfo::GetTypeAttr
3571 * Retrieves a TYPEATTR structure that contains the attributes of the type
3572 * description.
3575 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3576 LPTYPEATTR *ppTypeAttr)
3578 ICOM_THIS( ITypeInfoImpl, iface);
3579 TRACE("(%p)\n",This);
3580 /* FIXME: must do a copy here */
3581 *ppTypeAttr=&This->TypeAttr;
3582 return S_OK;
3585 /* ITypeInfo::GetTypeComp
3587 * Retrieves the ITypeComp interface for the type description, which enables a
3588 * client compiler to bind to the type description's members.
3591 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3592 ITypeComp * *ppTComp)
3594 ICOM_THIS( ITypeInfoImpl, iface);
3595 FIXME("(%p) stub!\n", This);
3596 return S_OK;
3599 /* ITypeInfo::GetFuncDesc
3601 * Retrieves the FUNCDESC structure that contains information about a
3602 * specified function.
3605 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3606 LPFUNCDESC *ppFuncDesc)
3608 ICOM_THIS( ITypeInfoImpl, iface);
3609 int i;
3610 TLBFuncDesc * pFDesc;
3611 TRACE("(%p) index %d\n", This, index);
3612 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3614 if(pFDesc){
3615 /* FIXME: must do a copy here */
3616 *ppFuncDesc=&pFDesc->funcdesc;
3617 return S_OK;
3619 return E_INVALIDARG;
3622 /* ITypeInfo::GetVarDesc
3624 * Retrieves a VARDESC structure that describes the specified variable.
3627 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3628 LPVARDESC *ppVarDesc)
3630 ICOM_THIS( ITypeInfoImpl, iface);
3631 int i;
3632 TLBVarDesc * pVDesc;
3633 TRACE("(%p) index %d\n", This, index);
3634 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3636 if(pVDesc){
3637 /* FIXME: must do a copy here */
3638 *ppVarDesc=&pVDesc->vardesc;
3639 return S_OK;
3641 return E_INVALIDARG;
3644 /* ITypeInfo_GetNames
3646 * Retrieves the variable with the specified member ID (or the name of the
3647 * property or method and its parameters) that correspond to the specified
3648 * function ID.
3650 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3651 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3653 ICOM_THIS( ITypeInfoImpl, iface);
3654 TLBFuncDesc * pFDesc;
3655 TLBVarDesc * pVDesc;
3656 int i;
3657 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3658 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3659 if(pFDesc)
3661 /* function found, now return function and parameter names */
3662 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3664 if(!i)
3665 *rgBstrNames=SysAllocString(pFDesc->Name);
3666 else
3667 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3669 *pcNames=i;
3671 else
3673 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3674 if(pVDesc)
3676 *rgBstrNames=SysAllocString(pVDesc->Name);
3677 *pcNames=1;
3679 else
3681 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3683 /* recursive search */
3684 ITypeInfo *pTInfo;
3685 HRESULT result;
3686 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3687 &pTInfo);
3688 if(SUCCEEDED(result))
3690 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3691 ITypeInfo_Release(pTInfo);
3692 return result;
3694 WARN("Could not search inherited interface!\n");
3696 else
3698 WARN("no names found\n");
3700 *pcNames=0;
3701 return TYPE_E_ELEMENTNOTFOUND;
3704 return S_OK;
3708 /* ITypeInfo::GetRefTypeOfImplType
3710 * If a type description describes a COM class, it retrieves the type
3711 * description of the implemented interface types. For an interface,
3712 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3713 * if any exist.
3716 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3717 ITypeInfo2 *iface,
3718 UINT index,
3719 HREFTYPE *pRefType)
3721 ICOM_THIS( ITypeInfoImpl, iface);
3722 int(i);
3723 TLBImplType *pImpl = This->impltypelist;
3725 TRACE("(%p) index %d\n", This, index);
3726 dump_TypeInfo(This);
3728 if(index==(UINT)-1)
3730 /* only valid on dual interfaces;
3731 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3733 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3735 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3736 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3738 *pRefType = -1;
3740 else
3742 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3743 *pRefType = pImpl->hRef;
3746 else
3748 /* get element n from linked list */
3749 for(i=0; pImpl && i<index; i++)
3751 pImpl = pImpl->next;
3754 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3756 *pRefType = pImpl->hRef;
3758 TRACE("-- 0x%08lx\n", pImpl->hRef );
3761 return S_OK;
3765 /* ITypeInfo::GetImplTypeFlags
3767 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3768 * or base interface in a type description.
3770 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
3771 UINT index, INT *pImplTypeFlags)
3773 ICOM_THIS( ITypeInfoImpl, iface);
3774 int i;
3775 TLBImplType *pImpl;
3777 TRACE("(%p) index %d\n", This, index);
3778 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
3779 i++, pImpl=pImpl->next)
3781 if(i==index && pImpl){
3782 *pImplTypeFlags=pImpl->implflags;
3783 return S_OK;
3785 *pImplTypeFlags=0;
3786 return TYPE_E_ELEMENTNOTFOUND;
3789 /* GetIDsOfNames
3790 * Maps between member names and member IDs, and parameter names and
3791 * parameter IDs.
3793 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
3794 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
3796 ICOM_THIS( ITypeInfoImpl, iface);
3797 TLBFuncDesc * pFDesc;
3798 TLBVarDesc * pVDesc;
3799 HRESULT ret=S_OK;
3801 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
3802 cNames);
3803 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
3804 int i, j;
3805 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
3806 if(cNames) *pMemId=pFDesc->funcdesc.memid;
3807 for(i=1; i < cNames; i++){
3808 for(j=0; j<pFDesc->funcdesc.cParams; j++)
3809 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
3810 break;
3811 if( j<pFDesc->funcdesc.cParams)
3812 pMemId[i]=j;
3813 else
3814 ret=DISP_E_UNKNOWNNAME;
3816 return ret;
3819 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
3820 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
3821 if(cNames) *pMemId=pVDesc->vardesc.memid;
3822 return ret;
3825 /* not found, see if this is and interface with an inheritance */
3826 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
3827 This->TypeAttr.cImplTypes ){
3828 /* recursive search */
3829 ITypeInfo *pTInfo;
3830 ret=ITypeInfo_GetRefTypeInfo(iface,
3831 This->impltypelist->hRef, &pTInfo);
3832 if(SUCCEEDED(ret)){
3833 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
3834 ITypeInfo_Release(pTInfo);
3835 return ret;
3837 WARN("Could not search inherited interface!\n");
3838 } else
3839 WARN("no names found\n");
3840 return DISP_E_UNKNOWNNAME;
3843 /* ITypeInfo::Invoke
3845 * Invokes a method, or accesses a property of an object, that implements the
3846 * interface described by the type description.
3848 static DWORD _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
3849 DWORD res;
3851 if (TRACE_ON(ole)) {
3852 int i;
3853 MESSAGE("Calling %p(",func);
3854 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
3855 MESSAGE(")\n");
3858 switch (callconv) {
3859 case CC_STDCALL:
3861 switch (nrargs) {
3862 case 0: {
3863 DWORD (WINAPI *xfunc)() = func;
3864 res = xfunc();
3865 break;
3867 case 1: {
3868 DWORD (WINAPI *xfunc)(DWORD) = func;
3869 res = xfunc(args[0]);
3870 break;
3872 case 2: {
3873 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
3874 res = xfunc(args[0],args[1]);
3875 break;
3877 case 3: {
3878 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
3879 res = xfunc(args[0],args[1],args[2]);
3880 break;
3882 default:
3883 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
3884 res = -1;
3885 break;
3887 break;
3888 default:
3889 FIXME("unsupported calling convention %d\n",callconv);
3890 res = -1;
3891 break;
3893 TRACE("returns %08lx\n",res);
3894 return res;
3897 static HRESULT WINAPI ITypeInfo_fnInvoke(
3898 ITypeInfo2 *iface,
3899 VOID *pIUnk,
3900 MEMBERID memid,
3901 UINT16 dwFlags,
3902 DISPPARAMS *pDispParams,
3903 VARIANT *pVarResult,
3904 EXCEPINFO *pExcepInfo,
3905 UINT *pArgErr)
3907 ICOM_THIS( ITypeInfoImpl, iface);
3908 TLBFuncDesc * pFDesc;
3909 TLBVarDesc * pVDesc;
3910 int i;
3912 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
3913 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
3915 dump_DispParms(pDispParams);
3917 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
3918 if (pFDesc->funcdesc.memid == memid) {
3919 if (pFDesc->funcdesc.invkind & dwFlags)
3920 break;
3922 if (pFDesc) {
3923 dump_TLBFuncDescOne(pFDesc);
3924 switch (pFDesc->funcdesc.funckind) {
3925 case FUNC_PUREVIRTUAL:
3926 case FUNC_VIRTUAL: {
3927 DWORD res;
3928 DWORD *args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*(pFDesc->funcdesc.cParams+1));
3929 DWORD *args2 = (DWORD*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*(pFDesc->funcdesc.cParams));
3930 args[0] = (DWORD)pIUnk;
3932 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
3933 if (i<pDispParams->cArgs) {
3934 TRACE("set %d to disparg type %d vs %d\n",i,
3935 V_VT(&pDispParams->rgvarg[pDispParams->cArgs-i-1]),
3936 pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt
3938 args[i+1] = V_UNION(&pDispParams->rgvarg[pDispParams->cArgs-i-1],lVal);
3939 } else {
3940 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
3941 TRACE("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
3942 /*FIXME: give pointers for the rest, so propertyget works*/
3943 args[i+1] = (DWORD)&args2[i];
3945 /* If pointer to variant, pass reference to variant
3946 * in result variant array.
3948 if ((tdesc->vt == VT_PTR) &&
3949 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
3950 pVarResult
3952 args[i+1] = (DWORD)(pVarResult+(i-pDispParams->cArgs));
3955 if (pFDesc->funcdesc.cParamsOpt)
3956 FIXME("Does not support optional parameters (%d)\n",
3957 pFDesc->funcdesc.cParamsOpt
3960 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
3961 pFDesc->funcdesc.callconv,
3962 pFDesc->funcdesc.cParams+1,
3963 args
3965 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
3966 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
3967 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
3968 /* If we are a pointer to a variant, we are done already */
3969 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
3970 continue;
3972 VariantInit(&pVarResult[i]);
3973 V_UNION(pVarResult+i,intVal) = args2[i];
3975 if (tdesc->vt == VT_PTR)
3976 tdesc = tdesc->u.lptdesc;
3977 V_VT(pVarResult+i) = tdesc->vt;
3979 /* HACK: VB5 likes this.
3980 * I do not know why. There is 1 example in MSDN which uses
3981 * this which appears broken (mixes int vals and
3982 * IDispatch*.).
3984 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
3985 V_VT(pVarResult+i) = VT_DISPATCH;
3986 TRACE("storing into variant: [%d] type %d, val %08x\n",
3987 i,V_VT(pVarResult+i),V_UNION(pVarResult+i,intVal)
3991 HeapFree(GetProcessHeap(),0,args2);
3992 HeapFree(GetProcessHeap(),0,args);
3993 return S_OK;
3995 case FUNC_DISPATCH: {
3996 IDispatch *disp;
3997 HRESULT hr;
3999 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4000 if (hr) {
4001 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4002 return hr;
4004 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4005 hr = IDispatch_Invoke(
4006 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4007 pVarResult,pExcepInfo,pArgErr
4009 if (hr)
4010 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4011 IDispatch_Release(disp);
4012 return hr;
4014 default:
4015 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4016 return E_FAIL;
4018 } else {
4019 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4020 if (pVDesc->vardesc.memid == memid) {
4021 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4022 dump_TLBVarDesc(pVDesc);
4023 break;
4027 /* not found, look for it in inherited interfaces */
4028 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4029 /* recursive search */
4030 ITypeInfo *pTInfo;
4031 HRESULT hr;
4032 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4033 if(SUCCEEDED(hr)){
4034 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4035 ITypeInfo_Release(pTInfo);
4036 return hr;
4038 WARN("Could not search inherited interface!\n");
4040 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4041 return DISP_E_MEMBERNOTFOUND;
4044 /* ITypeInfo::GetDocumentation
4046 * Retrieves the documentation string, the complete Help file name and path,
4047 * and the context ID for the Help topic for a specified type description.
4049 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4050 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4051 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4053 ICOM_THIS( ITypeInfoImpl, iface);
4054 TLBFuncDesc * pFDesc;
4055 TLBVarDesc * pVDesc;
4056 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4057 " HelpContext(%p) HelpFile(%p)\n",
4058 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4059 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4060 if(pBstrName)
4061 *pBstrName=SysAllocString(This->Name);
4062 if(pBstrDocString)
4063 *pBstrDocString=SysAllocString(This->DocString);
4064 if(pdwHelpContext)
4065 *pdwHelpContext=This->dwHelpContext;
4066 if(pBstrHelpFile)
4067 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4068 return S_OK;
4069 }else {/* for a member */
4070 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4071 if(pFDesc->funcdesc.memid==memid){
4072 if(pBstrName)
4073 *pBstrName = SysAllocString(pFDesc->Name);
4074 if(pBstrDocString)
4075 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4076 if(pdwHelpContext)
4077 *pdwHelpContext=pFDesc->helpcontext;
4078 return S_OK;
4080 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4081 if(pVDesc->vardesc.memid==memid){
4082 FIXME("Not implemented\n");
4083 return S_OK;
4086 return TYPE_E_ELEMENTNOTFOUND;
4089 /* ITypeInfo::GetDllEntry
4091 * Retrieves a description or specification of an entry point for a function
4092 * in a DLL.
4094 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4095 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4096 WORD *pwOrdinal)
4098 ICOM_THIS( ITypeInfoImpl, iface);
4099 FIXME("(%p) stub!\n", This);
4100 return E_FAIL;
4103 /* ITypeInfo::GetRefTypeInfo
4105 * If a type description references other type descriptions, it retrieves
4106 * the referenced type descriptions.
4108 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4109 ITypeInfo2 *iface,
4110 HREFTYPE hRefType,
4111 ITypeInfo **ppTInfo)
4113 ICOM_THIS( ITypeInfoImpl, iface);
4114 HRESULT result = E_FAIL;
4117 if (hRefType == -1 &&
4118 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4119 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4121 /* when we meet a DUAL dispinterface, we must create the interface
4122 * version of it.
4124 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4127 /* the interface version contains the same information as the dispinterface
4128 * copy the contents of the structs.
4130 *pTypeInfoImpl = *This;
4131 pTypeInfoImpl->ref = 1;
4133 /* change the type to interface */
4134 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4136 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4138 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4140 result = S_OK;
4142 } else {
4143 TLBRefType *pRefType;
4144 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4145 if(pRefType->reference == hRefType)
4146 break;
4148 if(!pRefType)
4149 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4150 if(pRefType && hRefType != -1) {
4151 ITypeLib *pTLib;
4153 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4154 int Index;
4155 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4156 } else {
4157 if(pRefType->pImpTLInfo->pImpTypeLib) {
4158 TRACE("typeinfo in imported typelib that is already loaded\n");
4159 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4160 ITypeLib2_AddRef((ITypeLib*) pTLib);
4161 result = S_OK;
4162 } else {
4163 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4164 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4165 pRefType->pImpTLInfo->wVersionMajor,
4166 pRefType->pImpTLInfo->wVersionMinor,
4167 pRefType->pImpTLInfo->lcid,
4168 &pTLib);
4170 if(!SUCCEEDED(result)) {
4171 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4172 result=LoadTypeLib(libnam, &pTLib);
4173 SysFreeString(libnam);
4175 if(SUCCEEDED(result)) {
4176 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4177 ITypeLib2_AddRef(pTLib);
4181 if(SUCCEEDED(result)) {
4182 if(pRefType->index == TLB_REF_USE_GUID)
4183 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4184 &pRefType->guid,
4185 ppTInfo);
4186 else
4187 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4188 ppTInfo);
4193 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4194 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4195 return result;
4198 /* ITypeInfo::AddressOfMember
4200 * Retrieves the addresses of static functions or variables, such as those
4201 * defined in a DLL.
4203 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4204 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4206 ICOM_THIS( ITypeInfoImpl, iface);
4207 FIXME("(%p) stub!\n", This);
4208 return S_OK;
4211 /* ITypeInfo::CreateInstance
4213 * Creates a new instance of a type that describes a component object class
4214 * (coclass).
4216 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4217 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4219 ICOM_THIS( ITypeInfoImpl, iface);
4220 FIXME("(%p) stub!\n", This);
4221 return S_OK;
4224 /* ITypeInfo::GetMops
4226 * Retrieves marshaling information.
4228 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4229 BSTR *pBstrMops)
4231 ICOM_THIS( ITypeInfoImpl, iface);
4232 FIXME("(%p) stub!\n", This);
4233 return S_OK;
4236 /* ITypeInfo::GetContainingTypeLib
4238 * Retrieves the containing type library and the index of the type description
4239 * within that type library.
4241 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4242 ITypeLib * *ppTLib, UINT *pIndex)
4244 ICOM_THIS( ITypeInfoImpl, iface);
4245 if (!pIndex)
4246 return E_INVALIDARG;
4247 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4248 *pIndex=This->index;
4249 ITypeLib2_AddRef(*ppTLib);
4250 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4251 return S_OK;
4254 /* ITypeInfo::ReleaseTypeAttr
4256 * Releases a TYPEATTR previously returned by GetTypeAttr.
4259 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4260 TYPEATTR* pTypeAttr)
4262 ICOM_THIS( ITypeInfoImpl, iface);
4263 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4264 return S_OK;
4267 /* ITypeInfo::ReleaseFuncDesc
4269 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4271 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4272 ITypeInfo2 *iface,
4273 FUNCDESC *pFuncDesc)
4275 ICOM_THIS( ITypeInfoImpl, iface);
4276 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4277 return S_OK;
4280 /* ITypeInfo::ReleaseVarDesc
4282 * Releases a VARDESC previously returned by GetVarDesc.
4284 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4285 VARDESC *pVarDesc)
4287 ICOM_THIS( ITypeInfoImpl, iface);
4288 TRACE("(%p)->(%p)\n", This, pVarDesc);
4289 return S_OK;
4292 /* ITypeInfo2::GetTypeKind
4294 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4297 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4298 TYPEKIND *pTypeKind)
4300 ICOM_THIS( ITypeInfoImpl, iface);
4301 *pTypeKind=This->TypeAttr.typekind;
4302 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4303 return S_OK;
4306 /* ITypeInfo2::GetTypeFlags
4308 * Returns the type flags without any allocations. This returns a DWORD type
4309 * flag, which expands the type flags without growing the TYPEATTR (type
4310 * attribute).
4313 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4314 UINT *pTypeFlags)
4316 ICOM_THIS( ITypeInfoImpl, iface);
4317 *pTypeFlags=This->TypeAttr.wTypeFlags;
4318 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4319 return S_OK;
4322 /* ITypeInfo2::GetFuncIndexOfMemId
4323 * Binds to a specific member based on a known DISPID, where the member name
4324 * is not known (for example, when binding to a default member).
4327 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4328 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4330 ICOM_THIS( ITypeInfoImpl, iface);
4331 TLBFuncDesc *pFuncInfo;
4332 int i;
4333 HRESULT result;
4334 /* FIXME: should check for invKind??? */
4335 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4336 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4337 if(pFuncInfo){
4338 *pFuncIndex=i;
4339 result= S_OK;
4340 }else{
4341 *pFuncIndex=0;
4342 result=E_INVALIDARG;
4344 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4345 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4346 return result;
4349 /* TypeInfo2::GetVarIndexOfMemId
4351 * Binds to a specific member based on a known DISPID, where the member name
4352 * is not known (for example, when binding to a default member).
4355 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4356 MEMBERID memid, UINT *pVarIndex)
4358 ICOM_THIS( ITypeInfoImpl, iface);
4359 TLBVarDesc *pVarInfo;
4360 int i;
4361 HRESULT result;
4362 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4363 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4365 if(pVarInfo){
4366 *pVarIndex=i;
4367 result= S_OK;
4368 }else{
4369 *pVarIndex=0;
4370 result=E_INVALIDARG;
4372 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4373 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4374 return result;
4377 /* ITypeInfo2::GetCustData
4379 * Gets the custom data
4381 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4382 ITypeInfo2 * iface,
4383 REFGUID guid,
4384 VARIANT *pVarVal)
4386 ICOM_THIS( ITypeInfoImpl, iface);
4387 TLBCustData *pCData;
4389 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4390 if( IsEqualIID(guid, &pCData->guid)) break;
4392 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4394 if(pCData)
4396 VariantInit( pVarVal);
4397 VariantCopy( pVarVal, &pCData->data);
4398 return S_OK;
4400 return E_INVALIDARG; /* FIXME: correct? */
4403 /* ITypeInfo2::GetFuncCustData
4405 * Gets the custom data
4407 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4408 ITypeInfo2 * iface,
4409 UINT index,
4410 REFGUID guid,
4411 VARIANT *pVarVal)
4413 ICOM_THIS( ITypeInfoImpl, iface);
4414 TLBCustData *pCData=NULL;
4415 TLBFuncDesc * pFDesc;
4416 int i;
4417 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4418 pFDesc=pFDesc->next);
4420 if(pFDesc)
4421 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4422 if( IsEqualIID(guid, &pCData->guid)) break;
4424 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4426 if(pCData){
4427 VariantInit( pVarVal);
4428 VariantCopy( pVarVal, &pCData->data);
4429 return S_OK;
4431 return E_INVALIDARG; /* FIXME: correct? */
4434 /* ITypeInfo2::GetParamCustData
4436 * Gets the custom data
4438 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4439 ITypeInfo2 * iface,
4440 UINT indexFunc,
4441 UINT indexParam,
4442 REFGUID guid,
4443 VARIANT *pVarVal)
4445 ICOM_THIS( ITypeInfoImpl, iface);
4446 TLBCustData *pCData=NULL;
4447 TLBFuncDesc * pFDesc;
4448 int i;
4450 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4452 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4453 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4454 pCData = pCData->next)
4455 if( IsEqualIID(guid, &pCData->guid)) break;
4457 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4459 if(pCData)
4461 VariantInit( pVarVal);
4462 VariantCopy( pVarVal, &pCData->data);
4463 return S_OK;
4465 return E_INVALIDARG; /* FIXME: correct? */
4468 /* ITypeInfo2::GetVarCustData
4470 * Gets the custom data
4472 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4473 ITypeInfo2 * iface,
4474 UINT index,
4475 REFGUID guid,
4476 VARIANT *pVarVal)
4478 ICOM_THIS( ITypeInfoImpl, iface);
4479 TLBCustData *pCData=NULL;
4480 TLBVarDesc * pVDesc;
4481 int i;
4483 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4485 if(pVDesc)
4487 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4489 if( IsEqualIID(guid, &pCData->guid)) break;
4493 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4495 if(pCData)
4497 VariantInit( pVarVal);
4498 VariantCopy( pVarVal, &pCData->data);
4499 return S_OK;
4501 return E_INVALIDARG; /* FIXME: correct? */
4504 /* ITypeInfo2::GetImplCustData
4506 * Gets the custom data
4508 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4509 ITypeInfo2 * iface,
4510 UINT index,
4511 REFGUID guid,
4512 VARIANT *pVarVal)
4514 ICOM_THIS( ITypeInfoImpl, iface);
4515 TLBCustData *pCData=NULL;
4516 TLBImplType * pRDesc;
4517 int i;
4519 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4521 if(pRDesc)
4523 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4525 if( IsEqualIID(guid, &pCData->guid)) break;
4529 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4531 if(pCData)
4533 VariantInit( pVarVal);
4534 VariantCopy( pVarVal, &pCData->data);
4535 return S_OK;
4537 return E_INVALIDARG; /* FIXME: correct? */
4540 /* ITypeInfo2::GetDocumentation2
4542 * Retrieves the documentation string, the complete Help file name and path,
4543 * the localization context to use, and the context ID for the library Help
4544 * topic in the Help file.
4547 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4548 ITypeInfo2 * iface,
4549 MEMBERID memid,
4550 LCID lcid,
4551 BSTR *pbstrHelpString,
4552 DWORD *pdwHelpStringContext,
4553 BSTR *pbstrHelpStringDll)
4555 ICOM_THIS( ITypeInfoImpl, iface);
4556 TLBFuncDesc * pFDesc;
4557 TLBVarDesc * pVDesc;
4558 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4559 "HelpStringContext(%p) HelpStringDll(%p)\n",
4560 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4561 pbstrHelpStringDll );
4562 /* the help string should be obtained from the helpstringdll,
4563 * using the _DLLGetDocumentation function, based on the supplied
4564 * lcid. Nice to do sometime...
4566 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4567 if(pbstrHelpString)
4568 *pbstrHelpString=SysAllocString(This->Name);
4569 if(pdwHelpStringContext)
4570 *pdwHelpStringContext=This->dwHelpStringContext;
4571 if(pbstrHelpStringDll)
4572 *pbstrHelpStringDll=
4573 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4574 return S_OK;
4575 }else {/* for a member */
4576 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4577 if(pFDesc->funcdesc.memid==memid){
4578 if(pbstrHelpString)
4579 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4580 if(pdwHelpStringContext)
4581 *pdwHelpStringContext=pFDesc->HelpStringContext;
4582 if(pbstrHelpStringDll)
4583 *pbstrHelpStringDll=
4584 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4585 return S_OK;
4587 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4588 if(pVDesc->vardesc.memid==memid){
4589 if(pbstrHelpString)
4590 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4591 if(pdwHelpStringContext)
4592 *pdwHelpStringContext=pVDesc->HelpStringContext;
4593 if(pbstrHelpStringDll)
4594 *pbstrHelpStringDll=
4595 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4596 return S_OK;
4599 return TYPE_E_ELEMENTNOTFOUND;
4602 /* ITypeInfo2::GetAllCustData
4604 * Gets all custom data items for the Type info.
4607 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4608 ITypeInfo2 * iface,
4609 CUSTDATA *pCustData)
4611 ICOM_THIS( ITypeInfoImpl, iface);
4612 TLBCustData *pCData;
4613 int i;
4615 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4617 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4618 if(pCustData->prgCustData ){
4619 pCustData->cCustData=This->ctCustData;
4620 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4621 pCustData->prgCustData[i].guid=pCData->guid;
4622 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4624 }else{
4625 ERR(" OUT OF MEMORY! \n");
4626 return E_OUTOFMEMORY;
4628 return S_OK;
4631 /* ITypeInfo2::GetAllFuncCustData
4633 * Gets all custom data items for the specified Function
4636 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4637 ITypeInfo2 * iface,
4638 UINT index,
4639 CUSTDATA *pCustData)
4641 ICOM_THIS( ITypeInfoImpl, iface);
4642 TLBCustData *pCData;
4643 TLBFuncDesc * pFDesc;
4644 int i;
4645 TRACE("(%p) index %d\n", This, index);
4646 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4647 pFDesc=pFDesc->next)
4649 if(pFDesc){
4650 pCustData->prgCustData =
4651 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4652 if(pCustData->prgCustData ){
4653 pCustData->cCustData=pFDesc->ctCustData;
4654 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4655 pCData = pCData->next){
4656 pCustData->prgCustData[i].guid=pCData->guid;
4657 VariantCopy(& pCustData->prgCustData[i].varValue,
4658 & pCData->data);
4660 }else{
4661 ERR(" OUT OF MEMORY! \n");
4662 return E_OUTOFMEMORY;
4664 return S_OK;
4666 return TYPE_E_ELEMENTNOTFOUND;
4669 /* ITypeInfo2::GetAllParamCustData
4671 * Gets all custom data items for the Functions
4674 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4675 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4677 ICOM_THIS( ITypeInfoImpl, iface);
4678 TLBCustData *pCData=NULL;
4679 TLBFuncDesc * pFDesc;
4680 int i;
4681 TRACE("(%p) index %d\n", This, indexFunc);
4682 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4683 pFDesc=pFDesc->next)
4685 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4686 pCustData->prgCustData =
4687 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4688 sizeof(CUSTDATAITEM));
4689 if(pCustData->prgCustData ){
4690 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
4691 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
4692 pCData; i++, pCData = pCData->next){
4693 pCustData->prgCustData[i].guid=pCData->guid;
4694 VariantCopy(& pCustData->prgCustData[i].varValue,
4695 & pCData->data);
4697 }else{
4698 ERR(" OUT OF MEMORY! \n");
4699 return E_OUTOFMEMORY;
4701 return S_OK;
4703 return TYPE_E_ELEMENTNOTFOUND;
4706 /* ITypeInfo2::GetAllVarCustData
4708 * Gets all custom data items for the specified Variable
4711 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
4712 UINT index, CUSTDATA *pCustData)
4714 ICOM_THIS( ITypeInfoImpl, iface);
4715 TLBCustData *pCData;
4716 TLBVarDesc * pVDesc;
4717 int i;
4718 TRACE("(%p) index %d\n", This, index);
4719 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
4720 pVDesc=pVDesc->next)
4722 if(pVDesc){
4723 pCustData->prgCustData =
4724 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
4725 if(pCustData->prgCustData ){
4726 pCustData->cCustData=pVDesc->ctCustData;
4727 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
4728 pCData = pCData->next){
4729 pCustData->prgCustData[i].guid=pCData->guid;
4730 VariantCopy(& pCustData->prgCustData[i].varValue,
4731 & pCData->data);
4733 }else{
4734 ERR(" OUT OF MEMORY! \n");
4735 return E_OUTOFMEMORY;
4737 return S_OK;
4739 return TYPE_E_ELEMENTNOTFOUND;
4742 /* ITypeInfo2::GetAllImplCustData
4744 * Gets all custom data items for the specified implementation type
4747 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
4748 ITypeInfo2 * iface,
4749 UINT index,
4750 CUSTDATA *pCustData)
4752 ICOM_THIS( ITypeInfoImpl, iface);
4753 TLBCustData *pCData;
4754 TLBImplType * pRDesc;
4755 int i;
4756 TRACE("(%p) index %d\n", This, index);
4757 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
4758 pRDesc=pRDesc->next)
4760 if(pRDesc){
4761 pCustData->prgCustData =
4762 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
4763 if(pCustData->prgCustData ){
4764 pCustData->cCustData=pRDesc->ctCustData;
4765 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
4766 pCData = pCData->next){
4767 pCustData->prgCustData[i].guid=pCData->guid;
4768 VariantCopy(& pCustData->prgCustData[i].varValue,
4769 & pCData->data);
4771 }else{
4772 ERR(" OUT OF MEMORY! \n");
4773 return E_OUTOFMEMORY;
4775 return S_OK;
4777 return TYPE_E_ELEMENTNOTFOUND;
4780 static ICOM_VTABLE(ITypeInfo2) tinfvt =
4782 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4784 ITypeInfo_fnQueryInterface,
4785 ITypeInfo_fnAddRef,
4786 ITypeInfo_fnRelease,
4788 ITypeInfo_fnGetTypeAttr,
4789 ITypeInfo_fnGetTypeComp,
4790 ITypeInfo_fnGetFuncDesc,
4791 ITypeInfo_fnGetVarDesc,
4792 ITypeInfo_fnGetNames,
4793 ITypeInfo_fnGetRefTypeOfImplType,
4794 ITypeInfo_fnGetImplTypeFlags,
4795 ITypeInfo_fnGetIDsOfNames,
4796 ITypeInfo_fnInvoke,
4797 ITypeInfo_fnGetDocumentation,
4798 ITypeInfo_fnGetDllEntry,
4799 ITypeInfo_fnGetRefTypeInfo,
4800 ITypeInfo_fnAddressOfMember,
4801 ITypeInfo_fnCreateInstance,
4802 ITypeInfo_fnGetMops,
4803 ITypeInfo_fnGetContainingTypeLib,
4804 ITypeInfo_fnReleaseTypeAttr,
4805 ITypeInfo_fnReleaseFuncDesc,
4806 ITypeInfo_fnReleaseVarDesc,
4808 ITypeInfo2_fnGetTypeKind,
4809 ITypeInfo2_fnGetTypeFlags,
4810 ITypeInfo2_fnGetFuncIndexOfMemId,
4811 ITypeInfo2_fnGetVarIndexOfMemId,
4812 ITypeInfo2_fnGetCustData,
4813 ITypeInfo2_fnGetFuncCustData,
4814 ITypeInfo2_fnGetParamCustData,
4815 ITypeInfo2_fnGetVarCustData,
4816 ITypeInfo2_fnGetImplTypeCustData,
4817 ITypeInfo2_fnGetDocumentation2,
4818 ITypeInfo2_fnGetAllCustData,
4819 ITypeInfo2_fnGetAllFuncCustData,
4820 ITypeInfo2_fnGetAllParamCustData,
4821 ITypeInfo2_fnGetAllVarCustData,
4822 ITypeInfo2_fnGetAllImplTypeCustData,