Add more magic to find the start of the nametable.
[wine.git] / dlls / oleaut32 / typelib.c
blob9f3968cbc12400f6b3bcc188415c81111218a658
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
47 * behaviour.
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
55 #include "config.h"
56 #include "wine/port.h"
58 #include <stdlib.h>
59 #include <string.h>
60 #include <stdio.h>
61 #include <ctype.h>
63 #include "winerror.h"
64 #include "winnls.h" /* for PRIMARYLANGID */
65 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
66 #include "winuser.h"
68 #include "wine/unicode.h"
69 #include "wine/obj_base.h"
70 #include "heap.h"
71 #include "ole2disp.h"
72 #include "typelib.h"
73 #include "wine/debug.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78 /****************************************************************************
79 * QueryPathOfRegTypeLib [TYPELIB.14]
81 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
82 * RETURNS
83 * path of typelib
85 HRESULT WINAPI
86 QueryPathOfRegTypeLib16(
87 REFGUID guid, /* [in] referenced guid */
88 WORD wMaj, /* [in] major version */
89 WORD wMin, /* [in] minor version */
90 LCID lcid, /* [in] locale id */
91 LPBSTR16 path /* [out] path of typelib */
92 ) {
93 char xguid[80];
94 char typelibkey[100],pathname[260];
95 DWORD plen;
97 TRACE("\n");
99 if (HIWORD(guid)) {
100 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
101 guid->Data1, guid->Data2, guid->Data3,
102 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
103 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
104 wMaj,wMin,lcid);
105 } else {
106 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
107 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
108 return E_FAIL;
110 plen = sizeof(pathname);
111 if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
112 /* try again without lang specific id */
113 if (SUBLANGID(lcid))
114 return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
115 FIXME("key %s not found\n",typelibkey);
116 return E_FAIL;
118 *path = SysAllocString16(pathname);
119 return S_OK;
122 /****************************************************************************
123 * QueryPathOfRegTypeLib [OLEAUT32.164]
124 * RETURNS
125 * path of typelib
127 HRESULT WINAPI
128 QueryPathOfRegTypeLib(
129 REFGUID guid, /* [in] referenced guid */
130 WORD wMaj, /* [in] major version */
131 WORD wMin, /* [in] minor version */
132 LCID lcid, /* [in] locale id */
133 LPBSTR path ) /* [out] path of typelib */
135 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
136 string termination character on output strings */
138 HRESULT hr = E_FAIL;
140 LCID myLCID = lcid;
142 char szXGUID[80];
143 char szTypeLibKey[100];
144 char szPath[MAX_PATH];
145 DWORD dwPathLen = sizeof(szPath);
147 if ( !HIWORD(guid) )
149 sprintf(szXGUID,
150 "<guid 0x%08lx>",
151 (DWORD) guid);
153 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
154 return E_FAIL;
157 while (hr != S_OK)
159 sprintf(szTypeLibKey,
160 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
161 guid->Data1, guid->Data2, guid->Data3,
162 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
163 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
164 wMaj,
165 wMin,
166 myLCID);
168 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
170 if (!lcid)
171 break;
172 else if (myLCID == lcid)
174 /* try with sub-langid */
175 myLCID = SUBLANGID(lcid);
177 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
179 /* try with system langid */
180 myLCID = 0;
182 else
184 break;
187 else
189 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
190 BSTR bstrPath = SysAllocStringLen(NULL,len);
192 MultiByteToWideChar(CP_ACP,
193 MB_PRECOMPOSED,
194 szPath,
195 dwPathLen,
196 bstrPath,
197 len);
198 *path = bstrPath;
199 hr = S_OK;
203 if (hr != S_OK)
204 TRACE_(typelib)("%s not found\n", szTypeLibKey);
206 return hr;
209 /******************************************************************************
210 * CreateTypeLib [OLEAUT32.160] creates a typelib
212 * RETURNS
213 * Success: S_OK
214 * Failure: Status
216 HRESULT WINAPI CreateTypeLib(
217 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
219 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
220 return E_FAIL;
222 /******************************************************************************
223 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
224 * NOTES
225 * Docs: OLECHAR FAR* szFile
226 * Docs: iTypeLib FAR* FAR* pptLib
228 * RETURNS
229 * Success: S_OK
230 * Failure: Status
232 HRESULT WINAPI LoadTypeLib16(
233 LPOLESTR szFile, /* [in] Name of file to load from */
234 ITypeLib** pptLib) /* [out] Pointer to pointer to loaded type library */
236 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
238 if (pptLib!=0)
239 *pptLib=0;
241 return E_FAIL;
244 /******************************************************************************
245 * LoadTypeLib [OLEAUT32.161]
246 * Loads and registers a type library
247 * NOTES
248 * Docs: OLECHAR FAR* szFile
249 * Docs: iTypeLib FAR* FAR* pptLib
251 * RETURNS
252 * Success: S_OK
253 * Failure: Status
255 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
257 HRESULT WINAPI LoadTypeLib(
258 const OLECHAR *szFile,/* [in] Name of file to load from */
259 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
261 TRACE("\n");
262 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
265 /******************************************************************************
266 * LoadTypeLibEx [OLEAUT32.183]
267 * Loads and optionally registers a type library
269 * RETURNS
270 * Success: S_OK
271 * Failure: Status
273 HRESULT WINAPI LoadTypeLibEx(
274 LPCOLESTR szFile, /* [in] Name of file to load from */
275 REGKIND regkind, /* [in] Specify kind of registration */
276 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
278 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
279 WCHAR *pIndexStr;
280 HRESULT res;
281 INT index = 1;
282 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
284 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
285 NULL)) {
287 /* Look for a trailing '\\' followed by an index */
288 pIndexStr = strrchrW(szFile, '\\');
289 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
290 index = atoiW(pIndexStr);
291 memcpy(szFileCopy, szFile,
292 (pIndexStr - szFile - 1) * sizeof(WCHAR));
293 szFileCopy[pIndexStr - szFile - 1] = '\0';
294 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
295 szPath,NULL))
296 return TYPE_E_CANTLOADLIBRARY;
297 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
298 return TYPE_E_CANTLOADLIBRARY;
299 } else
300 return TYPE_E_CANTLOADLIBRARY;
303 TRACE("File %s index %d\n", debugstr_w(szPath), index);
305 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
307 if (SUCCEEDED(res))
308 switch(regkind)
310 case REGKIND_DEFAULT:
311 /* FIXME: is this correct? */
312 if (!szFile || !szFile[0] ||
313 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
314 break;
315 /* else fall-through */
316 case REGKIND_REGISTER:
317 /* FIXME: Help path? */
318 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
320 IUnknown_Release(*pptLib);
321 *pptLib = 0;
323 break;
324 case REGKIND_NONE:
325 break;
328 TRACE(" returns %08lx\n",res);
329 return res;
332 /******************************************************************************
333 * LoadRegTypeLib [OLEAUT32.162]
335 HRESULT WINAPI LoadRegTypeLib(
336 REFGUID rguid, /* [in] referenced guid */
337 WORD wVerMajor, /* [in] major version */
338 WORD wVerMinor, /* [in] minor version */
339 LCID lcid, /* [in] locale id */
340 ITypeLib **ppTLib) /* [out] path of typelib */
342 BSTR bstr=NULL;
343 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
345 if(SUCCEEDED(res))
347 res= LoadTypeLib(bstr, ppTLib);
348 SysFreeString(bstr);
351 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
353 return res;
357 /******************************************************************************
358 * RegisterTypeLib [OLEAUT32.163]
359 * Adds information about a type library to the System Registry
360 * NOTES
361 * Docs: ITypeLib FAR * ptlib
362 * Docs: OLECHAR FAR* szFullPath
363 * Docs: OLECHAR FAR* szHelpDir
365 * RETURNS
366 * Success: S_OK
367 * Failure: Status
369 HRESULT WINAPI RegisterTypeLib(
370 ITypeLib * ptlib, /* [in] Pointer to the library*/
371 OLECHAR * szFullPath, /* [in] full Path of the library*/
372 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
373 may be NULL*/
375 HRESULT res;
376 TLIBATTR *attr;
377 OLECHAR guid[80];
378 LPSTR guidA;
379 CHAR keyName[120];
380 HKEY key, subKey;
381 UINT types, tidx;
382 TYPEKIND kind;
383 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
385 if (ptlib == NULL || szFullPath == NULL)
386 return E_INVALIDARG;
388 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
389 return E_FAIL;
391 StringFromGUID2(&attr->guid, guid, 80);
392 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
393 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
394 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
395 HeapFree(GetProcessHeap(), 0, guidA);
397 res = S_OK;
398 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
399 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
401 LPOLESTR doc;
403 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
405 if (RegSetValueExW(key, NULL, 0, REG_SZ,
406 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
407 res = E_FAIL;
409 SysFreeString(doc);
411 else
412 res = E_FAIL;
414 /* FIXME: This *seems* to be 0 always, not sure though */
415 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
416 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
418 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
419 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
420 res = E_FAIL;
422 RegCloseKey(subKey);
424 else
425 res = E_FAIL;
427 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
428 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
430 CHAR buf[20];
431 /* FIXME: is %u correct? */
432 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
433 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
434 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
435 res = E_FAIL;
437 RegCloseKey(key);
439 else
440 res = E_FAIL;
442 /* register OLE Automation-compatible interfaces for this typelib */
443 types = ITypeLib_GetTypeInfoCount(ptlib);
444 for (tidx=0; tidx<types; tidx++) {
445 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
446 LPOLESTR name = NULL;
447 ITypeInfo *tinfo = NULL;
448 BOOL stop = FALSE;
449 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
450 switch (kind) {
451 case TKIND_INTERFACE:
452 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
453 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
454 break;
455 case TKIND_DISPATCH:
456 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
457 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
458 break;
459 case TKIND_COCLASS:
460 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
461 /* coclasses should probably not be registered? */
462 break;
463 default:
464 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
465 break;
467 if (tinfo) {
468 TYPEATTR *tattr = NULL;
469 ITypeInfo_GetTypeAttr(tinfo, &tattr);
470 if (tattr) {
471 TRACE_(typelib)("guid=%s, flags=%04x (",
472 debugstr_guid(&tattr->guid),
473 tattr->wTypeFlags);
474 if (TRACE_ON(typelib)) {
475 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
476 XX(FAPPOBJECT);
477 XX(FCANCREATE);
478 XX(FLICENSED);
479 XX(FPREDECLID);
480 XX(FHIDDEN);
481 XX(FCONTROL);
482 XX(FDUAL);
483 XX(FNONEXTENSIBLE);
484 XX(FOLEAUTOMATION);
485 XX(FRESTRICTED);
486 XX(FAGGREGATABLE);
487 XX(FREPLACEABLE);
488 XX(FDISPATCHABLE);
489 XX(FREVERSEBIND);
490 XX(FPROXY);
491 #undef XX
492 MESSAGE("\n");
495 * FIXME: The 1 is just here until we implement rpcrt4
496 * stub/proxy handling. Until then it helps IShield
497 * v6 to work.
499 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
501 /* register interface<->typelib coupling */
502 StringFromGUID2(&tattr->guid, guid, 80);
503 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
504 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
505 HeapFree(GetProcessHeap(), 0, guidA);
507 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
508 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
509 if (name)
510 RegSetValueExW(key, NULL, 0, REG_SZ,
511 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
513 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
514 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
515 RegSetValueExA(subKey, NULL, 0, REG_SZ,
516 PSOA, strlen(PSOA));
517 RegCloseKey(subKey);
519 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
520 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
521 RegSetValueExA(subKey, NULL, 0, REG_SZ,
522 PSOA, strlen(PSOA));
523 RegCloseKey(subKey);
526 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
527 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
528 CHAR ver[32];
529 StringFromGUID2(&attr->guid, guid, 80);
530 snprintf(ver, sizeof(ver), "%x.%x",
531 attr->wMajorVerNum, attr->wMinorVerNum);
532 RegSetValueExW(subKey, NULL, 0, REG_SZ,
533 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
534 RegSetValueExA(subKey, "Version", 0, REG_SZ,
535 ver, lstrlenA(ver));
536 RegCloseKey(subKey);
538 RegCloseKey(key);
541 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
543 ITypeInfo_Release(tinfo);
545 SysFreeString(name);
546 if (stop) break;
550 ITypeLib_ReleaseTLibAttr(ptlib, attr);
552 return res;
556 /******************************************************************************
557 * UnRegisterTypeLib [OLEAUT32.186]
558 * Removes information about a type library from the System Registry
559 * NOTES
561 * RETURNS
562 * Success: S_OK
563 * Failure: Status
565 HRESULT WINAPI UnRegisterTypeLib(
566 REFGUID libid, /* [in] Guid of the library */
567 WORD wVerMajor, /* [in] major version */
568 WORD wVerMinor, /* [in] minor version */
569 LCID lcid, /* [in] locale id */
570 SYSKIND syskind)
572 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
573 return S_OK; /* FIXME: pretend everything is OK */
576 /****************************************************************************
577 * OaBuildVersion (TYPELIB.15)
579 * known TYPELIB.DLL versions:
581 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
582 * OLE 2.02 1993-94 02 3002
583 * OLE 2.03 23 730
584 * OLE 2.03 03 3025
585 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
586 * OLE 2.1 NT 1993-95 ?? ???
587 * OLE 2.3.1 W95 23 700
588 * OLE2 4.0 NT4SP6 1993-98 40 4277
590 DWORD WINAPI OaBuildVersion16(void)
592 /* FIXME: I'd like to return the highest currently known version value
593 * in case the user didn't force a --winver, but I don't know how
594 * to retrieve the "versionForced" info from misc/version.c :(
595 * (this would be useful in other places, too) */
596 FIXME("If you get version error messages, please report them\n");
597 switch(GetVersion() & 0x8000ffff) /* mask off build number */
599 case 0x80000a03: /* WIN31 */
600 return MAKELONG(3027, 3); /* WfW 3.11 */
601 case 0x80000004: /* WIN95 */
602 return MAKELONG(700, 23); /* Win95A */
603 case 0x80000a04: /* WIN98 */
604 return MAKELONG(3024, 10); /* W98 SE */
605 case 0x00000004: /* NT4 */
606 return MAKELONG(4277, 40); /* NT4 SP6 */
607 default:
608 FIXME("Version value not known yet. Please investigate it!\n");
609 return 0;
613 /* for better debugging info leave the static out for the time being */
614 #define static
616 /*======================= ITypeLib implementation =======================*/
618 typedef struct tagTLBCustData
620 GUID guid;
621 VARIANT data;
622 struct tagTLBCustData* next;
623 } TLBCustData;
625 /* data structure for import typelibs */
626 typedef struct tagTLBImpLib
628 int offset; /* offset in the file (MSFT)
629 offset in nametable (SLTG)
630 just used to identify library while reading
631 data from file */
632 GUID guid; /* libid */
633 BSTR name; /* name */
635 LCID lcid; /* lcid of imported typelib */
637 WORD wVersionMajor; /* major version number */
638 WORD wVersionMinor; /* minor version number */
640 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
641 NULL if not yet loaded */
642 struct tagTLBImpLib * next;
643 } TLBImpLib;
645 /* internal ITypeLib data */
646 typedef struct tagITypeLibImpl
648 ICOM_VFIELD(ITypeLib2);
649 UINT ref;
650 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
652 /* strings can be stored in tlb as multibyte strings BUT they are *always*
653 * exported to the application as a UNICODE string.
655 BSTR Name;
656 BSTR DocString;
657 BSTR HelpFile;
658 BSTR HelpStringDll;
659 unsigned long dwHelpContext;
660 int TypeInfoCount; /* nr of typeinfo's in librarry */
661 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
662 int ctCustData; /* number of items in cust data list */
663 TLBCustData * pCustData; /* linked list to cust data */
664 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
665 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
666 libary. Only used while read MSFT
667 typelibs */
668 } ITypeLibImpl;
670 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
672 /* ITypeLib methods */
673 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
674 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
676 /*======================= ITypeInfo implementation =======================*/
678 /* data for refernced types */
679 typedef struct tagTLBRefType
681 INT index; /* Type index for internal ref or for external ref
682 it the format is SLTG. -2 indicates to
683 use guid */
685 GUID guid; /* guid of the referenced type */
686 /* if index == TLB_REF_USE_GUID */
688 HREFTYPE reference; /* The href of this ref */
689 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
690 TLB_REF_INTERNAL for internal refs
691 TLB_REF_NOT_FOUND for broken refs */
693 struct tagTLBRefType * next;
694 } TLBRefType;
696 #define TLB_REF_USE_GUID -2
698 #define TLB_REF_INTERNAL (void*)-2
699 #define TLB_REF_NOT_FOUND (void*)-1
701 /* internal Parameter data */
702 typedef struct tagTLBParDesc
704 BSTR Name;
705 int ctCustData;
706 TLBCustData * pCustData; /* linked list to cust data */
707 } TLBParDesc;
709 /* internal Function data */
710 typedef struct tagTLBFuncDesc
712 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
713 BSTR Name; /* the name of this function */
714 TLBParDesc *pParamDesc; /* array with param names and custom data */
715 int helpcontext;
716 int HelpStringContext;
717 BSTR HelpString;
718 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
719 int ctCustData;
720 TLBCustData * pCustData; /* linked list to cust data; */
721 struct tagTLBFuncDesc * next;
722 } TLBFuncDesc;
724 /* internal Variable data */
725 typedef struct tagTLBVarDesc
727 VARDESC vardesc; /* lots of info on the variable and its attributes. */
728 BSTR Name; /* the name of this variable */
729 int HelpContext;
730 int HelpStringContext; /* FIXME: where? */
731 BSTR HelpString;
732 int ctCustData;
733 TLBCustData * pCustData;/* linked list to cust data; */
734 struct tagTLBVarDesc * next;
735 } TLBVarDesc;
737 /* internal implemented interface data */
738 typedef struct tagTLBImplType
740 HREFTYPE hRef; /* hRef of interface */
741 int implflags; /* IMPLFLAG_*s */
742 int ctCustData;
743 TLBCustData * pCustData;/* linked list to custom data; */
744 struct tagTLBImplType *next;
745 } TLBImplType;
747 /* internal TypeInfo data */
748 typedef struct tagITypeInfoImpl
750 ICOM_VFIELD(ITypeInfo2);
751 UINT ref;
752 TYPEATTR TypeAttr ; /* _lots_ of type information. */
753 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
754 int index; /* index in this typelib; */
755 /* type libs seem to store the doc strings in ascii
756 * so why should we do it in unicode?
758 BSTR Name;
759 BSTR DocString;
760 unsigned long dwHelpContext;
761 unsigned long dwHelpStringContext;
763 /* functions */
764 TLBFuncDesc * funclist; /* linked list with function descriptions */
766 /* variables */
767 TLBVarDesc * varlist; /* linked list with variable descriptions */
769 /* Implemented Interfaces */
770 TLBImplType * impltypelist;
772 TLBRefType * reflist;
773 int ctCustData;
774 TLBCustData * pCustData; /* linked list to cust data; */
775 struct tagITypeInfoImpl * next;
776 } ITypeInfoImpl;
778 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
780 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
782 typedef struct tagTLBContext
784 unsigned int oStart; /* start of TLB in file */
785 unsigned int pos; /* current pos */
786 unsigned int length; /* total length */
787 void *mapping; /* memory mapping */
788 MSFT_SegDir * pTblDir;
789 ITypeLibImpl* pLibInfo;
790 } TLBContext;
793 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
796 debug
798 static void dump_VarType(VARTYPE vt,char *szVarType) {
799 /* FIXME : we could have better trace here, depending on the VARTYPE
800 * of the variant
802 if (vt & VT_RESERVED)
803 szVarType += strlen(strcpy(szVarType, "reserved | "));
804 if (vt & VT_BYREF)
805 szVarType += strlen(strcpy(szVarType, "ref to "));
806 if (vt & VT_ARRAY)
807 szVarType += strlen(strcpy(szVarType, "array of "));
808 if (vt & VT_VECTOR)
809 szVarType += strlen(strcpy(szVarType, "vector of "));
810 switch(vt & VT_TYPEMASK) {
811 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
812 case VT_I2: sprintf(szVarType, "VT_I2"); break;
813 case VT_I4: sprintf(szVarType, "VT_I4"); break;
814 case VT_R4: sprintf(szVarType, "VT_R4"); break;
815 case VT_R8: sprintf(szVarType, "VT_R8"); break;
816 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
817 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
818 case VT_CY: sprintf(szVarType, "VT_CY"); break;
819 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
820 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
821 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
822 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
823 case VT_I1: sprintf(szVarType, "VT_I1"); break;
824 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
825 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
826 case VT_INT: sprintf(szVarType, "VT_INT"); break;
827 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
828 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
829 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
830 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
831 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
835 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
836 if (pTD->vt & VT_RESERVED)
837 szVarType += strlen(strcpy(szVarType, "reserved | "));
838 if (pTD->vt & VT_BYREF)
839 szVarType += strlen(strcpy(szVarType, "ref to "));
840 if (pTD->vt & VT_ARRAY)
841 szVarType += strlen(strcpy(szVarType, "array of "));
842 if (pTD->vt & VT_VECTOR)
843 szVarType += strlen(strcpy(szVarType, "vector of "));
844 switch(pTD->vt & VT_TYPEMASK) {
845 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
846 case VT_I2: sprintf(szVarType, "VT_I2"); break;
847 case VT_I4: sprintf(szVarType, "VT_I4"); break;
848 case VT_R4: sprintf(szVarType, "VT_R4"); break;
849 case VT_R8: sprintf(szVarType, "VT_R8"); break;
850 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
851 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
852 case VT_CY: sprintf(szVarType, "VT_CY"); break;
853 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
854 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
855 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
856 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
857 case VT_I1: sprintf(szVarType, "VT_I1"); break;
858 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
859 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
860 case VT_INT: sprintf(szVarType, "VT_INT"); break;
861 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
862 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
863 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
864 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
865 pTD->u.hreftype); break;
866 case VT_PTR: sprintf(szVarType, "ptr to ");
867 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
868 break;
869 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
870 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
871 break;
872 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
873 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
874 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
875 break;
877 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
881 void dump_ELEMDESC(ELEMDESC *edesc) {
882 char buf[200];
883 dump_TypeDesc(&edesc->tdesc,buf);
884 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
885 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
886 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
888 void dump_FUNCDESC(FUNCDESC *funcdesc) {
889 int i;
890 MESSAGE("memid is %08lx\n",funcdesc->memid);
891 for (i=0;i<funcdesc->cParams;i++) {
892 MESSAGE("Param %d:\n",i);
893 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
895 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
896 switch (funcdesc->funckind) {
897 case FUNC_VIRTUAL: MESSAGE("virtual");break;
898 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
899 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
900 case FUNC_STATIC: MESSAGE("static");break;
901 case FUNC_DISPATCH: MESSAGE("dispatch");break;
902 default: MESSAGE("unknown");break;
904 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
905 switch (funcdesc->invkind) {
906 case INVOKE_FUNC: MESSAGE("func");break;
907 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
908 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
909 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
911 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
912 switch (funcdesc->callconv) {
913 case CC_CDECL: MESSAGE("cdecl");break;
914 case CC_PASCAL: MESSAGE("pascal");break;
915 case CC_STDCALL: MESSAGE("stdcall");break;
916 case CC_SYSCALL: MESSAGE("syscall");break;
917 default:break;
919 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
920 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
921 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
924 void dump_IDLDESC(IDLDESC *idl) {
925 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
928 static char * typekind_desc[] =
930 "TKIND_ENUM",
931 "TKIND_RECORD",
932 "TKIND_MODULE",
933 "TKIND_INTERFACE",
934 "TKIND_DISPATCH",
935 "TKIND_COCLASS",
936 "TKIND_ALIAS",
937 "TKIND_UNION",
938 "TKIND_MAX"
941 void dump_TYPEATTR(TYPEATTR *tattr) {
942 char buf[200];
943 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
944 MESSAGE("\tlcid: %ld\n",tattr->lcid);
945 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
946 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
947 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
948 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
949 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
950 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
951 MESSAGE("\tcVars: %d\n", tattr->cVars);
952 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
953 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
954 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
955 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
956 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
957 dump_TypeDesc(&tattr->tdescAlias,buf);
958 MESSAGE("\ttypedesc: %s\n", buf);
959 dump_IDLDESC(&tattr->idldescType);
962 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
964 int i;
965 if (!TRACE_ON(typelib))
966 return;
967 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
968 for (i=0;i<pfd->funcdesc.cParams;i++)
969 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
972 dump_FUNCDESC(&(pfd->funcdesc));
974 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
975 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
977 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
979 while (pfd)
981 dump_TLBFuncDescOne(pfd);
982 pfd = pfd->next;
985 static void dump_TLBVarDesc(TLBVarDesc * pvd)
987 while (pvd)
989 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
990 pvd = pvd->next;
994 static void dump_TLBImpLib(TLBImpLib *import)
996 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
997 debugstr_w(import->name));
998 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
999 import->wVersionMinor, import->lcid, import->offset);
1002 static void dump_TLBRefType(TLBRefType * prt)
1004 while (prt)
1006 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1007 if(prt->index == -1)
1008 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1009 else
1010 TRACE_(typelib)("type no: %d\n", prt->index);
1012 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1013 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1014 TRACE_(typelib)("in lib\n");
1015 dump_TLBImpLib(prt->pImpTLInfo);
1017 prt = prt->next;
1021 static void dump_TLBImplType(TLBImplType * impl)
1023 while (impl) {
1024 TRACE_(typelib)(
1025 "implementing/inheriting interface hRef = %lx implflags %x\n",
1026 impl->hRef, impl->implflags);
1027 impl = impl->next;
1031 static void dump_Variant(VARIANT * pvar)
1033 char szVarType[32];
1034 LPVOID ref;
1036 TRACE("(%p)\n", pvar);
1038 if (!pvar) return;
1040 ZeroMemory(szVarType, sizeof(szVarType));
1042 /* FIXME : we could have better trace here, depending on the VARTYPE
1043 * of the variant
1045 dump_VarType(V_VT(pvar),szVarType);
1047 TRACE("VARTYPE: %s\n", szVarType);
1049 if (V_VT(pvar) & VT_BYREF) {
1050 ref = V_UNION(pvar, byref);
1051 TRACE("%p\n", ref);
1053 else ref = &V_UNION(pvar, cVal);
1055 if (V_VT(pvar) & VT_ARRAY) {
1056 /* FIXME */
1057 return;
1059 if (V_VT(pvar) & VT_VECTOR) {
1060 /* FIXME */
1061 return;
1064 switch (V_VT(pvar))
1066 case VT_I2:
1067 TRACE("%d\n", *(short*)ref);
1068 break;
1070 case VT_I4:
1071 TRACE("%d\n", *(INT*)ref);
1072 break;
1074 case VT_R4:
1075 TRACE("%3.3e\n", *(float*)ref);
1076 break;
1078 case VT_R8:
1079 TRACE("%3.3e\n", *(double*)ref);
1080 break;
1082 case VT_BOOL:
1083 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1084 break;
1086 case VT_BSTR:
1087 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1088 break;
1090 case VT_UNKNOWN:
1091 case VT_DISPATCH:
1092 TRACE("%p\n", *(LPVOID*)ref);
1093 break;
1095 case VT_VARIANT:
1096 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1097 break;
1099 default:
1100 TRACE("(?)%ld\n", *(long*)ref);
1101 break;
1105 static void dump_DispParms(DISPPARAMS * pdp)
1107 int index = 0;
1109 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1111 while (index < pdp->cArgs)
1113 dump_Variant( &pdp->rgvarg[index] );
1114 ++index;
1118 static void dump_TypeInfo(ITypeInfoImpl * pty)
1120 TRACE("%p ref=%u\n", pty, pty->ref);
1121 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1122 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1123 TRACE("fct:%u var:%u impl:%u\n",
1124 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1125 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1126 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1127 dump_TLBFuncDesc(pty->funclist);
1128 dump_TLBVarDesc(pty->varlist);
1129 dump_TLBImplType(pty->impltypelist);
1132 void dump_VARDESC(VARDESC *v)
1134 MESSAGE("memid %ld\n",v->memid);
1135 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1136 MESSAGE("oInst %ld\n",v->u.oInst);
1137 dump_ELEMDESC(&(v->elemdescVar));
1138 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1139 MESSAGE("varkind %d\n",v->varkind);
1142 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1144 /* VT_LPWSTR is largest type that */
1145 /* may appear in type description*/
1146 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1147 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1148 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1149 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1150 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1151 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1152 {{0},30},{{0},31}
1155 static void TLB_abort()
1157 DebugBreak();
1159 static void * TLB_Alloc(unsigned size)
1161 void * ret;
1162 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1163 /* FIXME */
1164 ERR("cannot allocate memory\n");
1166 return ret;
1169 static void TLB_Free(void * ptr)
1171 HeapFree(GetProcessHeap(), 0, ptr);
1175 /**********************************************************************
1177 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1179 /* read function */
1180 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1182 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1183 pcx->pos, count, pcx->oStart, pcx->length, where);
1185 if (where != DO_NOT_SEEK)
1187 where += pcx->oStart;
1188 if (where > pcx->length)
1190 /* FIXME */
1191 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1192 TLB_abort();
1194 pcx->pos = where;
1196 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1197 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1198 pcx->pos += count;
1199 return count;
1202 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1204 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1206 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1207 memset(pGuid,0, sizeof(GUID));
1208 return;
1210 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1213 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1215 char * name;
1216 MSFT_NameIntro niName;
1217 int lengthInChars;
1218 WCHAR* pwstring = NULL;
1219 BSTR bstrName = NULL;
1221 MSFT_Read(&niName, sizeof(niName), pcx,
1222 pcx->pTblDir->pNametab.offset+offset);
1223 niName.namelen &= 0xFF; /* FIXME: correct ? */
1224 name=TLB_Alloc((niName.namelen & 0xff) +1);
1225 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1226 name[niName.namelen & 0xff]='\0';
1228 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1229 name, -1, NULL, 0);
1231 /* no invalid characters in string */
1232 if (lengthInChars)
1234 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1236 /* don't check for invalid character since this has been done previously */
1237 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1239 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1240 lengthInChars = SysStringLen(bstrName);
1241 HeapFree(GetProcessHeap(), 0, pwstring);
1244 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1245 return bstrName;
1248 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1250 char * string;
1251 INT16 length;
1252 int lengthInChars;
1253 BSTR bstr = NULL;
1255 if(offset<0) return NULL;
1256 MSFT_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1257 if(length <= 0) return 0;
1258 string=TLB_Alloc(length +1);
1259 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1260 string[length]='\0';
1262 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1263 string, -1, NULL, 0);
1265 /* no invalid characters in string */
1266 if (lengthInChars)
1268 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1270 /* don't check for invalid character since this has been done previously */
1271 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1273 bstr = SysAllocStringLen(pwstring, lengthInChars);
1274 lengthInChars = SysStringLen(bstr);
1275 HeapFree(GetProcessHeap(), 0, pwstring);
1278 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1279 return bstr;
1282 * read a value and fill a VARIANT structure
1284 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1286 int size;
1288 TRACE_(typelib)("\n");
1290 if(offset <0) { /* data are packed in here */
1291 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1292 V_UNION(pVar, iVal) = offset & 0xffff;
1293 return;
1295 MSFT_Read(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1296 pcx->pTblDir->pCustData.offset + offset );
1297 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1298 switch (V_VT(pVar)){
1299 case VT_EMPTY: /* FIXME: is this right? */
1300 case VT_NULL: /* FIXME: is this right? */
1301 case VT_I2 : /* this should not happen */
1302 case VT_I4 :
1303 case VT_R4 :
1304 case VT_ERROR :
1305 case VT_BOOL :
1306 case VT_I1 :
1307 case VT_UI1 :
1308 case VT_UI2 :
1309 case VT_UI4 :
1310 case VT_INT :
1311 case VT_UINT :
1312 case VT_VOID : /* FIXME: is this right? */
1313 case VT_HRESULT :
1314 size=4; break;
1315 case VT_R8 :
1316 case VT_CY :
1317 case VT_DATE :
1318 case VT_I8 :
1319 case VT_UI8 :
1320 case VT_DECIMAL : /* FIXME: is this right? */
1321 case VT_FILETIME :
1322 size=8;break;
1323 /* pointer types with known behaviour */
1324 case VT_BSTR :{
1325 char * ptr;
1326 MSFT_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1327 if(size <= 0) {
1328 FIXME("BSTR length = %d?\n", size);
1329 } else {
1330 ptr=TLB_Alloc(size);/* allocate temp buffer */
1331 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1332 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1333 /* FIXME: do we need a AtoW conversion here? */
1334 V_UNION(pVar, bstrVal[size])=L'\0';
1335 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1336 TLB_Free(ptr);
1339 size=-4; break;
1340 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1341 case VT_DISPATCH :
1342 case VT_VARIANT :
1343 case VT_UNKNOWN :
1344 case VT_PTR :
1345 case VT_SAFEARRAY :
1346 case VT_CARRAY :
1347 case VT_USERDEFINED :
1348 case VT_LPSTR :
1349 case VT_LPWSTR :
1350 case VT_BLOB :
1351 case VT_STREAM :
1352 case VT_STORAGE :
1353 case VT_STREAMED_OBJECT :
1354 case VT_STORED_OBJECT :
1355 case VT_BLOB_OBJECT :
1356 case VT_CF :
1357 case VT_CLSID :
1358 default:
1359 size=0;
1360 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1361 V_VT(pVar));
1364 if(size>0) /* (big|small) endian correct? */
1365 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1366 return;
1369 * create a linked list with custom data
1371 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1373 MSFT_CDGuid entry;
1374 TLBCustData* pNew;
1375 int count=0;
1377 TRACE_(typelib)("\n");
1379 while(offset >=0){
1380 count++;
1381 pNew=TLB_Alloc(sizeof(TLBCustData));
1382 MSFT_Read(&entry, sizeof(entry), pcx,
1383 pcx->pTblDir->pCDGuids.offset+offset);
1384 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1385 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1386 /* add new custom data at head of the list */
1387 pNew->next=*ppCustData;
1388 *ppCustData=pNew;
1389 offset = entry.next;
1391 return count;
1394 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1395 ITypeInfoImpl *pTI)
1397 if(type <0)
1398 pTd->vt=type & VT_TYPEMASK;
1399 else
1400 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1402 if(pTd->vt == VT_USERDEFINED)
1403 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1405 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1408 static void
1409 MSFT_DoFuncs(TLBContext* pcx,
1410 ITypeInfoImpl* pTI,
1411 int cFuncs,
1412 int cVars,
1413 int offset,
1414 TLBFuncDesc** pptfd)
1417 * member information is stored in a data structure at offset
1418 * indicated by the memoffset field of the typeinfo structure
1419 * There are several distinctive parts.
1420 * the first part starts with a field that holds the total length
1421 * of this (first) part excluding this field. Then follow the records,
1422 * for each member there is one record.
1424 * First entry is always the length of the record (excluding this
1425 * length word).
1426 * Rest of the record depends on the type of the member. If there is
1427 * a field indicating the member type (function variable intereface etc)
1428 * I have not found it yet. At this time we depend on the information
1429 * in the type info and the usual order how things are stored.
1431 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1432 * for each member;
1434 * Third is a equal sized array with file offsets to the name entry
1435 * of each member.
1437 * Forth and last (?) part is an array with offsets to the records in the
1438 * first part of this file segment.
1441 int infolen, nameoffset, reclength, nrattributes, i;
1442 int recoffset = offset + sizeof(INT);
1444 char recbuf[512];
1445 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1447 TRACE_(typelib)("\n");
1449 MSFT_Read(&infolen, sizeof(INT), pcx, offset);
1451 for ( i = 0; i < cFuncs ; i++ )
1453 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1455 /* name, eventually add to a hash table */
1456 MSFT_Read(&nameoffset,
1457 sizeof(INT),
1458 pcx,
1459 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1461 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1463 /* read the function information record */
1464 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1466 reclength &= 0x1ff;
1468 MSFT_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1470 /* do the attributes */
1471 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1472 / sizeof(int);
1474 if ( nrattributes > 0 )
1476 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1478 if ( nrattributes > 1 )
1480 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1481 pFuncRec->OptAttr[1]) ;
1483 if ( nrattributes > 2 )
1485 if ( pFuncRec->FKCCIC & 0x2000 )
1487 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1489 else
1491 (*pptfd)->Entry = MSFT_ReadString(pcx,
1492 pFuncRec->OptAttr[2]);
1494 if( nrattributes > 5 )
1496 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1498 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1500 MSFT_CustData(pcx,
1501 pFuncRec->OptAttr[6],
1502 &(*pptfd)->pCustData);
1509 /* fill the FuncDesc Structure */
1510 MSFT_Read( & (*pptfd)->funcdesc.memid,
1511 sizeof(INT), pcx,
1512 offset + infolen + ( i + 1) * sizeof(INT));
1514 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1515 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1516 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1517 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1518 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1519 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1520 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1522 MSFT_GetTdesc(pcx,
1523 pFuncRec->DataType,
1524 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1525 pTI);
1527 /* do the parameters/arguments */
1528 if(pFuncRec->nrargs)
1530 int j = 0;
1531 MSFT_ParameterInfo paraminfo;
1533 (*pptfd)->funcdesc.lprgelemdescParam =
1534 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1536 (*pptfd)->pParamDesc =
1537 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1539 MSFT_Read(&paraminfo,
1540 sizeof(paraminfo),
1541 pcx,
1542 recoffset + reclength -
1543 pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1545 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1547 TYPEDESC* lpArgTypeDesc = 0;
1549 MSFT_GetTdesc(pcx,
1550 paraminfo.DataType,
1551 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1552 pTI);
1554 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1556 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1558 /* SEEK value = jump to offset,
1559 * from there jump to the end of record,
1560 * go back by (j-1) arguments
1562 MSFT_Read( &paraminfo ,
1563 sizeof(MSFT_ParameterInfo), pcx,
1564 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1565 * sizeof(MSFT_ParameterInfo)));
1566 lpArgTypeDesc =
1567 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1569 while ( lpArgTypeDesc != NULL )
1571 switch ( lpArgTypeDesc->vt )
1573 case VT_PTR:
1574 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1575 break;
1577 case VT_CARRAY:
1578 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1579 break;
1581 case VT_USERDEFINED:
1582 MSFT_DoRefType(pcx, pTI,
1583 lpArgTypeDesc->u.hreftype);
1585 lpArgTypeDesc = NULL;
1586 break;
1588 default:
1589 lpArgTypeDesc = NULL;
1595 /* parameter is the return value! */
1596 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1598 TYPEDESC* lpArgTypeDesc;
1600 (*pptfd)->funcdesc.elemdescFunc =
1601 (*pptfd)->funcdesc.lprgelemdescParam[j];
1603 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1605 while ( lpArgTypeDesc != NULL )
1607 switch ( lpArgTypeDesc->vt )
1609 case VT_PTR:
1610 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1611 break;
1612 case VT_CARRAY:
1613 lpArgTypeDesc =
1614 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1616 break;
1618 case VT_USERDEFINED:
1619 MSFT_DoRefType(pcx,
1620 pTI,
1621 lpArgTypeDesc->u.hreftype);
1623 lpArgTypeDesc = NULL;
1624 break;
1626 default:
1627 lpArgTypeDesc = NULL;
1632 /* second time around */
1633 for(j=0;j<pFuncRec->nrargs;j++)
1635 /* name */
1636 (*pptfd)->pParamDesc[j].Name =
1637 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1639 /* default value */
1640 if ( (PARAMFLAG_FHASDEFAULT &
1641 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1642 ((pFuncRec->FKCCIC) & 0x1000) )
1644 INT* pInt = (INT *)((char *)pFuncRec +
1645 reclength -
1646 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1648 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1650 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1651 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1653 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1654 pInt[j], pcx);
1656 /* custom info */
1657 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1659 MSFT_CustData(pcx,
1660 pFuncRec->OptAttr[7+j],
1661 &(*pptfd)->pParamDesc[j].pCustData);
1666 /* scode is not used: archaic win16 stuff FIXME: right? */
1667 (*pptfd)->funcdesc.cScodes = 0 ;
1668 (*pptfd)->funcdesc.lprgscode = NULL ;
1670 pptfd = & ((*pptfd)->next);
1671 recoffset += reclength;
1674 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1675 int cVars, int offset, TLBVarDesc ** pptvd)
1677 int infolen, nameoffset, reclength;
1678 char recbuf[256];
1679 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1680 int i;
1681 int recoffset;
1683 TRACE_(typelib)("\n");
1685 MSFT_Read(&infolen,sizeof(INT), pcx, offset);
1686 MSFT_Read(&recoffset,sizeof(INT), pcx, offset + infolen +
1687 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1688 recoffset += offset+sizeof(INT);
1689 for(i=0;i<cVars;i++){
1690 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1691 /* name, eventually add to a hash table */
1692 MSFT_Read(&nameoffset, sizeof(INT), pcx,
1693 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1694 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1695 /* read the variable information record */
1696 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1697 reclength &=0xff;
1698 MSFT_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1699 /* Optional data */
1700 if(reclength >(6*sizeof(INT)) )
1701 (*pptvd)->HelpContext=pVarRec->HelpContext;
1702 if(reclength >(7*sizeof(INT)) )
1703 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1704 if(reclength >(8*sizeof(INT)) )
1705 if(reclength >(9*sizeof(INT)) )
1706 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1707 /* fill the VarDesc Structure */
1708 MSFT_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1709 offset + infolen + ( i + 1) * sizeof(INT));
1710 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1711 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1712 MSFT_GetTdesc(pcx, pVarRec->DataType,
1713 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1714 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1715 if(pVarRec->VarKind == VAR_CONST ){
1716 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1717 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1718 pVarRec->OffsValue, pcx);
1719 } else
1720 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1721 pptvd=&((*pptvd)->next);
1722 recoffset += reclength;
1725 /* fill in data for a hreftype (offset). When the refernced type is contained
1726 * in the typelib, it's just an (file) offset in the type info base dir.
1727 * If comes from import, it's an offset+1 in the ImpInfo table
1728 * */
1729 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1730 int offset)
1732 int j;
1733 TLBRefType **ppRefType = &pTI->reflist;
1735 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1737 while(*ppRefType) {
1738 if((*ppRefType)->reference == offset)
1739 return;
1740 ppRefType = &(*ppRefType)->next;
1743 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1744 sizeof(**ppRefType));
1746 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1747 /* external typelib */
1748 MSFT_ImpInfo impinfo;
1749 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1751 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1753 MSFT_Read(&impinfo, sizeof(impinfo), pcx,
1754 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1755 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1756 if(pImpLib->offset==impinfo.oImpFile) break;
1757 pImpLib=pImpLib->next;
1759 if(pImpLib){
1760 (*ppRefType)->reference=offset;
1761 (*ppRefType)->pImpTLInfo = pImpLib;
1762 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1763 (*ppRefType)->index = TLB_REF_USE_GUID;
1764 }else{
1765 ERR("Cannot find a reference\n");
1766 (*ppRefType)->reference=-1;
1767 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1769 }else{
1770 /* in this typelib */
1771 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1772 (*ppRefType)->reference=offset;
1773 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1777 /* process Implemented Interfaces of a com class */
1778 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1779 int offset)
1781 int i;
1782 MSFT_RefRecord refrec;
1783 TLBImplType **ppImpl = &pTI->impltypelist;
1785 TRACE_(typelib)("\n");
1787 for(i=0;i<count;i++){
1788 if(offset<0) break; /* paranoia */
1789 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1790 MSFT_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1791 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1792 (*ppImpl)->hRef = refrec.reftype;
1793 (*ppImpl)->implflags=refrec.flags;
1794 (*ppImpl)->ctCustData=
1795 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1796 offset=refrec.onext;
1797 ppImpl=&((*ppImpl)->next);
1801 * process a typeinfo record
1803 ITypeInfoImpl * MSFT_DoTypeInfo(
1804 TLBContext *pcx,
1805 int count,
1806 ITypeLibImpl * pLibInfo)
1808 MSFT_TypeInfoBase tiBase;
1809 ITypeInfoImpl *ptiRet;
1811 TRACE_(typelib)("count=%u\n", count);
1813 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1814 MSFT_Read(&tiBase, sizeof(tiBase) ,pcx ,
1815 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1816 /* this is where we are coming from */
1817 ptiRet->pTypeLib = pLibInfo;
1818 ITypeLib2_AddRef((ITypeLib2 *)pLibInfo);
1819 ptiRet->index=count;
1820 /* fill in the typeattr fields */
1821 FIXME("Assign constructor/destructor memid\n");
1823 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1824 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1825 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1826 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1827 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1828 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1829 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1830 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1831 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1832 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1833 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1834 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1835 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1836 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1837 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1838 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1839 MSFT_GetTdesc(pcx, tiBase.datatype1,
1840 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1842 /* FIXME: */
1843 /* IDLDESC idldescType; *//* never saw this one != zero */
1845 /* name, eventually add to a hash table */
1846 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1847 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1848 /* help info */
1849 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1850 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1851 ptiRet->dwHelpContext=tiBase.helpcontext;
1852 /* note: InfoType's Help file and HelpStringDll come from the containing
1853 * library. Further HelpString and Docstring appear to be the same thing :(
1855 /* functions */
1856 if(ptiRet->TypeAttr.cFuncs >0 )
1857 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1858 ptiRet->TypeAttr.cVars,
1859 tiBase.memoffset, & ptiRet->funclist);
1860 /* variables */
1861 if(ptiRet->TypeAttr.cVars >0 )
1862 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1863 ptiRet->TypeAttr.cVars,
1864 tiBase.memoffset, & ptiRet->varlist);
1865 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1866 switch(ptiRet->TypeAttr.typekind)
1868 case TKIND_COCLASS:
1869 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1870 tiBase.datatype1);
1871 break;
1872 case TKIND_DISPATCH:
1873 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1875 if (tiBase.datatype1 != -1)
1877 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1878 ptiRet->impltypelist->hRef = tiBase.datatype1;
1880 else
1881 { /* FIXME: This is a really bad hack to add IDispatch */
1882 char* szStdOle = "stdole2.tlb\0";
1883 int nStdOleLen = strlen(szStdOle);
1884 TLBRefType **ppRef = &ptiRet->reflist;
1886 while(*ppRef) {
1887 if((*ppRef)->reference == -1)
1888 break;
1889 ppRef = &(*ppRef)->next;
1891 if(!*ppRef) {
1892 *ppRef = TLB_Alloc(sizeof(**ppRef));
1893 (*ppRef)->guid = IID_IDispatch;
1894 (*ppRef)->reference = -1;
1895 (*ppRef)->index = TLB_REF_USE_GUID;
1896 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1897 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1898 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1899 nStdOleLen + 1);
1901 MultiByteToWideChar(CP_ACP,
1902 MB_PRECOMPOSED,
1903 szStdOle,
1905 (*ppRef)->pImpTLInfo->name,
1906 SysStringLen((*ppRef)->pImpTLInfo->name));
1908 (*ppRef)->pImpTLInfo->lcid = 0;
1909 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1910 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1913 break;
1914 default:
1915 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1916 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1917 ptiRet->impltypelist->hRef = tiBase.datatype1;
1918 break;
1921 ptiRet->ctCustData=
1922 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1924 TRACE_(typelib)("%s guid: %s kind:%s\n",
1925 debugstr_w(ptiRet->Name),
1926 debugstr_guid(&ptiRet->TypeAttr.guid),
1927 typekind_desc[ptiRet->TypeAttr.typekind]);
1929 return ptiRet;
1932 /****************************************************************************
1933 * TLB_ReadTypeLib
1935 * find the type of the typelib file and map the typelib resource into
1936 * the memory
1938 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1939 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1940 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1942 int ret = TYPE_E_CANTLOADLIBRARY;
1943 DWORD dwSignature = 0;
1944 HFILE hFile;
1946 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1948 *ppTypeLib = NULL;
1950 /* check the signature of the file */
1951 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1952 if (INVALID_HANDLE_VALUE != hFile)
1954 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1955 if (hMapping)
1957 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1958 if(pBase)
1960 /* retrieve file size */
1961 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1963 /* first try to load as *.tlb */
1964 dwSignature = *((DWORD*) pBase);
1965 if ( dwSignature == MSFT_SIGNATURE)
1967 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1969 else if ( dwSignature == SLTG_SIGNATURE)
1971 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1973 UnmapViewOfFile(pBase);
1975 CloseHandle(hMapping);
1977 CloseHandle(hFile);
1980 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1982 /* find the typelibrary resource*/
1983 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
1984 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1985 if (hinstDLL)
1987 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
1988 "TYPELIB");
1989 if (hrsrc)
1991 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1992 if (hGlobal)
1994 LPVOID pBase = LockResource(hGlobal);
1995 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1997 if (pBase)
1999 /* try to load as incore resource */
2000 dwSignature = *((DWORD*) pBase);
2001 if ( dwSignature == MSFT_SIGNATURE)
2003 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2005 else if ( dwSignature == SLTG_SIGNATURE)
2007 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2009 else
2011 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2014 FreeResource( hGlobal );
2017 FreeLibrary(hinstDLL);
2021 if(*ppTypeLib)
2022 ret = S_OK;
2023 else
2024 ERR("Loading of typelib %s failed with error %ld\n",
2025 debugstr_w(pszFileName), GetLastError());
2027 return ret;
2030 /*================== ITypeLib(2) Methods ===================================*/
2032 /****************************************************************************
2033 * ITypeLib2_Constructor_MSFT
2035 * loading an MSFT typelib from an in-memory image
2037 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2039 TLBContext cx;
2040 long lPSegDir;
2041 MSFT_Header tlbHeader;
2042 MSFT_SegDir tlbSegDir;
2043 ITypeLibImpl * pTypeLibImpl;
2045 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2047 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2048 if (!pTypeLibImpl) return NULL;
2050 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2051 pTypeLibImpl->ref = 1;
2053 /* get pointer to beginning of typelib data */
2054 cx.pos = 0;
2055 cx.oStart=0;
2056 cx.mapping = pLib;
2057 cx.pLibInfo = pTypeLibImpl;
2058 cx.length = dwTLBLength;
2060 /* read header */
2061 MSFT_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2062 TRACE("header:\n");
2063 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2064 if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
2065 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2066 return NULL;
2068 /* there is a small amount of information here until the next important
2069 * part:
2070 * the segment directory . Try to calculate the amount of data */
2071 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2073 /* now read the segment directory */
2074 TRACE("read segment directory (at %ld)\n",lPSegDir);
2075 MSFT_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2076 cx.pTblDir = &tlbSegDir;
2078 /* just check two entries */
2079 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2081 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2082 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2083 return NULL;
2086 /* now fill our internal data */
2087 /* TLIBATTR fields */
2088 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2090 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2091 /* Windows seems to have zero here, is this correct? */
2092 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2093 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2094 else
2095 pTypeLibImpl->LibAttr.lcid = 0;
2097 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2098 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2099 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2100 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2102 /* name, eventually add to a hash table */
2103 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2105 /* help info */
2106 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2107 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2109 if( tlbHeader.varflags & HELPDLLFLAG)
2111 int offset;
2112 MSFT_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2113 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2116 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2118 /* custom data */
2119 if(tlbHeader.CustomDataOffset >= 0)
2121 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2124 /* fill in typedescriptions */
2125 if(tlbSegDir.pTypdescTab.length > 0)
2127 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2128 INT16 td[4];
2129 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2130 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2131 for(i=0; i<cTD; )
2133 /* FIXME: add several sanity checks here */
2134 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2135 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2137 /* FIXME: check safearray */
2138 if(td[3] < 0)
2139 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2140 else
2141 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2143 else if(td[0] == VT_CARRAY)
2145 /* array descr table here */
2146 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2148 else if(td[0] == VT_USERDEFINED)
2150 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2152 if(++i<cTD) MSFT_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
2155 /* second time around to fill the array subscript info */
2156 for(i=0;i<cTD;i++)
2158 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2159 if(tlbSegDir.pArrayDescriptions.offset>0)
2161 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2162 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2164 if(td[1]<0)
2165 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2166 else
2167 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2169 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2171 for(j = 0; j<td[2]; j++)
2173 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2174 sizeof(INT), &cx, DO_NOT_SEEK);
2175 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2176 sizeof(INT), &cx, DO_NOT_SEEK);
2179 else
2181 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2182 ERR("didn't find array description data\n");
2187 /* imported type libs */
2188 if(tlbSegDir.pImpFiles.offset>0)
2190 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2191 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2192 UINT16 size;
2194 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2196 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2197 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2198 MSFT_Read(&oGuid, sizeof(INT), &cx, offset);
2200 MSFT_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2201 MSFT_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2202 MSFT_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2203 MSFT_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2205 size >>= 2;
2206 (*ppImpLib)->name = TLB_Alloc(size+1);
2207 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2208 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2209 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2211 ppImpLib = &(*ppImpLib)->next;
2215 /* type info's */
2216 if(tlbHeader.nrtypeinfos >= 0 )
2218 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2219 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2220 int i;
2222 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2224 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2226 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2227 ppTI = &((*ppTI)->next);
2228 (pTypeLibImpl->TypeInfoCount)++;
2232 TRACE("(%p)\n", pTypeLibImpl);
2233 return (ITypeLib2*) pTypeLibImpl;
2237 static BSTR TLB_MultiByteToBSTR(char *ptr)
2239 DWORD len;
2240 WCHAR *nameW;
2241 BSTR ret;
2243 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2244 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2245 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2246 ret = SysAllocString(nameW);
2247 HeapFree(GetProcessHeap(), 0, nameW);
2248 return ret;
2251 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2253 char b[3];
2254 int i;
2255 short s;
2257 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2258 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2259 return FALSE;
2262 guid->Data4[0] = s >> 8;
2263 guid->Data4[1] = s & 0xff;
2265 b[2] = '\0';
2266 for(i = 0; i < 6; i++) {
2267 memcpy(b, str + 24 + 2 * i, 2);
2268 guid->Data4[i + 2] = strtol(b, NULL, 16);
2270 return TRUE;
2273 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2275 WORD bytelen;
2276 DWORD len;
2277 WCHAR *nameW;
2279 *pBstr = NULL;
2280 bytelen = *(WORD*)ptr;
2281 if(bytelen == 0xffff) return 2;
2282 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2283 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2284 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2285 *pBstr = SysAllocStringLen(nameW, len);
2286 HeapFree(GetProcessHeap(), 0, nameW);
2287 return bytelen + 2;
2290 static WORD SLTG_ReadStringA(char *ptr, char **str)
2292 WORD bytelen;
2294 *str = NULL;
2295 bytelen = *(WORD*)ptr;
2296 if(bytelen == 0xffff) return 2;
2297 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2298 memcpy(*str, ptr + 2, bytelen);
2299 (*str)[bytelen] = '\0';
2300 return bytelen + 2;
2303 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2305 char *ptr = pLibBlk;
2306 WORD w;
2308 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2309 FIXME("libblk magic = %04x\n", w);
2310 return 0;
2313 ptr += 6;
2314 if((w = *(WORD*)ptr) != 0xffff) {
2315 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2316 ptr += w;
2318 ptr += 2;
2320 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2322 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2324 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2325 ptr += 4;
2327 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2328 ptr += 2;
2330 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2331 ptr += 2;
2333 ptr += 4; /* skip res12 */
2335 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2336 ptr += 2;
2338 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2339 ptr += 2;
2341 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2342 ptr += 2;
2344 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2345 ptr += sizeof(GUID);
2347 return ptr - (char*)pLibBlk;
2350 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2352 BOOL done = FALSE;
2353 TYPEDESC *pTD = &pElem->tdesc;
2355 /* Handle [in/out] first */
2356 if((*pType & 0xc000) == 0xc000)
2357 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2358 else if(*pType & 0x8000)
2359 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2360 else if(*pType & 0x4000)
2361 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2362 else
2363 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2365 if(*pType & 0x2000)
2366 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2368 if(*pType & 0x80)
2369 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2371 while(!done) {
2372 if((*pType & 0xe00) == 0xe00) {
2373 pTD->vt = VT_PTR;
2374 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2375 sizeof(TYPEDESC));
2376 pTD = pTD->u.lptdesc;
2378 switch(*pType & 0x7f) {
2379 case VT_PTR:
2380 pTD->vt = VT_PTR;
2381 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2382 sizeof(TYPEDESC));
2383 pTD = pTD->u.lptdesc;
2384 break;
2386 case VT_USERDEFINED:
2387 pTD->vt = VT_USERDEFINED;
2388 pTD->u.hreftype = *(++pType) / 4;
2389 done = TRUE;
2390 break;
2392 case VT_CARRAY:
2394 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2395 array */
2397 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2399 pTD->vt = VT_CARRAY;
2400 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2401 sizeof(ARRAYDESC) +
2402 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2403 pTD->u.lpadesc->cDims = pSA->cDims;
2404 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2405 pSA->cDims * sizeof(SAFEARRAYBOUND));
2407 pTD = &pTD->u.lpadesc->tdescElem;
2408 break;
2411 case VT_SAFEARRAY:
2413 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2414 useful? */
2416 pType++;
2417 pTD->vt = VT_SAFEARRAY;
2418 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2419 sizeof(TYPEDESC));
2420 pTD = pTD->u.lptdesc;
2421 break;
2423 default:
2424 pTD->vt = *pType & 0x7f;
2425 done = TRUE;
2426 break;
2428 pType++;
2430 return pType;
2434 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2435 char *pNameTable)
2437 int ref;
2438 char *name;
2439 TLBRefType **ppRefType;
2441 if(pRef->magic != SLTG_REF_MAGIC) {
2442 FIXME("Ref magic = %x\n", pRef->magic);
2443 return;
2445 name = ( (char*)(&pRef->names) + pRef->number);
2447 ppRefType = &pTI->reflist;
2448 for(ref = 0; ref < pRef->number >> 3; ref++) {
2449 char *refname;
2450 unsigned int lib_offs, type_num;
2452 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2453 sizeof(**ppRefType));
2455 name += SLTG_ReadStringA(name, &refname);
2456 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2457 FIXME("Can't sscanf ref\n");
2458 if(lib_offs != 0xffff) {
2459 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2461 while(*import) {
2462 if((*import)->offset == lib_offs)
2463 break;
2464 import = &(*import)->next;
2466 if(!*import) {
2467 char fname[MAX_PATH+1];
2468 int len;
2470 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2471 sizeof(**import));
2472 (*import)->offset = lib_offs;
2473 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2474 &(*import)->guid);
2475 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2476 &(*import)->wVersionMajor,
2477 &(*import)->wVersionMinor,
2478 &(*import)->lcid, fname) != 4) {
2479 FIXME("can't sscanf ref %s\n",
2480 pNameTable + lib_offs + 40);
2482 len = strlen(fname);
2483 if(fname[len-1] != '#')
2484 FIXME("fname = %s\n", fname);
2485 fname[len-1] = '\0';
2486 (*import)->name = TLB_MultiByteToBSTR(fname);
2488 (*ppRefType)->pImpTLInfo = *import;
2489 } else { /* internal ref */
2490 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2492 (*ppRefType)->reference = ref;
2493 (*ppRefType)->index = type_num;
2495 HeapFree(GetProcessHeap(), 0, refname);
2496 ppRefType = &(*ppRefType)->next;
2498 if((BYTE)*name != SLTG_REF_MAGIC)
2499 FIXME("End of ref block magic = %x\n", *name);
2500 dump_TLBRefType(pTI->reflist);
2503 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2504 BOOL OneOnly)
2506 SLTG_ImplInfo *info;
2507 TLBImplType **ppImplType = &pTI->impltypelist;
2508 /* I don't really get this structure, usually it's 0x16 bytes
2509 long, but iuser.tlb contains some that are 0x18 bytes long.
2510 That's ok because we can use the next ptr to jump to the next
2511 one. But how do we know the length of the last one? The WORD
2512 at offs 0x8 might be the clue. For now I'm just assuming that
2513 the last one is the regular 0x16 bytes. */
2515 info = (SLTG_ImplInfo*)pBlk;
2516 while(1) {
2517 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2518 sizeof(**ppImplType));
2519 (*ppImplType)->hRef = info->ref;
2520 (*ppImplType)->implflags = info->impltypeflags;
2521 pTI->TypeAttr.cImplTypes++;
2522 ppImplType = &(*ppImplType)->next;
2524 if(info->next == 0xffff)
2525 break;
2526 if(OneOnly)
2527 FIXME("Interface inheriting more than one interface\n");
2528 info = (SLTG_ImplInfo*)(pBlk + info->next);
2530 info++; /* see comment at top of function */
2531 return (char*)info;
2534 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2535 char *pNameTable)
2537 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2538 SLTG_MemberHeader *pMemHeader;
2539 char *pFirstItem, *pNextItem;
2541 if(pTIHeader->href_table != 0xffffffff) {
2542 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2543 pNameTable);
2547 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2549 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2551 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2552 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2555 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2559 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2560 char *pNameTable)
2562 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2563 SLTG_MemberHeader *pMemHeader;
2564 SLTG_Function *pFunc;
2565 char *pFirstItem, *pNextItem;
2566 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2567 int num = 0;
2569 if(pTIHeader->href_table != 0xffffffff) {
2570 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2571 pNameTable);
2574 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2576 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2578 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2579 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2582 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2583 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2585 int param;
2586 WORD *pType, *pArg;
2588 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2589 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2590 FIXME("func magic = %02x\n", pFunc->magic);
2591 return NULL;
2593 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2594 sizeof(**ppFuncDesc));
2595 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2597 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2598 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2599 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2600 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2601 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2602 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2604 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2605 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2607 if(pFunc->retnextopt & 0x80)
2608 pType = &pFunc->rettype;
2609 else
2610 pType = (WORD*)(pFirstItem + pFunc->rettype);
2613 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2615 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2616 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2617 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2618 (*ppFuncDesc)->pParamDesc =
2619 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2620 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2622 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2624 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2625 char *paramName = pNameTable + *pArg;
2626 BOOL HaveOffs;
2627 /* If arg type follows then paramName points to the 2nd
2628 letter of the name, else the next WORD is an offset to
2629 the arg type and paramName points to the first letter.
2630 So let's take one char off paramName and see if we're
2631 pointing at an alpha-numeric char. However if *pArg is
2632 0xffff or 0xfffe then the param has no name, the former
2633 meaning that the next WORD is the type, the latter
2634 meaning the the next WORD is an offset to the type. */
2636 HaveOffs = FALSE;
2637 if(*pArg == 0xffff)
2638 paramName = NULL;
2639 else if(*pArg == 0xfffe) {
2640 paramName = NULL;
2641 HaveOffs = TRUE;
2643 else if(!isalnum(*(paramName-1)))
2644 HaveOffs = TRUE;
2646 pArg++;
2648 if(HaveOffs) { /* the next word is an offset to type */
2649 pType = (WORD*)(pFirstItem + *pArg);
2650 SLTG_DoType(pType, pFirstItem,
2651 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2652 pArg++;
2653 } else {
2654 if(paramName)
2655 paramName--;
2656 pArg = SLTG_DoType(pArg, pFirstItem,
2657 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2660 /* Are we an optional param ? */
2661 if((*ppFuncDesc)->funcdesc.cParams - param <=
2662 (*ppFuncDesc)->funcdesc.cParamsOpt)
2663 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2665 if(paramName) {
2666 (*ppFuncDesc)->pParamDesc[param].Name =
2667 TLB_MultiByteToBSTR(paramName);
2671 ppFuncDesc = &((*ppFuncDesc)->next);
2672 if(pFunc->next == 0xffff) break;
2674 pTI->TypeAttr.cFuncs = num;
2675 dump_TLBFuncDesc(pTI->funclist);
2676 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2679 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2680 char *pNameTable)
2682 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2683 SLTG_MemberHeader *pMemHeader;
2684 SLTG_RecordItem *pItem;
2685 char *pFirstItem;
2686 TLBVarDesc **ppVarDesc = &pTI->varlist;
2687 int num = 0;
2688 WORD *pType;
2689 char buf[300];
2691 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2693 pFirstItem = (char*)(pMemHeader + 1);
2694 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2695 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2696 if(pItem->magic != SLTG_RECORD_MAGIC) {
2697 FIXME("record magic = %02x\n", pItem->magic);
2698 return NULL;
2700 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2701 sizeof(**ppVarDesc));
2702 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2703 (*ppVarDesc)->vardesc.memid = pItem->memid;
2704 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2705 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2707 if(pItem->typepos == 0x02)
2708 pType = &pItem->type;
2709 else if(pItem->typepos == 0x00)
2710 pType = (WORD*)(pFirstItem + pItem->type);
2711 else {
2712 FIXME("typepos = %02x\n", pItem->typepos);
2713 break;
2716 SLTG_DoType(pType, pFirstItem,
2717 &(*ppVarDesc)->vardesc.elemdescVar);
2719 /* FIXME("helpcontext, helpstring\n"); */
2721 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2723 ppVarDesc = &((*ppVarDesc)->next);
2724 if(pItem->next == 0xffff) break;
2726 pTI->TypeAttr.cVars = num;
2727 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2730 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2731 char *pNameTable)
2733 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2734 SLTG_MemberHeader *pMemHeader;
2735 SLTG_EnumItem *pItem;
2736 char *pFirstItem;
2737 TLBVarDesc **ppVarDesc = &pTI->varlist;
2738 int num = 0;
2740 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2742 pFirstItem = (char*)(pMemHeader + 1);
2743 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2744 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2745 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2746 FIXME("enumitem magic = %04x\n", pItem->magic);
2747 return NULL;
2749 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2750 sizeof(**ppVarDesc));
2751 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2752 (*ppVarDesc)->vardesc.memid = pItem->memid;
2753 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2754 sizeof(VARIANT));
2755 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2756 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2757 *(INT*)(pItem->value + pFirstItem);
2758 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2759 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2760 /* FIXME("helpcontext, helpstring\n"); */
2762 ppVarDesc = &((*ppVarDesc)->next);
2763 if(pItem->next == 0xffff) break;
2765 pTI->TypeAttr.cVars = num;
2766 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2769 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2770 managable copy of it into this */
2771 typedef struct {
2772 WORD small_no;
2773 char *index_name;
2774 char *other_name;
2775 WORD res1a;
2776 WORD name_offs;
2777 WORD more_bytes;
2778 char *extra;
2779 WORD res20;
2780 DWORD helpcontext;
2781 WORD res26;
2782 GUID uuid;
2783 } SLTG_InternalOtherTypeInfo;
2785 /****************************************************************************
2786 * ITypeLib2_Constructor_SLTG
2788 * loading a SLTG typelib from an in-memory image
2790 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2792 ITypeLibImpl *pTypeLibImpl;
2793 SLTG_Header *pHeader;
2794 SLTG_BlkEntry *pBlkEntry;
2795 SLTG_Magic *pMagic;
2796 SLTG_Index *pIndex;
2797 SLTG_Pad9 *pPad9;
2798 LPVOID pBlk, pFirstBlk;
2799 SLTG_LibBlk *pLibBlk;
2800 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2801 char *pAfterOTIBlks = NULL;
2802 char *pNameTable, *ptr;
2803 int i;
2804 DWORD len, order;
2805 ITypeInfoImpl **ppTypeInfoImpl;
2807 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2809 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2810 if (!pTypeLibImpl) return NULL;
2812 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2813 pTypeLibImpl->ref = 1;
2815 pHeader = pLib;
2817 TRACE("header:\n");
2818 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2819 pHeader->nrOfFileBlks );
2820 if (memcmp(&pHeader->SLTG_magic, TLBMAGIC1, 4)) {
2821 FIXME("Header type magic 0x%08lx not supported.\n",
2822 pHeader->SLTG_magic);
2823 return NULL;
2826 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2827 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2829 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2830 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2832 /* Next we have a magic block */
2833 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2835 /* Let's see if we're still in sync */
2836 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2837 sizeof(SLTG_COMPOBJ_MAGIC))) {
2838 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2839 return NULL;
2841 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2842 sizeof(SLTG_DIR_MAGIC))) {
2843 FIXME("dir magic = %s\n", pMagic->dir_magic);
2844 return NULL;
2847 pIndex = (SLTG_Index*)(pMagic+1);
2849 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2851 pFirstBlk = (LPVOID)(pPad9 + 1);
2853 /* We'll set up a ptr to the main library block, which is the last one. */
2855 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2856 pBlkEntry[order].next != 0;
2857 order = pBlkEntry[order].next - 1, i++) {
2858 pBlk += pBlkEntry[order].len;
2860 pLibBlk = pBlk;
2862 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2864 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2865 interspersed */
2867 len += 0x40;
2869 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2871 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2872 sizeof(*pOtherTypeInfoBlks) *
2873 pTypeLibImpl->TypeInfoCount);
2876 ptr = (char*)pLibBlk + len;
2878 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2879 WORD w, extra;
2880 len = 0;
2882 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2884 w = *(WORD*)(ptr + 2);
2885 if(w != 0xffff) {
2886 len += w;
2887 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2888 w+1);
2889 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2890 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2892 w = *(WORD*)(ptr + 4 + len);
2893 if(w != 0xffff) {
2894 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2895 len += w;
2896 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2897 w+1);
2898 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2899 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2901 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2902 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2903 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2904 if(extra) {
2905 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2906 extra);
2907 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2908 len += extra;
2910 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2911 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2912 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2913 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2914 len += sizeof(SLTG_OtherTypeInfo);
2915 ptr += len;
2918 pAfterOTIBlks = ptr;
2920 /* Skip this WORD and get the next DWORD */
2921 len = *(DWORD*)(pAfterOTIBlks + 2);
2923 /* Now add this to pLibBLk look at what we're pointing at and
2924 possibly add 0x20, then add 0x216, sprinkle a bit a magic
2925 dust and we should be pointing at the beginning of the name
2926 table */
2928 pNameTable = (char*)pLibBlk + len;
2930 switch(*(WORD*)pNameTable) {
2931 case 0xffff:
2932 break;
2933 case 0x0200:
2934 pNameTable += 0x20;
2935 break;
2936 default:
2937 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
2938 break;
2941 pNameTable += 0x216;
2943 pNameTable += 2;
2945 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
2947 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
2950 /* Hopefully we now have enough ptrs set up to actually read in
2951 some TypeInfos. It's not clear which order to do them in, so
2952 I'll just follow the links along the BlkEntry chain and read
2953 them in in the order in which they're in the file */
2955 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
2957 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2958 pBlkEntry[order].next != 0;
2959 order = pBlkEntry[order].next - 1, i++) {
2961 SLTG_TypeInfoHeader *pTIHeader;
2962 SLTG_TypeInfoTail *pTITail;
2964 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
2965 pOtherTypeInfoBlks[i].index_name)) {
2966 FIXME("Index strings don't match\n");
2967 return NULL;
2970 pTIHeader = pBlk;
2971 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
2972 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
2973 return NULL;
2975 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
2976 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
2977 ITypeLib2_AddRef((ITypeLib2 *)pTypeLibImpl);
2978 (*ppTypeInfoImpl)->index = i;
2979 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
2980 pOtherTypeInfoBlks[i].name_offs +
2981 pNameTable);
2982 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
2983 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
2984 sizeof(GUID));
2985 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
2986 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
2987 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
2988 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
2989 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
2991 if((pTIHeader->typeflags1 & 7) != 2)
2992 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
2993 if(pTIHeader->typeflags3 != 2)
2994 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
2996 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2997 debugstr_w((*ppTypeInfoImpl)->Name),
2998 typekind_desc[pTIHeader->typekind],
2999 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3000 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3002 switch(pTIHeader->typekind) {
3003 case TKIND_ENUM:
3004 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3005 break;
3007 case TKIND_RECORD:
3008 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3009 break;
3011 case TKIND_INTERFACE:
3012 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3013 break;
3015 case TKIND_COCLASS:
3016 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3017 break;
3019 default:
3020 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3021 pTITail = NULL;
3022 break;
3026 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3027 but we've already set those */
3028 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3029 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3030 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3032 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3033 pBlk += pBlkEntry[order].len;
3036 if(i != pTypeLibImpl->TypeInfoCount) {
3037 FIXME("Somehow processed %d TypeInfos\n", i);
3038 return NULL;
3041 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3042 return (ITypeLib2*)pTypeLibImpl;
3045 /* ITypeLib::QueryInterface
3047 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3048 ITypeLib2 * iface,
3049 REFIID riid,
3050 VOID **ppvObject)
3052 ICOM_THIS( ITypeLibImpl, iface);
3054 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3056 *ppvObject=NULL;
3057 if(IsEqualIID(riid, &IID_IUnknown) ||
3058 IsEqualIID(riid,&IID_ITypeLib)||
3059 IsEqualIID(riid,&IID_ITypeLib2))
3061 *ppvObject = This;
3064 if(*ppvObject)
3066 ITypeLib2_AddRef(iface);
3067 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3068 return S_OK;
3070 TRACE("-- Interface: E_NOINTERFACE\n");
3071 return E_NOINTERFACE;
3074 /* ITypeLib::AddRef
3076 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3078 ICOM_THIS( ITypeLibImpl, iface);
3080 TRACE("(%p)->ref is %u\n",This, This->ref);
3082 return ++(This->ref);
3085 /* ITypeLib::Release
3087 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3089 ICOM_THIS( ITypeLibImpl, iface);
3091 --(This->ref);
3093 TRACE("(%p)->(%u)\n",This, This->ref);
3095 if (!This->ref)
3097 /* FIXME destroy child objects */
3099 TRACE(" destroying ITypeLib(%p)\n",This);
3101 if (This->Name)
3103 SysFreeString(This->Name);
3104 This->Name = NULL;
3107 if (This->DocString)
3109 SysFreeString(This->DocString);
3110 This->DocString = NULL;
3113 if (This->HelpFile)
3115 SysFreeString(This->HelpFile);
3116 This->HelpFile = NULL;
3119 if (This->HelpStringDll)
3121 SysFreeString(This->HelpStringDll);
3122 This->HelpStringDll = NULL;
3125 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3126 HeapFree(GetProcessHeap(),0,This);
3127 return 0;
3130 return This->ref;
3133 /* ITypeLib::GetTypeInfoCount
3135 * Returns the number of type descriptions in the type library
3137 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3139 ICOM_THIS( ITypeLibImpl, iface);
3140 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3141 return This->TypeInfoCount;
3144 /* ITypeLib::GetTypeInfo
3146 * retrieves the specified type description in the library.
3148 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3149 ITypeLib2 *iface,
3150 UINT index,
3151 ITypeInfo **ppTInfo)
3153 int i;
3155 ICOM_THIS( ITypeLibImpl, iface);
3156 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3158 TRACE("(%p)->(index=%d) \n", This, index);
3160 if (!ppTInfo) return E_INVALIDARG;
3162 /* search element n in list */
3163 for(i=0; i < index; i++)
3165 pTypeInfo = pTypeInfo->next;
3166 if (!pTypeInfo)
3168 TRACE("-- element not found\n");
3169 return TYPE_E_ELEMENTNOTFOUND;
3173 *ppTInfo = (ITypeInfo *) pTypeInfo;
3175 ITypeInfo_AddRef(*ppTInfo);
3176 TRACE("-- found (%p)\n",*ppTInfo);
3177 return S_OK;
3181 /* ITypeLibs::GetTypeInfoType
3183 * Retrieves the type of a type description.
3185 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3186 ITypeLib2 *iface,
3187 UINT index,
3188 TYPEKIND *pTKind)
3190 ICOM_THIS( ITypeLibImpl, iface);
3191 int i;
3192 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3194 TRACE("(%p) index %d \n",This, index);
3196 if(!pTKind) return E_INVALIDARG;
3198 /* search element n in list */
3199 for(i=0; i < index; i++)
3201 if(!pTInfo)
3203 TRACE("-- element not found\n");
3204 return TYPE_E_ELEMENTNOTFOUND;
3206 pTInfo = pTInfo->next;
3209 *pTKind = pTInfo->TypeAttr.typekind;
3210 TRACE("-- found Type (%d)\n", *pTKind);
3211 return S_OK;
3214 /* ITypeLib::GetTypeInfoOfGuid
3216 * Retrieves the type description that corresponds to the specified GUID.
3219 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3220 ITypeLib2 *iface,
3221 REFGUID guid,
3222 ITypeInfo **ppTInfo)
3224 ICOM_THIS( ITypeLibImpl, iface);
3225 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3227 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3229 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3231 /* search linked list for guid */
3232 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3234 pTypeInfo = pTypeInfo->next;
3236 if (!pTypeInfo)
3238 /* end of list reached */
3239 TRACE("-- element not found\n");
3240 return TYPE_E_ELEMENTNOTFOUND;
3244 TRACE("-- found (%p, %s)\n",
3245 pTypeInfo,
3246 debugstr_w(pTypeInfo->Name));
3248 *ppTInfo = (ITypeInfo*)pTypeInfo;
3249 ITypeInfo_AddRef(*ppTInfo);
3250 return S_OK;
3253 /* ITypeLib::GetLibAttr
3255 * Retrieves the structure that contains the library's attributes.
3258 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3259 ITypeLib2 *iface,
3260 LPTLIBATTR *ppTLibAttr)
3262 ICOM_THIS( ITypeLibImpl, iface);
3263 TRACE("(%p)\n",This);
3264 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3265 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3266 return S_OK;
3269 /* ITypeLib::GetTypeComp
3271 * Enables a client compiler to bind to a library's types, variables,
3272 * constants, and global functions.
3275 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3276 ITypeLib2 *iface,
3277 ITypeComp **ppTComp)
3279 ICOM_THIS( ITypeLibImpl, iface);
3280 FIXME("(%p): stub!\n",This);
3281 return E_NOTIMPL;
3284 /* ITypeLib::GetDocumentation
3286 * Retrieves the library's documentation string, the complete Help file name
3287 * and path, and the context identifier for the library Help topic in the Help
3288 * file.
3290 * On a successful return all non-null BSTR pointers will have been set,
3291 * possibly to NULL.
3293 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3294 ITypeLib2 *iface,
3295 INT index,
3296 BSTR *pBstrName,
3297 BSTR *pBstrDocString,
3298 DWORD *pdwHelpContext,
3299 BSTR *pBstrHelpFile)
3301 ICOM_THIS( ITypeLibImpl, iface);
3303 HRESULT result = E_INVALIDARG;
3305 ITypeInfo *pTInfo;
3308 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3309 This, index,
3310 pBstrName, pBstrDocString,
3311 pdwHelpContext, pBstrHelpFile);
3313 if(index<0)
3315 /* documentation for the typelib */
3316 if(pBstrName)
3318 if (This->Name)
3319 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3320 else
3321 *pBstrName = NULL;
3323 if(pBstrDocString)
3325 if (This->DocString)
3326 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3327 else if (This->Name)
3328 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3329 else
3330 *pBstrDocString = NULL;
3332 if(pdwHelpContext)
3334 *pdwHelpContext = This->dwHelpContext;
3336 if(pBstrHelpFile)
3338 if (This->HelpFile)
3339 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3340 else
3341 *pBstrHelpFile = NULL;
3344 result = S_OK;
3346 else
3348 /* for a typeinfo */
3349 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3351 if(SUCCEEDED(result))
3353 result = ITypeInfo_GetDocumentation(pTInfo,
3354 MEMBERID_NIL,
3355 pBstrName,
3356 pBstrDocString,
3357 pdwHelpContext, pBstrHelpFile);
3359 ITypeInfo_Release(pTInfo);
3362 return result;
3363 memerr3:
3364 if (pBstrDocString) SysFreeString (*pBstrDocString);
3365 memerr2:
3366 if (pBstrName) SysFreeString (*pBstrName);
3367 memerr1:
3368 return STG_E_INSUFFICIENTMEMORY;
3371 /* ITypeLib::IsName
3373 * Indicates whether a passed-in string contains the name of a type or member
3374 * described in the library.
3377 static HRESULT WINAPI ITypeLib2_fnIsName(
3378 ITypeLib2 *iface,
3379 LPOLESTR szNameBuf,
3380 ULONG lHashVal,
3381 BOOL *pfName)
3383 ICOM_THIS( ITypeLibImpl, iface);
3384 ITypeInfoImpl *pTInfo;
3385 TLBFuncDesc *pFInfo;
3386 TLBVarDesc *pVInfo;
3387 int i;
3388 UINT nNameBufLen = SysStringLen(szNameBuf);
3390 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3391 pfName);
3393 *pfName=TRUE;
3394 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3395 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3396 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3397 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3398 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3399 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3400 goto ITypeLib2_fnIsName_exit;
3402 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3403 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3406 *pfName=FALSE;
3408 ITypeLib2_fnIsName_exit:
3409 TRACE("(%p)slow! search for %s: %s found!\n", This,
3410 debugstr_w(szNameBuf), *pfName?"NOT":"");
3412 return S_OK;
3415 /* ITypeLib::FindName
3417 * Finds occurrences of a type description in a type library. This may be used
3418 * to quickly verify that a name exists in a type library.
3421 static HRESULT WINAPI ITypeLib2_fnFindName(
3422 ITypeLib2 *iface,
3423 LPOLESTR szNameBuf,
3424 ULONG lHashVal,
3425 ITypeInfo **ppTInfo,
3426 MEMBERID *rgMemId,
3427 UINT16 *pcFound)
3429 ICOM_THIS( ITypeLibImpl, iface);
3430 ITypeInfoImpl *pTInfo;
3431 TLBFuncDesc *pFInfo;
3432 TLBVarDesc *pVInfo;
3433 int i,j = 0;
3435 UINT nNameBufLen = SysStringLen(szNameBuf);
3437 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3438 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3439 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3440 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3441 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3442 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3443 goto ITypeLib2_fnFindName_exit;
3445 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3446 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3447 continue;
3448 ITypeLib2_fnFindName_exit:
3449 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3450 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3451 j++;
3453 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3454 This, *pcFound, debugstr_w(szNameBuf), j);
3456 *pcFound=j;
3458 return S_OK;
3461 /* ITypeLib::ReleaseTLibAttr
3463 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3466 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3467 ITypeLib2 *iface,
3468 TLIBATTR *pTLibAttr)
3470 ICOM_THIS( ITypeLibImpl, iface);
3471 TRACE("freeing (%p)\n",This);
3472 HeapFree(GetProcessHeap(),0,pTLibAttr);
3476 /* ITypeLib2::GetCustData
3478 * gets the custom data
3480 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3481 ITypeLib2 * iface,
3482 REFGUID guid,
3483 VARIANT *pVarVal)
3485 ICOM_THIS( ITypeLibImpl, iface);
3486 TLBCustData *pCData;
3488 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3490 if( IsEqualIID(guid, &pCData->guid)) break;
3493 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3495 if(pCData)
3497 VariantInit( pVarVal);
3498 VariantCopy( pVarVal, &pCData->data);
3499 return S_OK;
3501 return E_INVALIDARG; /* FIXME: correct? */
3504 /* ITypeLib2::GetLibStatistics
3506 * Returns statistics about a type library that are required for efficient
3507 * sizing of hash tables.
3510 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3511 ITypeLib2 * iface,
3512 ULONG *pcUniqueNames,
3513 ULONG *pcchUniqueNames)
3515 ICOM_THIS( ITypeLibImpl, iface);
3517 FIXME("(%p): stub!\n", This);
3519 if(pcUniqueNames) *pcUniqueNames=1;
3520 if(pcchUniqueNames) *pcchUniqueNames=1;
3521 return S_OK;
3524 /* ITypeLib2::GetDocumentation2
3526 * Retrieves the library's documentation string, the complete Help file name
3527 * and path, the localization context to use, and the context ID for the
3528 * library Help topic in the Help file.
3531 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3532 ITypeLib2 * iface,
3533 INT index,
3534 LCID lcid,
3535 BSTR *pbstrHelpString,
3536 DWORD *pdwHelpStringContext,
3537 BSTR *pbstrHelpStringDll)
3539 ICOM_THIS( ITypeLibImpl, iface);
3540 HRESULT result;
3541 ITypeInfo *pTInfo;
3543 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3545 /* the help string should be obtained from the helpstringdll,
3546 * using the _DLLGetDocumentation function, based on the supplied
3547 * lcid. Nice to do sometime...
3549 if(index<0)
3551 /* documentation for the typelib */
3552 if(pbstrHelpString)
3553 *pbstrHelpString=SysAllocString(This->DocString);
3554 if(pdwHelpStringContext)
3555 *pdwHelpStringContext=This->dwHelpContext;
3556 if(pbstrHelpStringDll)
3557 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3559 result = S_OK;
3561 else
3563 /* for a typeinfo */
3564 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3566 if(SUCCEEDED(result))
3568 ITypeInfo2 * pTInfo2;
3569 result = ITypeInfo_QueryInterface(pTInfo,
3570 &IID_ITypeInfo2,
3571 (LPVOID*) &pTInfo2);
3573 if(SUCCEEDED(result))
3575 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3576 MEMBERID_NIL,
3577 lcid,
3578 pbstrHelpString,
3579 pdwHelpStringContext,
3580 pbstrHelpStringDll);
3582 ITypeInfo2_Release(pTInfo2);
3585 ITypeInfo_Release(pTInfo);
3588 return result;
3591 /* ITypeLib2::GetAllCustData
3593 * Gets all custom data items for the library.
3596 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3597 ITypeLib2 * iface,
3598 CUSTDATA *pCustData)
3600 ICOM_THIS( ITypeLibImpl, iface);
3601 TLBCustData *pCData;
3602 int i;
3603 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3604 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3605 if(pCustData->prgCustData ){
3606 pCustData->cCustData=This->ctCustData;
3607 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3608 pCustData->prgCustData[i].guid=pCData->guid;
3609 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3611 }else{
3612 ERR(" OUT OF MEMORY! \n");
3613 return E_OUTOFMEMORY;
3615 return S_OK;
3618 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3619 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3620 ITypeLib2_fnQueryInterface,
3621 ITypeLib2_fnAddRef,
3622 ITypeLib2_fnRelease,
3623 ITypeLib2_fnGetTypeInfoCount,
3624 ITypeLib2_fnGetTypeInfo,
3625 ITypeLib2_fnGetTypeInfoType,
3626 ITypeLib2_fnGetTypeInfoOfGuid,
3627 ITypeLib2_fnGetLibAttr,
3628 ITypeLib2_fnGetTypeComp,
3629 ITypeLib2_fnGetDocumentation,
3630 ITypeLib2_fnIsName,
3631 ITypeLib2_fnFindName,
3632 ITypeLib2_fnReleaseTLibAttr,
3634 ITypeLib2_fnGetCustData,
3635 ITypeLib2_fnGetLibStatistics,
3636 ITypeLib2_fnGetDocumentation2,
3637 ITypeLib2_fnGetAllCustData
3640 /*================== ITypeInfo(2) Methods ===================================*/
3641 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3643 ITypeInfoImpl * pTypeInfoImpl;
3645 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3646 if (pTypeInfoImpl)
3648 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3649 pTypeInfoImpl->ref=1;
3651 TRACE("(%p)\n", pTypeInfoImpl);
3652 return (ITypeInfo2*) pTypeInfoImpl;
3655 /* ITypeInfo::QueryInterface
3657 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3658 ITypeInfo2 *iface,
3659 REFIID riid,
3660 VOID **ppvObject)
3662 ICOM_THIS( ITypeLibImpl, iface);
3664 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3666 *ppvObject=NULL;
3667 if(IsEqualIID(riid, &IID_IUnknown) ||
3668 IsEqualIID(riid,&IID_ITypeInfo)||
3669 IsEqualIID(riid,&IID_ITypeInfo2))
3670 *ppvObject = This;
3672 if(*ppvObject){
3673 ITypeInfo_AddRef(iface);
3674 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3675 return S_OK;
3677 TRACE("-- Interface: E_NOINTERFACE\n");
3678 return E_NOINTERFACE;
3681 /* ITypeInfo::AddRef
3683 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3685 ICOM_THIS( ITypeInfoImpl, iface);
3687 ++(This->ref);
3689 TRACE("(%p)->ref is %u\n",This, This->ref);
3690 return This->ref;
3693 /* ITypeInfo::Release
3695 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3697 ICOM_THIS( ITypeInfoImpl, iface);
3699 --(This->ref);
3701 TRACE("(%p)->(%u)\n",This, This->ref);
3703 if (!This->ref)
3705 FIXME("destroy child objects\n");
3707 TRACE("destroying ITypeInfo(%p)\n",This);
3708 if (This->Name)
3710 SysFreeString(This->Name);
3711 This->Name = 0;
3714 if (This->DocString)
3716 SysFreeString(This->DocString);
3717 This->DocString = 0;
3720 if (This->next)
3722 ITypeInfo_Release((ITypeInfo*)This->next);
3725 HeapFree(GetProcessHeap(),0,This);
3726 return 0;
3728 return This->ref;
3731 /* ITypeInfo::GetTypeAttr
3733 * Retrieves a TYPEATTR structure that contains the attributes of the type
3734 * description.
3737 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3738 LPTYPEATTR *ppTypeAttr)
3740 ICOM_THIS( ITypeInfoImpl, iface);
3741 TRACE("(%p)\n",This);
3742 /* FIXME: must do a copy here */
3743 *ppTypeAttr=&This->TypeAttr;
3744 return S_OK;
3747 /* ITypeInfo::GetTypeComp
3749 * Retrieves the ITypeComp interface for the type description, which enables a
3750 * client compiler to bind to the type description's members.
3753 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3754 ITypeComp * *ppTComp)
3756 ICOM_THIS( ITypeInfoImpl, iface);
3757 FIXME("(%p) stub!\n", This);
3758 return S_OK;
3761 /* ITypeInfo::GetFuncDesc
3763 * Retrieves the FUNCDESC structure that contains information about a
3764 * specified function.
3767 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3768 LPFUNCDESC *ppFuncDesc)
3770 ICOM_THIS( ITypeInfoImpl, iface);
3771 int i;
3772 TLBFuncDesc * pFDesc;
3773 TRACE("(%p) index %d\n", This, index);
3774 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3776 if(pFDesc){
3777 /* FIXME: must do a copy here */
3778 *ppFuncDesc=&pFDesc->funcdesc;
3779 return S_OK;
3781 return E_INVALIDARG;
3784 /* ITypeInfo::GetVarDesc
3786 * Retrieves a VARDESC structure that describes the specified variable.
3789 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3790 LPVARDESC *ppVarDesc)
3792 ICOM_THIS( ITypeInfoImpl, iface);
3793 int i;
3794 TLBVarDesc * pVDesc;
3795 TRACE("(%p) index %d\n", This, index);
3796 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3798 if(pVDesc){
3799 /* FIXME: must do a copy here */
3800 *ppVarDesc=&pVDesc->vardesc;
3801 return S_OK;
3803 return E_INVALIDARG;
3806 /* ITypeInfo_GetNames
3808 * Retrieves the variable with the specified member ID (or the name of the
3809 * property or method and its parameters) that correspond to the specified
3810 * function ID.
3812 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3813 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3815 ICOM_THIS( ITypeInfoImpl, iface);
3816 TLBFuncDesc * pFDesc;
3817 TLBVarDesc * pVDesc;
3818 int i;
3819 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3820 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3821 if(pFDesc)
3823 /* function found, now return function and parameter names */
3824 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3826 if(!i)
3827 *rgBstrNames=SysAllocString(pFDesc->Name);
3828 else
3829 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3831 *pcNames=i;
3833 else
3835 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3836 if(pVDesc)
3838 *rgBstrNames=SysAllocString(pVDesc->Name);
3839 *pcNames=1;
3841 else
3843 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3845 /* recursive search */
3846 ITypeInfo *pTInfo;
3847 HRESULT result;
3848 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3849 &pTInfo);
3850 if(SUCCEEDED(result))
3852 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3853 ITypeInfo_Release(pTInfo);
3854 return result;
3856 WARN("Could not search inherited interface!\n");
3858 else
3860 WARN("no names found\n");
3862 *pcNames=0;
3863 return TYPE_E_ELEMENTNOTFOUND;
3866 return S_OK;
3870 /* ITypeInfo::GetRefTypeOfImplType
3872 * If a type description describes a COM class, it retrieves the type
3873 * description of the implemented interface types. For an interface,
3874 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3875 * if any exist.
3878 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3879 ITypeInfo2 *iface,
3880 UINT index,
3881 HREFTYPE *pRefType)
3883 ICOM_THIS( ITypeInfoImpl, iface);
3884 int(i);
3885 TLBImplType *pImpl = This->impltypelist;
3887 TRACE("(%p) index %d\n", This, index);
3888 dump_TypeInfo(This);
3890 if(index==(UINT)-1)
3892 /* only valid on dual interfaces;
3893 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3895 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3897 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3898 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3900 *pRefType = -1;
3902 else
3904 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3905 *pRefType = pImpl->hRef;
3908 else
3910 /* get element n from linked list */
3911 for(i=0; pImpl && i<index; i++)
3913 pImpl = pImpl->next;
3916 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3918 *pRefType = pImpl->hRef;
3920 TRACE("-- 0x%08lx\n", pImpl->hRef );
3923 return S_OK;
3927 /* ITypeInfo::GetImplTypeFlags
3929 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3930 * or base interface in a type description.
3932 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
3933 UINT index, INT *pImplTypeFlags)
3935 ICOM_THIS( ITypeInfoImpl, iface);
3936 int i;
3937 TLBImplType *pImpl;
3939 TRACE("(%p) index %d\n", This, index);
3940 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
3941 i++, pImpl=pImpl->next)
3943 if(i==index && pImpl){
3944 *pImplTypeFlags=pImpl->implflags;
3945 return S_OK;
3947 *pImplTypeFlags=0;
3948 return TYPE_E_ELEMENTNOTFOUND;
3951 /* GetIDsOfNames
3952 * Maps between member names and member IDs, and parameter names and
3953 * parameter IDs.
3955 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
3956 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
3958 ICOM_THIS( ITypeInfoImpl, iface);
3959 TLBFuncDesc * pFDesc;
3960 TLBVarDesc * pVDesc;
3961 HRESULT ret=S_OK;
3963 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
3964 cNames);
3965 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
3966 int i, j;
3967 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
3968 if(cNames) *pMemId=pFDesc->funcdesc.memid;
3969 for(i=1; i < cNames; i++){
3970 for(j=0; j<pFDesc->funcdesc.cParams; j++)
3971 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
3972 break;
3973 if( j<pFDesc->funcdesc.cParams)
3974 pMemId[i]=j;
3975 else
3976 ret=DISP_E_UNKNOWNNAME;
3978 return ret;
3981 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
3982 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
3983 if(cNames) *pMemId=pVDesc->vardesc.memid;
3984 return ret;
3987 /* not found, see if this is and interface with an inheritance */
3988 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
3989 This->TypeAttr.cImplTypes ){
3990 /* recursive search */
3991 ITypeInfo *pTInfo;
3992 ret=ITypeInfo_GetRefTypeInfo(iface,
3993 This->impltypelist->hRef, &pTInfo);
3994 if(SUCCEEDED(ret)){
3995 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
3996 ITypeInfo_Release(pTInfo);
3997 return ret;
3999 WARN("Could not search inherited interface!\n");
4000 } else
4001 WARN("no names found\n");
4002 return DISP_E_UNKNOWNNAME;
4005 /* ITypeInfo::Invoke
4007 * Invokes a method, or accesses a property of an object, that implements the
4008 * interface described by the type description.
4010 DWORD
4011 _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
4012 DWORD res;
4014 if (TRACE_ON(ole)) {
4015 int i;
4016 MESSAGE("Calling %p(",func);
4017 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
4018 MESSAGE(")\n");
4021 switch (callconv) {
4022 case CC_STDCALL:
4024 switch (nrargs) {
4025 case 0: {
4026 DWORD (WINAPI *xfunc)() = func;
4027 res = xfunc();
4028 break;
4030 case 1: {
4031 DWORD (WINAPI *xfunc)(DWORD) = func;
4032 res = xfunc(args[0]);
4033 break;
4035 case 2: {
4036 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
4037 res = xfunc(args[0],args[1]);
4038 break;
4040 case 3: {
4041 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
4042 res = xfunc(args[0],args[1],args[2]);
4043 break;
4045 case 4: {
4046 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD) = func;
4047 res = xfunc(args[0],args[1],args[2],args[3]);
4048 break;
4050 case 5: {
4051 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4052 res = xfunc(args[0],args[1],args[2],args[3],args[4]);
4053 break;
4055 case 6: {
4056 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4057 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5]);
4058 break;
4060 case 7: {
4061 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4062 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4063 break;
4065 case 8: {
4066 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4067 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4068 break;
4070 case 9: {
4071 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4072 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4073 break;
4075 default:
4076 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4077 res = -1;
4078 break;
4080 break;
4081 default:
4082 FIXME("unsupported calling convention %d\n",callconv);
4083 res = -1;
4084 break;
4086 TRACE("returns %08lx\n",res);
4087 return res;
4090 static HRESULT WINAPI ITypeInfo_fnInvoke(
4091 ITypeInfo2 *iface,
4092 VOID *pIUnk,
4093 MEMBERID memid,
4094 UINT16 dwFlags,
4095 DISPPARAMS *pDispParams,
4096 VARIANT *pVarResult,
4097 EXCEPINFO *pExcepInfo,
4098 UINT *pArgErr)
4100 ICOM_THIS( ITypeInfoImpl, iface);
4101 TLBFuncDesc * pFDesc;
4102 TLBVarDesc * pVDesc;
4103 int i;
4105 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4106 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4108 dump_DispParms(pDispParams);
4110 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4111 if (pFDesc->funcdesc.memid == memid) {
4112 if (pFDesc->funcdesc.invkind & dwFlags)
4113 break;
4115 if (pFDesc) {
4116 dump_TLBFuncDescOne(pFDesc);
4117 switch (pFDesc->funcdesc.funckind) {
4118 case FUNC_PUREVIRTUAL:
4119 case FUNC_VIRTUAL: {
4120 DWORD res;
4121 DWORD *args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*(pFDesc->funcdesc.cParams+1));
4122 DWORD *args2 = (DWORD*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*(pFDesc->funcdesc.cParams));
4123 args[0] = (DWORD)pIUnk;
4125 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4126 if (i<pDispParams->cArgs) {
4127 TRACE("set %d to disparg type %d vs %d\n",i,
4128 V_VT(&pDispParams->rgvarg[pDispParams->cArgs-i-1]),
4129 pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt
4131 args[i+1] = V_UNION(&pDispParams->rgvarg[pDispParams->cArgs-i-1],lVal);
4132 } else {
4133 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4134 TRACE("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4135 /*FIXME: give pointers for the rest, so propertyget works*/
4136 args[i+1] = (DWORD)&args2[i];
4138 /* If pointer to variant, pass reference to variant
4139 * in result variant array.
4141 if ((tdesc->vt == VT_PTR) &&
4142 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4143 pVarResult
4145 args[i+1] = (DWORD)(pVarResult+(i-pDispParams->cArgs));
4148 if (pFDesc->funcdesc.cParamsOpt)
4149 FIXME("Does not support optional parameters (%d)\n",
4150 pFDesc->funcdesc.cParamsOpt
4153 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4154 pFDesc->funcdesc.callconv,
4155 pFDesc->funcdesc.cParams+1,
4156 args
4158 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4159 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4160 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4161 /* If we are a pointer to a variant, we are done already */
4162 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4163 continue;
4165 VariantInit(&pVarResult[i]);
4166 V_UNION(pVarResult+i,intVal) = args2[i+pDispParams->cArgs];
4168 if (tdesc->vt == VT_PTR)
4169 tdesc = tdesc->u.lptdesc;
4170 V_VT(pVarResult+i) = tdesc->vt;
4172 /* HACK: VB5 likes this.
4173 * I do not know why. There is 1 example in MSDN which uses
4174 * this which appears broken (mixes int vals and
4175 * IDispatch*.).
4177 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4178 V_VT(pVarResult+i) = VT_DISPATCH;
4179 TRACE("storing into variant: [%d]\n", i);
4180 dump_Variant(pVarResult+i);
4183 HeapFree(GetProcessHeap(),0,args2);
4184 HeapFree(GetProcessHeap(),0,args);
4185 return S_OK;
4187 case FUNC_DISPATCH: {
4188 IDispatch *disp;
4189 HRESULT hr;
4191 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4192 if (hr) {
4193 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4194 return hr;
4196 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4197 hr = IDispatch_Invoke(
4198 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4199 pVarResult,pExcepInfo,pArgErr
4201 if (hr)
4202 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4203 IDispatch_Release(disp);
4204 return hr;
4206 default:
4207 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4208 return E_FAIL;
4210 } else {
4211 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4212 if (pVDesc->vardesc.memid == memid) {
4213 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4214 dump_TLBVarDesc(pVDesc);
4215 break;
4219 /* not found, look for it in inherited interfaces */
4220 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4221 /* recursive search */
4222 ITypeInfo *pTInfo;
4223 HRESULT hr;
4224 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4225 if(SUCCEEDED(hr)){
4226 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4227 ITypeInfo_Release(pTInfo);
4228 return hr;
4230 WARN("Could not search inherited interface!\n");
4232 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4233 return DISP_E_MEMBERNOTFOUND;
4236 /* ITypeInfo::GetDocumentation
4238 * Retrieves the documentation string, the complete Help file name and path,
4239 * and the context ID for the Help topic for a specified type description.
4241 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4242 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4243 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4245 ICOM_THIS( ITypeInfoImpl, iface);
4246 TLBFuncDesc * pFDesc;
4247 TLBVarDesc * pVDesc;
4248 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4249 " HelpContext(%p) HelpFile(%p)\n",
4250 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4251 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4252 if(pBstrName)
4253 *pBstrName=SysAllocString(This->Name);
4254 if(pBstrDocString)
4255 *pBstrDocString=SysAllocString(This->DocString);
4256 if(pdwHelpContext)
4257 *pdwHelpContext=This->dwHelpContext;
4258 if(pBstrHelpFile)
4259 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4260 return S_OK;
4261 }else {/* for a member */
4262 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4263 if(pFDesc->funcdesc.memid==memid){
4264 if(pBstrName)
4265 *pBstrName = SysAllocString(pFDesc->Name);
4266 if(pBstrDocString)
4267 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4268 if(pdwHelpContext)
4269 *pdwHelpContext=pFDesc->helpcontext;
4270 return S_OK;
4272 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4273 if(pVDesc->vardesc.memid==memid){
4274 FIXME("Not implemented\n");
4275 return S_OK;
4278 return TYPE_E_ELEMENTNOTFOUND;
4281 /* ITypeInfo::GetDllEntry
4283 * Retrieves a description or specification of an entry point for a function
4284 * in a DLL.
4286 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4287 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4288 WORD *pwOrdinal)
4290 ICOM_THIS( ITypeInfoImpl, iface);
4291 FIXME("(%p) stub!\n", This);
4292 return E_FAIL;
4295 /* ITypeInfo::GetRefTypeInfo
4297 * If a type description references other type descriptions, it retrieves
4298 * the referenced type descriptions.
4300 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4301 ITypeInfo2 *iface,
4302 HREFTYPE hRefType,
4303 ITypeInfo **ppTInfo)
4305 ICOM_THIS( ITypeInfoImpl, iface);
4306 HRESULT result = E_FAIL;
4309 if (hRefType == -1 &&
4310 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4311 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4313 /* when we meet a DUAL dispinterface, we must create the interface
4314 * version of it.
4316 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4319 /* the interface version contains the same information as the dispinterface
4320 * copy the contents of the structs.
4322 *pTypeInfoImpl = *This;
4323 pTypeInfoImpl->ref = 1;
4325 /* change the type to interface */
4326 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4328 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4330 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4332 result = S_OK;
4334 } else {
4335 TLBRefType *pRefType;
4336 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4337 if(pRefType->reference == hRefType)
4338 break;
4340 if(!pRefType)
4341 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4342 if(pRefType && hRefType != -1) {
4343 ITypeLib *pTLib = NULL;
4345 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4346 int Index;
4347 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4348 } else {
4349 if(pRefType->pImpTLInfo->pImpTypeLib) {
4350 TRACE("typeinfo in imported typelib that is already loaded\n");
4351 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4352 ITypeLib2_AddRef((ITypeLib*) pTLib);
4353 result = S_OK;
4354 } else {
4355 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4356 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4357 pRefType->pImpTLInfo->wVersionMajor,
4358 pRefType->pImpTLInfo->wVersionMinor,
4359 pRefType->pImpTLInfo->lcid,
4360 &pTLib);
4362 if(!SUCCEEDED(result)) {
4363 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4364 result=LoadTypeLib(libnam, &pTLib);
4365 SysFreeString(libnam);
4367 if(SUCCEEDED(result)) {
4368 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4369 ITypeLib2_AddRef(pTLib);
4373 if(SUCCEEDED(result)) {
4374 if(pRefType->index == TLB_REF_USE_GUID)
4375 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4376 &pRefType->guid,
4377 ppTInfo);
4378 else
4379 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4380 ppTInfo);
4382 if (pTLib != NULL)
4383 ITypeLib2_Release(pTLib);
4387 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4388 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4389 return result;
4392 /* ITypeInfo::AddressOfMember
4394 * Retrieves the addresses of static functions or variables, such as those
4395 * defined in a DLL.
4397 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4398 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4400 ICOM_THIS( ITypeInfoImpl, iface);
4401 FIXME("(%p) stub!\n", This);
4402 return S_OK;
4405 /* ITypeInfo::CreateInstance
4407 * Creates a new instance of a type that describes a component object class
4408 * (coclass).
4410 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4411 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4413 ICOM_THIS( ITypeInfoImpl, iface);
4414 FIXME("(%p) stub!\n", This);
4415 return S_OK;
4418 /* ITypeInfo::GetMops
4420 * Retrieves marshaling information.
4422 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4423 BSTR *pBstrMops)
4425 ICOM_THIS( ITypeInfoImpl, iface);
4426 FIXME("(%p) stub!\n", This);
4427 return S_OK;
4430 /* ITypeInfo::GetContainingTypeLib
4432 * Retrieves the containing type library and the index of the type description
4433 * within that type library.
4435 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4436 ITypeLib * *ppTLib, UINT *pIndex)
4438 ICOM_THIS( ITypeInfoImpl, iface);
4439 if (!pIndex)
4440 return E_INVALIDARG;
4441 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4442 *pIndex=This->index;
4443 ITypeLib2_AddRef(*ppTLib);
4444 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4445 return S_OK;
4448 /* ITypeInfo::ReleaseTypeAttr
4450 * Releases a TYPEATTR previously returned by GetTypeAttr.
4453 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4454 TYPEATTR* pTypeAttr)
4456 ICOM_THIS( ITypeInfoImpl, iface);
4457 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4458 return S_OK;
4461 /* ITypeInfo::ReleaseFuncDesc
4463 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4465 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4466 ITypeInfo2 *iface,
4467 FUNCDESC *pFuncDesc)
4469 ICOM_THIS( ITypeInfoImpl, iface);
4470 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4471 return S_OK;
4474 /* ITypeInfo::ReleaseVarDesc
4476 * Releases a VARDESC previously returned by GetVarDesc.
4478 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4479 VARDESC *pVarDesc)
4481 ICOM_THIS( ITypeInfoImpl, iface);
4482 TRACE("(%p)->(%p)\n", This, pVarDesc);
4483 return S_OK;
4486 /* ITypeInfo2::GetTypeKind
4488 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4491 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4492 TYPEKIND *pTypeKind)
4494 ICOM_THIS( ITypeInfoImpl, iface);
4495 *pTypeKind=This->TypeAttr.typekind;
4496 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4497 return S_OK;
4500 /* ITypeInfo2::GetTypeFlags
4502 * Returns the type flags without any allocations. This returns a DWORD type
4503 * flag, which expands the type flags without growing the TYPEATTR (type
4504 * attribute).
4507 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4508 UINT *pTypeFlags)
4510 ICOM_THIS( ITypeInfoImpl, iface);
4511 *pTypeFlags=This->TypeAttr.wTypeFlags;
4512 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4513 return S_OK;
4516 /* ITypeInfo2::GetFuncIndexOfMemId
4517 * Binds to a specific member based on a known DISPID, where the member name
4518 * is not known (for example, when binding to a default member).
4521 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4522 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4524 ICOM_THIS( ITypeInfoImpl, iface);
4525 TLBFuncDesc *pFuncInfo;
4526 int i;
4527 HRESULT result;
4528 /* FIXME: should check for invKind??? */
4529 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4530 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4531 if(pFuncInfo){
4532 *pFuncIndex=i;
4533 result= S_OK;
4534 }else{
4535 *pFuncIndex=0;
4536 result=E_INVALIDARG;
4538 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4539 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4540 return result;
4543 /* TypeInfo2::GetVarIndexOfMemId
4545 * Binds to a specific member based on a known DISPID, where the member name
4546 * is not known (for example, when binding to a default member).
4549 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4550 MEMBERID memid, UINT *pVarIndex)
4552 ICOM_THIS( ITypeInfoImpl, iface);
4553 TLBVarDesc *pVarInfo;
4554 int i;
4555 HRESULT result;
4556 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4557 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4559 if(pVarInfo){
4560 *pVarIndex=i;
4561 result= S_OK;
4562 }else{
4563 *pVarIndex=0;
4564 result=E_INVALIDARG;
4566 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4567 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4568 return result;
4571 /* ITypeInfo2::GetCustData
4573 * Gets the custom data
4575 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4576 ITypeInfo2 * iface,
4577 REFGUID guid,
4578 VARIANT *pVarVal)
4580 ICOM_THIS( ITypeInfoImpl, iface);
4581 TLBCustData *pCData;
4583 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4584 if( IsEqualIID(guid, &pCData->guid)) break;
4586 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4588 if(pCData)
4590 VariantInit( pVarVal);
4591 VariantCopy( pVarVal, &pCData->data);
4592 return S_OK;
4594 return E_INVALIDARG; /* FIXME: correct? */
4597 /* ITypeInfo2::GetFuncCustData
4599 * Gets the custom data
4601 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4602 ITypeInfo2 * iface,
4603 UINT index,
4604 REFGUID guid,
4605 VARIANT *pVarVal)
4607 ICOM_THIS( ITypeInfoImpl, iface);
4608 TLBCustData *pCData=NULL;
4609 TLBFuncDesc * pFDesc;
4610 int i;
4611 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4612 pFDesc=pFDesc->next);
4614 if(pFDesc)
4615 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4616 if( IsEqualIID(guid, &pCData->guid)) break;
4618 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4620 if(pCData){
4621 VariantInit( pVarVal);
4622 VariantCopy( pVarVal, &pCData->data);
4623 return S_OK;
4625 return E_INVALIDARG; /* FIXME: correct? */
4628 /* ITypeInfo2::GetParamCustData
4630 * Gets the custom data
4632 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4633 ITypeInfo2 * iface,
4634 UINT indexFunc,
4635 UINT indexParam,
4636 REFGUID guid,
4637 VARIANT *pVarVal)
4639 ICOM_THIS( ITypeInfoImpl, iface);
4640 TLBCustData *pCData=NULL;
4641 TLBFuncDesc * pFDesc;
4642 int i;
4644 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4646 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4647 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4648 pCData = pCData->next)
4649 if( IsEqualIID(guid, &pCData->guid)) break;
4651 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4653 if(pCData)
4655 VariantInit( pVarVal);
4656 VariantCopy( pVarVal, &pCData->data);
4657 return S_OK;
4659 return E_INVALIDARG; /* FIXME: correct? */
4662 /* ITypeInfo2::GetVarCustData
4664 * Gets the custom data
4666 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4667 ITypeInfo2 * iface,
4668 UINT index,
4669 REFGUID guid,
4670 VARIANT *pVarVal)
4672 ICOM_THIS( ITypeInfoImpl, iface);
4673 TLBCustData *pCData=NULL;
4674 TLBVarDesc * pVDesc;
4675 int i;
4677 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4679 if(pVDesc)
4681 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4683 if( IsEqualIID(guid, &pCData->guid)) break;
4687 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4689 if(pCData)
4691 VariantInit( pVarVal);
4692 VariantCopy( pVarVal, &pCData->data);
4693 return S_OK;
4695 return E_INVALIDARG; /* FIXME: correct? */
4698 /* ITypeInfo2::GetImplCustData
4700 * Gets the custom data
4702 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4703 ITypeInfo2 * iface,
4704 UINT index,
4705 REFGUID guid,
4706 VARIANT *pVarVal)
4708 ICOM_THIS( ITypeInfoImpl, iface);
4709 TLBCustData *pCData=NULL;
4710 TLBImplType * pRDesc;
4711 int i;
4713 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4715 if(pRDesc)
4717 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4719 if( IsEqualIID(guid, &pCData->guid)) break;
4723 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4725 if(pCData)
4727 VariantInit( pVarVal);
4728 VariantCopy( pVarVal, &pCData->data);
4729 return S_OK;
4731 return E_INVALIDARG; /* FIXME: correct? */
4734 /* ITypeInfo2::GetDocumentation2
4736 * Retrieves the documentation string, the complete Help file name and path,
4737 * the localization context to use, and the context ID for the library Help
4738 * topic in the Help file.
4741 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4742 ITypeInfo2 * iface,
4743 MEMBERID memid,
4744 LCID lcid,
4745 BSTR *pbstrHelpString,
4746 DWORD *pdwHelpStringContext,
4747 BSTR *pbstrHelpStringDll)
4749 ICOM_THIS( ITypeInfoImpl, iface);
4750 TLBFuncDesc * pFDesc;
4751 TLBVarDesc * pVDesc;
4752 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4753 "HelpStringContext(%p) HelpStringDll(%p)\n",
4754 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4755 pbstrHelpStringDll );
4756 /* the help string should be obtained from the helpstringdll,
4757 * using the _DLLGetDocumentation function, based on the supplied
4758 * lcid. Nice to do sometime...
4760 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4761 if(pbstrHelpString)
4762 *pbstrHelpString=SysAllocString(This->Name);
4763 if(pdwHelpStringContext)
4764 *pdwHelpStringContext=This->dwHelpStringContext;
4765 if(pbstrHelpStringDll)
4766 *pbstrHelpStringDll=
4767 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4768 return S_OK;
4769 }else {/* for a member */
4770 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4771 if(pFDesc->funcdesc.memid==memid){
4772 if(pbstrHelpString)
4773 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4774 if(pdwHelpStringContext)
4775 *pdwHelpStringContext=pFDesc->HelpStringContext;
4776 if(pbstrHelpStringDll)
4777 *pbstrHelpStringDll=
4778 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4779 return S_OK;
4781 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4782 if(pVDesc->vardesc.memid==memid){
4783 if(pbstrHelpString)
4784 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4785 if(pdwHelpStringContext)
4786 *pdwHelpStringContext=pVDesc->HelpStringContext;
4787 if(pbstrHelpStringDll)
4788 *pbstrHelpStringDll=
4789 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4790 return S_OK;
4793 return TYPE_E_ELEMENTNOTFOUND;
4796 /* ITypeInfo2::GetAllCustData
4798 * Gets all custom data items for the Type info.
4801 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4802 ITypeInfo2 * iface,
4803 CUSTDATA *pCustData)
4805 ICOM_THIS( ITypeInfoImpl, iface);
4806 TLBCustData *pCData;
4807 int i;
4809 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4811 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4812 if(pCustData->prgCustData ){
4813 pCustData->cCustData=This->ctCustData;
4814 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4815 pCustData->prgCustData[i].guid=pCData->guid;
4816 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4818 }else{
4819 ERR(" OUT OF MEMORY! \n");
4820 return E_OUTOFMEMORY;
4822 return S_OK;
4825 /* ITypeInfo2::GetAllFuncCustData
4827 * Gets all custom data items for the specified Function
4830 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4831 ITypeInfo2 * iface,
4832 UINT index,
4833 CUSTDATA *pCustData)
4835 ICOM_THIS( ITypeInfoImpl, iface);
4836 TLBCustData *pCData;
4837 TLBFuncDesc * pFDesc;
4838 int i;
4839 TRACE("(%p) index %d\n", This, index);
4840 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4841 pFDesc=pFDesc->next)
4843 if(pFDesc){
4844 pCustData->prgCustData =
4845 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4846 if(pCustData->prgCustData ){
4847 pCustData->cCustData=pFDesc->ctCustData;
4848 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4849 pCData = pCData->next){
4850 pCustData->prgCustData[i].guid=pCData->guid;
4851 VariantCopy(& pCustData->prgCustData[i].varValue,
4852 & pCData->data);
4854 }else{
4855 ERR(" OUT OF MEMORY! \n");
4856 return E_OUTOFMEMORY;
4858 return S_OK;
4860 return TYPE_E_ELEMENTNOTFOUND;
4863 /* ITypeInfo2::GetAllParamCustData
4865 * Gets all custom data items for the Functions
4868 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4869 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4871 ICOM_THIS( ITypeInfoImpl, iface);
4872 TLBCustData *pCData=NULL;
4873 TLBFuncDesc * pFDesc;
4874 int i;
4875 TRACE("(%p) index %d\n", This, indexFunc);
4876 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4877 pFDesc=pFDesc->next)
4879 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4880 pCustData->prgCustData =
4881 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4882 sizeof(CUSTDATAITEM));
4883 if(pCustData->prgCustData ){
4884 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
4885 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
4886 pCData; i++, pCData = pCData->next){
4887 pCustData->prgCustData[i].guid=pCData->guid;
4888 VariantCopy(& pCustData->prgCustData[i].varValue,
4889 & pCData->data);
4891 }else{
4892 ERR(" OUT OF MEMORY! \n");
4893 return E_OUTOFMEMORY;
4895 return S_OK;
4897 return TYPE_E_ELEMENTNOTFOUND;
4900 /* ITypeInfo2::GetAllVarCustData
4902 * Gets all custom data items for the specified Variable
4905 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
4906 UINT index, CUSTDATA *pCustData)
4908 ICOM_THIS( ITypeInfoImpl, iface);
4909 TLBCustData *pCData;
4910 TLBVarDesc * pVDesc;
4911 int i;
4912 TRACE("(%p) index %d\n", This, index);
4913 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
4914 pVDesc=pVDesc->next)
4916 if(pVDesc){
4917 pCustData->prgCustData =
4918 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
4919 if(pCustData->prgCustData ){
4920 pCustData->cCustData=pVDesc->ctCustData;
4921 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
4922 pCData = pCData->next){
4923 pCustData->prgCustData[i].guid=pCData->guid;
4924 VariantCopy(& pCustData->prgCustData[i].varValue,
4925 & pCData->data);
4927 }else{
4928 ERR(" OUT OF MEMORY! \n");
4929 return E_OUTOFMEMORY;
4931 return S_OK;
4933 return TYPE_E_ELEMENTNOTFOUND;
4936 /* ITypeInfo2::GetAllImplCustData
4938 * Gets all custom data items for the specified implementation type
4941 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
4942 ITypeInfo2 * iface,
4943 UINT index,
4944 CUSTDATA *pCustData)
4946 ICOM_THIS( ITypeInfoImpl, iface);
4947 TLBCustData *pCData;
4948 TLBImplType * pRDesc;
4949 int i;
4950 TRACE("(%p) index %d\n", This, index);
4951 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
4952 pRDesc=pRDesc->next)
4954 if(pRDesc){
4955 pCustData->prgCustData =
4956 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
4957 if(pCustData->prgCustData ){
4958 pCustData->cCustData=pRDesc->ctCustData;
4959 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
4960 pCData = pCData->next){
4961 pCustData->prgCustData[i].guid=pCData->guid;
4962 VariantCopy(& pCustData->prgCustData[i].varValue,
4963 & pCData->data);
4965 }else{
4966 ERR(" OUT OF MEMORY! \n");
4967 return E_OUTOFMEMORY;
4969 return S_OK;
4971 return TYPE_E_ELEMENTNOTFOUND;
4974 static ICOM_VTABLE(ITypeInfo2) tinfvt =
4976 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4978 ITypeInfo_fnQueryInterface,
4979 ITypeInfo_fnAddRef,
4980 ITypeInfo_fnRelease,
4982 ITypeInfo_fnGetTypeAttr,
4983 ITypeInfo_fnGetTypeComp,
4984 ITypeInfo_fnGetFuncDesc,
4985 ITypeInfo_fnGetVarDesc,
4986 ITypeInfo_fnGetNames,
4987 ITypeInfo_fnGetRefTypeOfImplType,
4988 ITypeInfo_fnGetImplTypeFlags,
4989 ITypeInfo_fnGetIDsOfNames,
4990 ITypeInfo_fnInvoke,
4991 ITypeInfo_fnGetDocumentation,
4992 ITypeInfo_fnGetDllEntry,
4993 ITypeInfo_fnGetRefTypeInfo,
4994 ITypeInfo_fnAddressOfMember,
4995 ITypeInfo_fnCreateInstance,
4996 ITypeInfo_fnGetMops,
4997 ITypeInfo_fnGetContainingTypeLib,
4998 ITypeInfo_fnReleaseTypeAttr,
4999 ITypeInfo_fnReleaseFuncDesc,
5000 ITypeInfo_fnReleaseVarDesc,
5002 ITypeInfo2_fnGetTypeKind,
5003 ITypeInfo2_fnGetTypeFlags,
5004 ITypeInfo2_fnGetFuncIndexOfMemId,
5005 ITypeInfo2_fnGetVarIndexOfMemId,
5006 ITypeInfo2_fnGetCustData,
5007 ITypeInfo2_fnGetFuncCustData,
5008 ITypeInfo2_fnGetParamCustData,
5009 ITypeInfo2_fnGetVarCustData,
5010 ITypeInfo2_fnGetImplTypeCustData,
5011 ITypeInfo2_fnGetDocumentation2,
5012 ITypeInfo2_fnGetAllCustData,
5013 ITypeInfo2_fnGetAllFuncCustData,
5014 ITypeInfo2_fnGetAllParamCustData,
5015 ITypeInfo2_fnGetAllVarCustData,
5016 ITypeInfo2_fnGetAllImplTypeCustData,