Apply same magic to LibAttr.lcid from MSFT to SLTG.
[wine.git] / dlls / oleaut32 / typelib.c
blob493a48fb36ad4ad1d6dded3d696dcca275078192
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 <stdarg.h>
61 #include <stdio.h>
62 #include <ctype.h>
64 #define NONAMELESSUNION
65 #define NONAMELESSSTRUCT
66 #include "winerror.h"
67 #include "windef.h"
68 #include "winbase.h"
69 #include "winnls.h"
70 #include "winreg.h"
71 #include "winuser.h"
73 #include "wine/unicode.h"
74 #include "objbase.h"
75 #include "heap.h"
76 #include "ole2disp.h"
77 #include "typelib.h"
78 #include "wine/debug.h"
79 #include "parsedt.h"
81 WINE_DEFAULT_DEBUG_CHANNEL(ole);
82 WINE_DECLARE_DEBUG_CHANNEL(typelib);
84 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
85 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
87 /****************************************************************************
88 * FromLExxx
90 * Takes p_iVal (which is in little endian) and returns it
91 * in the host machine's byte order.
93 #ifdef WORDS_BIGENDIAN
94 static WORD FromLEWord(WORD p_iVal)
96 return (((p_iVal & 0x00FF) << 8) |
97 ((p_iVal & 0xFF00) >> 8));
101 static DWORD FromLEDWord(DWORD p_iVal)
103 return (((p_iVal & 0x000000FF) << 24) |
104 ((p_iVal & 0x0000FF00) << 8) |
105 ((p_iVal & 0x00FF0000) >> 8) |
106 ((p_iVal & 0xFF000000) >> 24));
108 #else
109 #define FromLEWord(X) (X)
110 #define FromLEDWord(X) (X)
111 #endif
114 /****************************************************************************
115 * FromLExxx
117 * Fix byte order in any structure if necessary
119 #ifdef WORDS_BIGENDIAN
120 static void FromLEWords(void *p_Val, int p_iSize)
122 WORD *Val = p_Val;
124 p_iSize /= sizeof(WORD);
126 while (p_iSize) {
127 *Val = FromLEWord(*Val);
128 Val++;
129 p_iSize--;
134 static void FromLEDWords(void *p_Val, int p_iSize)
136 DWORD *Val = p_Val;
138 p_iSize /= sizeof(DWORD);
140 while (p_iSize) {
141 *Val = FromLEDWord(*Val);
142 Val++;
143 p_iSize--;
146 #else
147 #define FromLEWords(X,Y) /*nothing*/
148 #define FromLEDWords(X,Y) /*nothing*/
149 #endif
152 /****************************************************************************
153 * QueryPathOfRegTypeLib [OLEAUT32.164]
154 * RETURNS
155 * path of typelib
157 HRESULT WINAPI
158 QueryPathOfRegTypeLib(
159 REFGUID guid, /* [in] referenced guid */
160 WORD wMaj, /* [in] major version */
161 WORD wMin, /* [in] minor version */
162 LCID lcid, /* [in] locale id */
163 LPBSTR path ) /* [out] path of typelib */
165 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
166 string termination character on output strings */
168 HRESULT hr = E_FAIL;
170 LCID myLCID = lcid;
172 char szXGUID[80];
173 char szTypeLibKey[100];
174 char szPath[MAX_PATH];
175 DWORD dwPathLen = sizeof(szPath);
177 if ( !HIWORD(guid) )
179 sprintf(szXGUID,
180 "<guid 0x%08lx>",
181 (DWORD) guid);
183 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
184 return E_FAIL;
187 while (hr != S_OK)
189 sprintf(szTypeLibKey,
190 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
191 guid->Data1, guid->Data2, guid->Data3,
192 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
193 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
194 wMaj,
195 wMin,
196 myLCID);
198 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
200 if (!lcid)
201 break;
202 else if (myLCID == lcid)
204 /* try with sub-langid */
205 myLCID = SUBLANGID(lcid);
207 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
209 /* try with system langid */
210 myLCID = 0;
212 else
214 break;
217 else
219 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
220 BSTR bstrPath = SysAllocStringLen(NULL,len);
222 MultiByteToWideChar(CP_ACP,
223 MB_PRECOMPOSED,
224 szPath,
225 dwPathLen,
226 bstrPath,
227 len);
228 *path = bstrPath;
229 hr = S_OK;
233 if (hr != S_OK)
234 TRACE_(typelib)("%s not found\n", szTypeLibKey);
236 return hr;
239 /******************************************************************************
240 * CreateTypeLib [OLEAUT32.160] creates a typelib
242 * RETURNS
243 * Success: S_OK
244 * Failure: Status
246 HRESULT WINAPI CreateTypeLib(
247 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
249 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
250 return E_FAIL;
252 /******************************************************************************
253 * LoadTypeLib [OLEAUT32.161]
254 * Loads and registers a type library
255 * NOTES
256 * Docs: OLECHAR FAR* szFile
257 * Docs: iTypeLib FAR* FAR* pptLib
259 * RETURNS
260 * Success: S_OK
261 * Failure: Status
263 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
265 HRESULT WINAPI LoadTypeLib(
266 const OLECHAR *szFile,/* [in] Name of file to load from */
267 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
269 TRACE("\n");
270 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
273 /******************************************************************************
274 * LoadTypeLibEx [OLEAUT32.183]
275 * Loads and optionally registers a type library
277 * RETURNS
278 * Success: S_OK
279 * Failure: Status
281 HRESULT WINAPI LoadTypeLibEx(
282 LPCOLESTR szFile, /* [in] Name of file to load from */
283 REGKIND regkind, /* [in] Specify kind of registration */
284 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
286 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
287 WCHAR *pIndexStr;
288 HRESULT res;
289 INT index = 1;
291 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
293 *pptLib = NULL;
294 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
295 NULL)) {
297 /* Look for a trailing '\\' followed by an index */
298 pIndexStr = strrchrW(szFile, '\\');
299 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
300 index = atoiW(pIndexStr);
301 memcpy(szFileCopy, szFile,
302 (pIndexStr - szFile - 1) * sizeof(WCHAR));
303 szFileCopy[pIndexStr - szFile - 1] = '\0';
304 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
305 szPath,NULL))
306 return TYPE_E_CANTLOADLIBRARY;
307 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
308 return TYPE_E_CANTLOADLIBRARY;
309 } else {
310 WCHAR tstpath[260];
311 WCHAR stdole32tlb[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
312 int i;
314 lstrcpyW(tstpath,szFile);
315 CharLowerW(tstpath);
316 for (i=0;i<strlenW(tstpath);i++) {
317 if (tstpath[i] == 's') {
318 if (!strcmpW(tstpath+i,stdole32tlb)) {
319 MESSAGE("\n");
320 MESSAGE("**************************************************************************\n");
321 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
322 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
323 MESSAGE("on the Microsoft Download Pages.\n");
324 MESSAGE("**************************************************************************\n");
325 break;
329 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile));
330 return TYPE_E_CANTLOADLIBRARY;
334 TRACE("File %s index %d\n", debugstr_w(szPath), index);
336 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
338 if (SUCCEEDED(res))
339 switch(regkind)
341 case REGKIND_DEFAULT:
342 /* FIXME: is this correct? */
343 if (!szFile || !szFile[0] ||
344 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
345 break;
346 /* else fall-through */
347 case REGKIND_REGISTER:
348 /* FIXME: Help path? */
349 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
351 IUnknown_Release(*pptLib);
352 *pptLib = 0;
354 break;
355 case REGKIND_NONE:
356 break;
359 TRACE(" returns %08lx\n",res);
360 return res;
363 /******************************************************************************
364 * LoadRegTypeLib [OLEAUT32.162]
366 HRESULT WINAPI LoadRegTypeLib(
367 REFGUID rguid, /* [in] referenced guid */
368 WORD wVerMajor, /* [in] major version */
369 WORD wVerMinor, /* [in] minor version */
370 LCID lcid, /* [in] locale id */
371 ITypeLib **ppTLib) /* [out] path of typelib */
373 BSTR bstr=NULL;
374 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
376 if(SUCCEEDED(res))
378 res= LoadTypeLib(bstr, ppTLib);
379 SysFreeString(bstr);
382 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
384 return res;
388 /******************************************************************************
389 * RegisterTypeLib [OLEAUT32.163]
390 * Adds information about a type library to the System Registry
391 * NOTES
392 * Docs: ITypeLib FAR * ptlib
393 * Docs: OLECHAR FAR* szFullPath
394 * Docs: OLECHAR FAR* szHelpDir
396 * RETURNS
397 * Success: S_OK
398 * Failure: Status
400 HRESULT WINAPI RegisterTypeLib(
401 ITypeLib * ptlib, /* [in] Pointer to the library*/
402 OLECHAR * szFullPath, /* [in] full Path of the library*/
403 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
404 may be NULL*/
406 HRESULT res;
407 TLIBATTR *attr;
408 OLECHAR guid[80];
409 LPSTR guidA;
410 CHAR keyName[120];
411 HKEY key, subKey;
412 UINT types, tidx;
413 TYPEKIND kind;
414 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
416 if (ptlib == NULL || szFullPath == NULL)
417 return E_INVALIDARG;
419 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
420 return E_FAIL;
422 StringFromGUID2(&attr->guid, guid, 80);
423 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
424 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
425 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
426 HeapFree(GetProcessHeap(), 0, guidA);
428 res = S_OK;
429 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
430 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
432 LPOLESTR doc;
434 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
436 if (RegSetValueExW(key, NULL, 0, REG_SZ,
437 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
438 res = E_FAIL;
440 SysFreeString(doc);
442 else
443 res = E_FAIL;
445 /* FIXME: This *seems* to be 0 always, not sure though */
446 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
447 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
449 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
450 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
451 res = E_FAIL;
453 RegCloseKey(subKey);
455 else
456 res = E_FAIL;
458 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
459 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
461 CHAR buf[20];
462 /* FIXME: is %u correct? */
463 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
464 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
465 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
466 res = E_FAIL;
468 RegCloseKey(key);
470 else
471 res = E_FAIL;
473 /* register OLE Automation-compatible interfaces for this typelib */
474 types = ITypeLib_GetTypeInfoCount(ptlib);
475 for (tidx=0; tidx<types; tidx++) {
476 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
477 LPOLESTR name = NULL;
478 ITypeInfo *tinfo = NULL;
479 BOOL stop = FALSE;
480 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
481 switch (kind) {
482 case TKIND_INTERFACE:
483 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
484 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
485 break;
486 case TKIND_DISPATCH:
487 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
488 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
489 break;
490 case TKIND_COCLASS:
491 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
492 /* coclasses should probably not be registered? */
493 break;
494 default:
495 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
496 break;
498 if (tinfo) {
499 TYPEATTR *tattr = NULL;
500 ITypeInfo_GetTypeAttr(tinfo, &tattr);
501 if (tattr) {
502 TRACE_(typelib)("guid=%s, flags=%04x (",
503 debugstr_guid(&tattr->guid),
504 tattr->wTypeFlags);
505 if (TRACE_ON(typelib)) {
506 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
507 XX(FAPPOBJECT);
508 XX(FCANCREATE);
509 XX(FLICENSED);
510 XX(FPREDECLID);
511 XX(FHIDDEN);
512 XX(FCONTROL);
513 XX(FDUAL);
514 XX(FNONEXTENSIBLE);
515 XX(FOLEAUTOMATION);
516 XX(FRESTRICTED);
517 XX(FAGGREGATABLE);
518 XX(FREPLACEABLE);
519 XX(FDISPATCHABLE);
520 XX(FREVERSEBIND);
521 XX(FPROXY);
522 #undef XX
523 MESSAGE("\n");
526 * FIXME: The 1 is just here until we implement rpcrt4
527 * stub/proxy handling. Until then it helps IShield
528 * v6 to work.
530 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
532 /* register interface<->typelib coupling */
533 StringFromGUID2(&tattr->guid, guid, 80);
534 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
535 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
536 HeapFree(GetProcessHeap(), 0, guidA);
538 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
539 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
540 if (name)
541 RegSetValueExW(key, NULL, 0, REG_SZ,
542 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
544 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
545 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
546 RegSetValueExA(subKey, NULL, 0, REG_SZ,
547 PSOA, strlen(PSOA));
548 RegCloseKey(subKey);
550 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
551 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
552 RegSetValueExA(subKey, NULL, 0, REG_SZ,
553 PSOA, strlen(PSOA));
554 RegCloseKey(subKey);
557 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
558 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
559 CHAR ver[32];
560 StringFromGUID2(&attr->guid, guid, 80);
561 snprintf(ver, sizeof(ver), "%x.%x",
562 attr->wMajorVerNum, attr->wMinorVerNum);
563 RegSetValueExW(subKey, NULL, 0, REG_SZ,
564 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
565 RegSetValueExA(subKey, "Version", 0, REG_SZ,
566 ver, lstrlenA(ver));
567 RegCloseKey(subKey);
569 RegCloseKey(key);
572 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
574 ITypeInfo_Release(tinfo);
576 SysFreeString(name);
577 if (stop) break;
581 ITypeLib_ReleaseTLibAttr(ptlib, attr);
583 return res;
587 /******************************************************************************
588 * UnRegisterTypeLib [OLEAUT32.186]
589 * Removes information about a type library from the System Registry
590 * NOTES
592 * RETURNS
593 * Success: S_OK
594 * Failure: Status
596 HRESULT WINAPI UnRegisterTypeLib(
597 REFGUID libid, /* [in] Guid of the library */
598 WORD wVerMajor, /* [in] major version */
599 WORD wVerMinor, /* [in] minor version */
600 LCID lcid, /* [in] locale id */
601 SYSKIND syskind)
603 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
604 return S_OK; /* FIXME: pretend everything is OK */
607 /*======================= ITypeLib implementation =======================*/
609 typedef struct tagTLBCustData
611 GUID guid;
612 VARIANT data;
613 struct tagTLBCustData* next;
614 } TLBCustData;
616 /* data structure for import typelibs */
617 typedef struct tagTLBImpLib
619 int offset; /* offset in the file (MSFT)
620 offset in nametable (SLTG)
621 just used to identify library while reading
622 data from file */
623 GUID guid; /* libid */
624 BSTR name; /* name */
626 LCID lcid; /* lcid of imported typelib */
628 WORD wVersionMajor; /* major version number */
629 WORD wVersionMinor; /* minor version number */
631 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
632 NULL if not yet loaded */
633 struct tagTLBImpLib * next;
634 } TLBImpLib;
636 /* internal ITypeLib data */
637 typedef struct tagITypeLibImpl
639 ICOM_VFIELD(ITypeLib2);
640 ICOM_VTABLE(ITypeComp) * lpVtblTypeComp;
641 UINT ref;
642 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
644 /* strings can be stored in tlb as multibyte strings BUT they are *always*
645 * exported to the application as a UNICODE string.
647 BSTR Name;
648 BSTR DocString;
649 BSTR HelpFile;
650 BSTR HelpStringDll;
651 unsigned long dwHelpContext;
652 int TypeInfoCount; /* nr of typeinfo's in librarry */
653 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
654 int ctCustData; /* number of items in cust data list */
655 TLBCustData * pCustData; /* linked list to cust data */
656 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
657 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
658 libary. Only used while read MSFT
659 typelibs */
661 /* typelibs are cached, keyed by path, so store the linked list info within them */
662 struct tagITypeLibImpl *next, *prev;
663 WCHAR *path;
664 } ITypeLibImpl;
666 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
667 static struct ICOM_VTABLE(ITypeComp) tlbtcvt;
669 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
670 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
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 ICOM_VTABLE(ITypeComp) * lpVtblTypeComp;
752 UINT ref;
753 TYPEATTR TypeAttr ; /* _lots_ of type information. */
754 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
755 int index; /* index in this typelib; */
756 /* type libs seem to store the doc strings in ascii
757 * so why should we do it in unicode?
759 BSTR Name;
760 BSTR DocString;
761 unsigned long dwHelpContext;
762 unsigned long dwHelpStringContext;
764 /* functions */
765 TLBFuncDesc * funclist; /* linked list with function descriptions */
767 /* variables */
768 TLBVarDesc * varlist; /* linked list with variable descriptions */
770 /* Implemented Interfaces */
771 TLBImplType * impltypelist;
773 TLBRefType * reflist;
774 int ctCustData;
775 TLBCustData * pCustData; /* linked list to cust data; */
776 struct tagITypeInfoImpl * next;
777 } ITypeInfoImpl;
779 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
780 static struct ICOM_VTABLE(ITypeComp) tcompvt;
782 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
784 typedef struct tagTLBContext
786 unsigned int oStart; /* start of TLB in file */
787 unsigned int pos; /* current pos */
788 unsigned int length; /* total length */
789 void *mapping; /* memory mapping */
790 MSFT_SegDir * pTblDir;
791 ITypeLibImpl* pLibInfo;
792 } TLBContext;
795 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
798 debug
800 static void dump_VarType(VARTYPE vt,char *szVarType) {
801 /* FIXME : we could have better trace here, depending on the VARTYPE
802 * of the variant
804 if (vt & VT_RESERVED)
805 szVarType += strlen(strcpy(szVarType, "reserved | "));
806 if (vt & VT_BYREF)
807 szVarType += strlen(strcpy(szVarType, "ref to "));
808 if (vt & VT_ARRAY)
809 szVarType += strlen(strcpy(szVarType, "array of "));
810 if (vt & VT_VECTOR)
811 szVarType += strlen(strcpy(szVarType, "vector of "));
812 switch(vt & VT_TYPEMASK) {
813 case VT_EMPTY: sprintf(szVarType, "VT_EMPTY"); break;
814 case VT_NULL: sprintf(szVarType, "VT_NULL"); break;
815 case VT_RECORD: sprintf(szVarType, "VT_RECORD"); break;
816 case VT_I8: sprintf(szVarType, "VT_I8"); break;
817 case VT_UI8: sprintf(szVarType, "VT_UI8"); break;
818 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
819 case VT_I2: sprintf(szVarType, "VT_I2"); break;
820 case VT_I4: sprintf(szVarType, "VT_I4"); break;
821 case VT_R4: sprintf(szVarType, "VT_R4"); break;
822 case VT_R8: sprintf(szVarType, "VT_R8"); break;
823 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
824 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
825 case VT_CY: sprintf(szVarType, "VT_CY"); break;
826 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
827 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
828 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
829 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
830 case VT_I1: sprintf(szVarType, "VT_I1"); break;
831 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
832 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
833 case VT_INT: sprintf(szVarType, "VT_INT"); break;
834 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
835 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
836 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
837 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
838 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
842 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
843 if (pTD->vt & VT_RESERVED)
844 szVarType += strlen(strcpy(szVarType, "reserved | "));
845 if (pTD->vt & VT_BYREF)
846 szVarType += strlen(strcpy(szVarType, "ref to "));
847 if (pTD->vt & VT_ARRAY)
848 szVarType += strlen(strcpy(szVarType, "array of "));
849 if (pTD->vt & VT_VECTOR)
850 szVarType += strlen(strcpy(szVarType, "vector of "));
851 switch(pTD->vt & VT_TYPEMASK) {
852 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
853 case VT_I2: sprintf(szVarType, "VT_I2"); break;
854 case VT_I4: sprintf(szVarType, "VT_I4"); break;
855 case VT_R4: sprintf(szVarType, "VT_R4"); break;
856 case VT_R8: sprintf(szVarType, "VT_R8"); break;
857 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
858 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
859 case VT_CY: sprintf(szVarType, "VT_CY"); break;
860 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
861 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
862 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
863 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
864 case VT_I1: sprintf(szVarType, "VT_I1"); break;
865 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
866 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
867 case VT_INT: sprintf(szVarType, "VT_INT"); break;
868 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
869 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
870 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
871 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
872 pTD->u.hreftype); break;
873 case VT_PTR: sprintf(szVarType, "ptr to ");
874 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
875 break;
876 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
877 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
878 break;
879 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
880 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
881 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
882 break;
884 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
888 void dump_ELEMDESC(ELEMDESC *edesc) {
889 char buf[200];
890 dump_TypeDesc(&edesc->tdesc,buf);
891 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
892 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
893 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
895 void dump_FUNCDESC(FUNCDESC *funcdesc) {
896 int i;
897 MESSAGE("memid is %08lx\n",funcdesc->memid);
898 for (i=0;i<funcdesc->cParams;i++) {
899 MESSAGE("Param %d:\n",i);
900 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
902 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
903 switch (funcdesc->funckind) {
904 case FUNC_VIRTUAL: MESSAGE("virtual");break;
905 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
906 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
907 case FUNC_STATIC: MESSAGE("static");break;
908 case FUNC_DISPATCH: MESSAGE("dispatch");break;
909 default: MESSAGE("unknown");break;
911 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
912 switch (funcdesc->invkind) {
913 case INVOKE_FUNC: MESSAGE("func");break;
914 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
915 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
916 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
918 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
919 switch (funcdesc->callconv) {
920 case CC_CDECL: MESSAGE("cdecl");break;
921 case CC_PASCAL: MESSAGE("pascal");break;
922 case CC_STDCALL: MESSAGE("stdcall");break;
923 case CC_SYSCALL: MESSAGE("syscall");break;
924 default:break;
926 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
927 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
928 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
931 void dump_IDLDESC(IDLDESC *idl) {
932 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
935 static const char * typekind_desc[] =
937 "TKIND_ENUM",
938 "TKIND_RECORD",
939 "TKIND_MODULE",
940 "TKIND_INTERFACE",
941 "TKIND_DISPATCH",
942 "TKIND_COCLASS",
943 "TKIND_ALIAS",
944 "TKIND_UNION",
945 "TKIND_MAX"
948 void dump_TYPEATTR(TYPEATTR *tattr) {
949 char buf[200];
950 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
951 MESSAGE("\tlcid: %ld\n",tattr->lcid);
952 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
953 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
954 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
955 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
956 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
957 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
958 MESSAGE("\tcVars: %d\n", tattr->cVars);
959 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
960 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
961 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
962 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
963 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
964 dump_TypeDesc(&tattr->tdescAlias,buf);
965 MESSAGE("\ttypedesc: %s\n", buf);
966 dump_IDLDESC(&tattr->idldescType);
969 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
971 int i;
972 if (!TRACE_ON(typelib))
973 return;
974 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
975 for (i=0;i<pfd->funcdesc.cParams;i++)
976 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
979 dump_FUNCDESC(&(pfd->funcdesc));
981 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
982 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
984 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
986 while (pfd)
988 dump_TLBFuncDescOne(pfd);
989 pfd = pfd->next;
992 static void dump_TLBVarDesc(TLBVarDesc * pvd)
994 while (pvd)
996 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
997 pvd = pvd->next;
1001 static void dump_TLBImpLib(TLBImpLib *import)
1003 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1004 debugstr_w(import->name));
1005 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1006 import->wVersionMinor, import->lcid, import->offset);
1009 static void dump_TLBRefType(TLBRefType * prt)
1011 while (prt)
1013 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1014 if(prt->index == -1)
1015 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1016 else
1017 TRACE_(typelib)("type no: %d\n", prt->index);
1019 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1020 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1021 TRACE_(typelib)("in lib\n");
1022 dump_TLBImpLib(prt->pImpTLInfo);
1024 prt = prt->next;
1028 static void dump_TLBImplType(TLBImplType * impl)
1030 while (impl) {
1031 TRACE_(typelib)(
1032 "implementing/inheriting interface hRef = %lx implflags %x\n",
1033 impl->hRef, impl->implflags);
1034 impl = impl->next;
1038 void dump_Variant(VARIANT * pvar)
1040 char szVarType[32];
1041 LPVOID ref;
1043 TRACE("(%p)\n", pvar);
1045 if (!pvar) return;
1047 ZeroMemory(szVarType, sizeof(szVarType));
1049 /* FIXME : we could have better trace here, depending on the VARTYPE
1050 * of the variant
1052 dump_VarType(V_VT(pvar),szVarType);
1054 TRACE("VARTYPE: %s\n", szVarType);
1056 if (V_VT(pvar) & VT_BYREF) {
1057 ref = V_UNION(pvar, byref);
1058 TRACE("%p\n", ref);
1060 else ref = &V_UNION(pvar, cVal);
1062 if (V_VT(pvar) & VT_ARRAY) {
1063 /* FIXME */
1064 return;
1066 if (V_VT(pvar) & VT_VECTOR) {
1067 /* FIXME */
1068 return;
1071 switch (V_VT(pvar) & VT_TYPEMASK)
1073 case VT_I2:
1074 TRACE("%d\n", *(short*)ref);
1075 break;
1077 case VT_UI4:
1078 case VT_UINT:
1079 TRACE("%u\n", *(UINT*)ref);
1080 break;
1082 case VT_I4:
1083 case VT_INT:
1084 TRACE("%d\n", *(INT*)ref);
1085 break;
1087 case VT_R4:
1088 TRACE("%3.3e\n", *(float*)ref);
1089 break;
1091 case VT_R8:
1092 TRACE("%3.3e\n", *(double*)ref);
1093 break;
1095 case VT_BOOL:
1096 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1097 break;
1099 case VT_BSTR:
1100 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1101 break;
1103 case VT_UNKNOWN:
1104 case VT_DISPATCH:
1105 TRACE("%p\n", *(LPVOID*)ref);
1106 break;
1108 case VT_VARIANT:
1109 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1110 break;
1112 case VT_DATE:
1114 SYSTEMTIME st;
1116 if(!VariantTimeToSystemTime(*(DATE*)ref, &st)) {
1117 TRACE("invalid date? (?)%ld %f\n", *(long*)ref, *(double *)ref);
1118 } else {
1119 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1120 st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute,
1121 st.wSecond, *(double *)ref);
1123 break;
1126 case VT_CY:
1127 TRACE("%ld (hi), %lu (lo)\n", ((CY *)ref)->s.Hi, ((CY *)ref)->s.Lo);
1128 break;
1131 default:
1132 TRACE("(?)%ld\n", *(long*)ref);
1133 break;
1137 static void dump_DispParms(DISPPARAMS * pdp)
1139 int index = 0;
1141 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1143 while (index < pdp->cArgs)
1145 dump_Variant( &pdp->rgvarg[index] );
1146 ++index;
1150 static void dump_TypeInfo(ITypeInfoImpl * pty)
1152 TRACE("%p ref=%u\n", pty, pty->ref);
1153 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1154 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1155 TRACE("fct:%u var:%u impl:%u\n",
1156 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1157 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1158 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1159 dump_TLBFuncDesc(pty->funclist);
1160 dump_TLBVarDesc(pty->varlist);
1161 dump_TLBImplType(pty->impltypelist);
1164 void dump_VARDESC(VARDESC *v)
1166 MESSAGE("memid %ld\n",v->memid);
1167 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1168 MESSAGE("oInst %ld\n",v->u.oInst);
1169 dump_ELEMDESC(&(v->elemdescVar));
1170 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1171 MESSAGE("varkind %d\n",v->varkind);
1174 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1176 /* VT_LPWSTR is largest type that */
1177 /* may appear in type description*/
1178 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1179 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1180 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1181 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1182 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1183 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1184 {{0},30},{{0},31}
1187 static void TLB_abort()
1189 DebugBreak();
1191 static void * TLB_Alloc(unsigned size)
1193 void * ret;
1194 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1195 /* FIXME */
1196 ERR("cannot allocate memory\n");
1198 return ret;
1201 static void TLB_Free(void * ptr)
1203 HeapFree(GetProcessHeap(), 0, ptr);
1207 /**********************************************************************
1209 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1211 /* read function */
1212 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1214 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1215 pcx->pos, count, pcx->oStart, pcx->length, where);
1217 if (where != DO_NOT_SEEK)
1219 where += pcx->oStart;
1220 if (where > pcx->length)
1222 /* FIXME */
1223 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1224 TLB_abort();
1226 pcx->pos = where;
1228 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1229 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1230 pcx->pos += count;
1231 return count;
1234 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1235 long where )
1237 DWORD ret;
1239 ret = MSFT_Read(buffer, count, pcx, where);
1240 FromLEDWords(buffer, ret);
1242 return ret;
1245 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1246 long where )
1248 DWORD ret;
1250 ret = MSFT_Read(buffer, count, pcx, where);
1251 FromLEWords(buffer, ret);
1253 return ret;
1256 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1258 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1259 memset(pGuid,0, sizeof(GUID));
1260 return;
1262 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1263 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1264 pGuid->Data2 = FromLEWord(pGuid->Data2);
1265 pGuid->Data3 = FromLEWord(pGuid->Data3);
1266 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1269 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1271 char * name;
1272 MSFT_NameIntro niName;
1273 int lengthInChars;
1274 WCHAR* pwstring = NULL;
1275 BSTR bstrName = NULL;
1277 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1278 pcx->pTblDir->pNametab.offset+offset);
1279 niName.namelen &= 0xFF; /* FIXME: correct ? */
1280 name=TLB_Alloc((niName.namelen & 0xff) +1);
1281 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1282 name[niName.namelen & 0xff]='\0';
1284 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1285 name, -1, NULL, 0);
1287 /* no invalid characters in string */
1288 if (lengthInChars)
1290 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1292 /* don't check for invalid character since this has been done previously */
1293 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1295 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1296 lengthInChars = SysStringLen(bstrName);
1297 HeapFree(GetProcessHeap(), 0, pwstring);
1300 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1301 return bstrName;
1304 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1306 char * string;
1307 INT16 length;
1308 int lengthInChars;
1309 BSTR bstr = NULL;
1311 if(offset<0) return NULL;
1312 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1313 if(length <= 0) return 0;
1314 string=TLB_Alloc(length +1);
1315 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1316 string[length]='\0';
1318 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1319 string, -1, NULL, 0);
1321 /* no invalid characters in string */
1322 if (lengthInChars)
1324 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1326 /* don't check for invalid character since this has been done previously */
1327 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1329 bstr = SysAllocStringLen(pwstring, lengthInChars);
1330 lengthInChars = SysStringLen(bstr);
1331 HeapFree(GetProcessHeap(), 0, pwstring);
1334 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1335 return bstr;
1338 * read a value and fill a VARIANT structure
1340 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1342 int size;
1344 TRACE_(typelib)("\n");
1346 if(offset <0) { /* data are packed in here */
1347 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1348 V_UNION(pVar, iVal) = offset & 0xffff;
1349 return;
1351 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1352 pcx->pTblDir->pCustData.offset + offset );
1353 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1354 switch (V_VT(pVar)){
1355 case VT_EMPTY: /* FIXME: is this right? */
1356 case VT_NULL: /* FIXME: is this right? */
1357 case VT_I2 : /* this should not happen */
1358 case VT_I4 :
1359 case VT_R4 :
1360 case VT_ERROR :
1361 case VT_BOOL :
1362 case VT_I1 :
1363 case VT_UI1 :
1364 case VT_UI2 :
1365 case VT_UI4 :
1366 case VT_INT :
1367 case VT_UINT :
1368 case VT_VOID : /* FIXME: is this right? */
1369 case VT_HRESULT :
1370 size=4; break;
1371 case VT_R8 :
1372 case VT_CY :
1373 case VT_DATE :
1374 case VT_I8 :
1375 case VT_UI8 :
1376 case VT_DECIMAL : /* FIXME: is this right? */
1377 case VT_FILETIME :
1378 size=8;break;
1379 /* pointer types with known behaviour */
1380 case VT_BSTR :{
1381 char * ptr;
1382 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1383 if(size <= 0) {
1384 FIXME("BSTR length = %d?\n", size);
1385 } else {
1386 ptr=TLB_Alloc(size);/* allocate temp buffer */
1387 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1388 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1389 /* FIXME: do we need a AtoW conversion here? */
1390 V_UNION(pVar, bstrVal[size])=L'\0';
1391 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1392 TLB_Free(ptr);
1395 size=-4; break;
1396 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1397 case VT_DISPATCH :
1398 case VT_VARIANT :
1399 case VT_UNKNOWN :
1400 case VT_PTR :
1401 case VT_SAFEARRAY :
1402 case VT_CARRAY :
1403 case VT_USERDEFINED :
1404 case VT_LPSTR :
1405 case VT_LPWSTR :
1406 case VT_BLOB :
1407 case VT_STREAM :
1408 case VT_STORAGE :
1409 case VT_STREAMED_OBJECT :
1410 case VT_STORED_OBJECT :
1411 case VT_BLOB_OBJECT :
1412 case VT_CF :
1413 case VT_CLSID :
1414 default:
1415 size=0;
1416 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1417 V_VT(pVar));
1420 if(size>0) /* (big|small) endian correct? */
1421 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1422 return;
1425 * create a linked list with custom data
1427 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1429 MSFT_CDGuid entry;
1430 TLBCustData* pNew;
1431 int count=0;
1433 TRACE_(typelib)("\n");
1435 while(offset >=0){
1436 count++;
1437 pNew=TLB_Alloc(sizeof(TLBCustData));
1438 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1439 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1440 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1441 /* add new custom data at head of the list */
1442 pNew->next=*ppCustData;
1443 *ppCustData=pNew;
1444 offset = entry.next;
1446 return count;
1449 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1450 ITypeInfoImpl *pTI)
1452 if(type <0)
1453 pTd->vt=type & VT_TYPEMASK;
1454 else
1455 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1457 if(pTd->vt == VT_USERDEFINED)
1458 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1460 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1463 static void
1464 MSFT_DoFuncs(TLBContext* pcx,
1465 ITypeInfoImpl* pTI,
1466 int cFuncs,
1467 int cVars,
1468 int offset,
1469 TLBFuncDesc** pptfd)
1472 * member information is stored in a data structure at offset
1473 * indicated by the memoffset field of the typeinfo structure
1474 * There are several distinctive parts.
1475 * the first part starts with a field that holds the total length
1476 * of this (first) part excluding this field. Then follow the records,
1477 * for each member there is one record.
1479 * First entry is always the length of the record (excluding this
1480 * length word).
1481 * Rest of the record depends on the type of the member. If there is
1482 * a field indicating the member type (function variable intereface etc)
1483 * I have not found it yet. At this time we depend on the information
1484 * in the type info and the usual order how things are stored.
1486 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1487 * for each member;
1489 * Third is a equal sized array with file offsets to the name entry
1490 * of each member.
1492 * Forth and last (?) part is an array with offsets to the records in the
1493 * first part of this file segment.
1496 int infolen, nameoffset, reclength, nrattributes, i;
1497 int recoffset = offset + sizeof(INT);
1499 char recbuf[512];
1500 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1502 TRACE_(typelib)("\n");
1504 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1506 for ( i = 0; i < cFuncs ; i++ )
1508 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1510 /* name, eventually add to a hash table */
1511 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1512 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1514 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1516 /* read the function information record */
1517 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1519 reclength &= 0x1ff;
1521 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1523 /* do the attributes */
1524 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1525 / sizeof(int);
1527 if ( nrattributes > 0 )
1529 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1531 if ( nrattributes > 1 )
1533 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1534 pFuncRec->OptAttr[1]) ;
1536 if ( nrattributes > 2 )
1538 if ( pFuncRec->FKCCIC & 0x2000 )
1540 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1542 else
1544 (*pptfd)->Entry = MSFT_ReadString(pcx,
1545 pFuncRec->OptAttr[2]);
1547 if( nrattributes > 5 )
1549 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1551 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1553 MSFT_CustData(pcx,
1554 pFuncRec->OptAttr[6],
1555 &(*pptfd)->pCustData);
1562 /* fill the FuncDesc Structure */
1563 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1564 offset + infolen + ( i + 1) * sizeof(INT));
1566 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1567 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1568 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1569 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1570 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1571 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1572 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1574 MSFT_GetTdesc(pcx,
1575 pFuncRec->DataType,
1576 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1577 pTI);
1579 /* do the parameters/arguments */
1580 if(pFuncRec->nrargs)
1582 int j = 0;
1583 MSFT_ParameterInfo paraminfo;
1585 (*pptfd)->funcdesc.lprgelemdescParam =
1586 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1588 (*pptfd)->pParamDesc =
1589 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1591 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1592 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1594 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1596 TYPEDESC* lpArgTypeDesc = 0;
1598 MSFT_GetTdesc(pcx,
1599 paraminfo.DataType,
1600 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1601 pTI);
1603 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1605 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1607 /* SEEK value = jump to offset,
1608 * from there jump to the end of record,
1609 * go back by (j-1) arguments
1611 MSFT_ReadLEDWords( &paraminfo ,
1612 sizeof(MSFT_ParameterInfo), pcx,
1613 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1614 * sizeof(MSFT_ParameterInfo)));
1615 lpArgTypeDesc =
1616 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1618 while ( lpArgTypeDesc != NULL )
1620 switch ( lpArgTypeDesc->vt )
1622 case VT_PTR:
1623 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1624 break;
1626 case VT_CARRAY:
1627 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1628 break;
1630 case VT_USERDEFINED:
1631 MSFT_DoRefType(pcx, pTI,
1632 lpArgTypeDesc->u.hreftype);
1634 lpArgTypeDesc = NULL;
1635 break;
1637 default:
1638 lpArgTypeDesc = NULL;
1644 /* parameter is the return value! */
1645 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1647 TYPEDESC* lpArgTypeDesc;
1649 (*pptfd)->funcdesc.elemdescFunc =
1650 (*pptfd)->funcdesc.lprgelemdescParam[j];
1652 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1654 while ( lpArgTypeDesc != NULL )
1656 switch ( lpArgTypeDesc->vt )
1658 case VT_PTR:
1659 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1660 break;
1661 case VT_CARRAY:
1662 lpArgTypeDesc =
1663 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1665 break;
1667 case VT_USERDEFINED:
1668 MSFT_DoRefType(pcx,
1669 pTI,
1670 lpArgTypeDesc->u.hreftype);
1672 lpArgTypeDesc = NULL;
1673 break;
1675 default:
1676 lpArgTypeDesc = NULL;
1681 /* second time around */
1682 for(j=0;j<pFuncRec->nrargs;j++)
1684 /* name */
1685 (*pptfd)->pParamDesc[j].Name =
1686 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1688 /* default value */
1689 if ( (PARAMFLAG_FHASDEFAULT &
1690 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1691 ((pFuncRec->FKCCIC) & 0x1000) )
1693 INT* pInt = (INT *)((char *)pFuncRec +
1694 reclength -
1695 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1697 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1699 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1700 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1702 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1703 pInt[j], pcx);
1705 /* custom info */
1706 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1708 MSFT_CustData(pcx,
1709 pFuncRec->OptAttr[7+j],
1710 &(*pptfd)->pParamDesc[j].pCustData);
1715 /* scode is not used: archaic win16 stuff FIXME: right? */
1716 (*pptfd)->funcdesc.cScodes = 0 ;
1717 (*pptfd)->funcdesc.lprgscode = NULL ;
1719 pptfd = & ((*pptfd)->next);
1720 recoffset += reclength;
1724 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1725 int cVars, int offset, TLBVarDesc ** pptvd)
1727 int infolen, nameoffset, reclength;
1728 char recbuf[256];
1729 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1730 int i;
1731 int recoffset;
1733 TRACE_(typelib)("\n");
1735 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1736 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1737 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1738 recoffset += offset+sizeof(INT);
1739 for(i=0;i<cVars;i++){
1740 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1741 /* name, eventually add to a hash table */
1742 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1743 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1744 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1745 /* read the variable information record */
1746 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1747 reclength &=0xff;
1748 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1749 /* Optional data */
1750 if(reclength >(6*sizeof(INT)) )
1751 (*pptvd)->HelpContext=pVarRec->HelpContext;
1752 if(reclength >(7*sizeof(INT)) )
1753 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1754 if(reclength >(8*sizeof(INT)) )
1755 if(reclength >(9*sizeof(INT)) )
1756 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1757 /* fill the VarDesc Structure */
1758 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1759 offset + infolen + ( i + 1) * sizeof(INT));
1760 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1761 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1762 MSFT_GetTdesc(pcx, pVarRec->DataType,
1763 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1764 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1765 if(pVarRec->VarKind == VAR_CONST ){
1766 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1767 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1768 pVarRec->OffsValue, pcx);
1769 } else
1770 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1771 pptvd=&((*pptvd)->next);
1772 recoffset += reclength;
1775 /* fill in data for a hreftype (offset). When the refernced type is contained
1776 * in the typelib, it's just an (file) offset in the type info base dir.
1777 * If comes from import, it's an offset+1 in the ImpInfo table
1778 * */
1779 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1780 int offset)
1782 int j;
1783 TLBRefType **ppRefType = &pTI->reflist;
1785 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1787 while(*ppRefType) {
1788 if((*ppRefType)->reference == offset)
1789 return;
1790 ppRefType = &(*ppRefType)->next;
1793 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1794 sizeof(**ppRefType));
1796 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1797 /* external typelib */
1798 MSFT_ImpInfo impinfo;
1799 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1801 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1803 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1804 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1805 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1806 if(pImpLib->offset==impinfo.oImpFile) break;
1807 pImpLib=pImpLib->next;
1809 if(pImpLib){
1810 (*ppRefType)->reference=offset;
1811 (*ppRefType)->pImpTLInfo = pImpLib;
1812 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1813 (*ppRefType)->index = TLB_REF_USE_GUID;
1814 }else{
1815 ERR("Cannot find a reference\n");
1816 (*ppRefType)->reference=-1;
1817 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1819 }else{
1820 /* in this typelib */
1821 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1822 (*ppRefType)->reference=offset;
1823 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1827 /* process Implemented Interfaces of a com class */
1828 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1829 int offset)
1831 int i;
1832 MSFT_RefRecord refrec;
1833 TLBImplType **ppImpl = &pTI->impltypelist;
1835 TRACE_(typelib)("\n");
1837 for(i=0;i<count;i++){
1838 if(offset<0) break; /* paranoia */
1839 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1840 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1841 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1842 (*ppImpl)->hRef = refrec.reftype;
1843 (*ppImpl)->implflags=refrec.flags;
1844 (*ppImpl)->ctCustData=
1845 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1846 offset=refrec.onext;
1847 ppImpl=&((*ppImpl)->next);
1851 * process a typeinfo record
1853 ITypeInfoImpl * MSFT_DoTypeInfo(
1854 TLBContext *pcx,
1855 int count,
1856 ITypeLibImpl * pLibInfo)
1858 MSFT_TypeInfoBase tiBase;
1859 ITypeInfoImpl *ptiRet;
1861 TRACE_(typelib)("count=%u\n", count);
1863 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1864 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
1865 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1866 /* this is where we are coming from */
1867 ptiRet->pTypeLib = pLibInfo;
1868 ptiRet->index=count;
1869 /* fill in the typeattr fields */
1870 WARN("Assign constructor/destructor memid\n");
1872 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1873 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1874 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1875 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1876 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1877 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1878 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1879 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1880 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1881 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1882 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1883 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1884 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1885 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1886 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1887 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1888 MSFT_GetTdesc(pcx, tiBase.datatype1,
1889 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1891 /* FIXME: */
1892 /* IDLDESC idldescType; *//* never saw this one != zero */
1894 /* name, eventually add to a hash table */
1895 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1896 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1897 /* help info */
1898 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1899 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1900 ptiRet->dwHelpContext=tiBase.helpcontext;
1901 /* note: InfoType's Help file and HelpStringDll come from the containing
1902 * library. Further HelpString and Docstring appear to be the same thing :(
1904 /* functions */
1905 if(ptiRet->TypeAttr.cFuncs >0 )
1906 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1907 ptiRet->TypeAttr.cVars,
1908 tiBase.memoffset, & ptiRet->funclist);
1909 /* variables */
1910 if(ptiRet->TypeAttr.cVars >0 )
1911 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1912 ptiRet->TypeAttr.cVars,
1913 tiBase.memoffset, & ptiRet->varlist);
1914 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1915 switch(ptiRet->TypeAttr.typekind)
1917 case TKIND_COCLASS:
1918 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1919 tiBase.datatype1);
1920 break;
1921 case TKIND_DISPATCH:
1922 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1924 if (tiBase.datatype1 != -1)
1926 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1927 ptiRet->impltypelist->hRef = tiBase.datatype1;
1929 else
1930 { /* FIXME: This is a really bad hack to add IDispatch */
1931 const char* szStdOle = "stdole2.tlb\0";
1932 int nStdOleLen = strlen(szStdOle);
1933 TLBRefType **ppRef = &ptiRet->reflist;
1935 while(*ppRef) {
1936 if((*ppRef)->reference == -1)
1937 break;
1938 ppRef = &(*ppRef)->next;
1940 if(!*ppRef) {
1941 *ppRef = TLB_Alloc(sizeof(**ppRef));
1942 (*ppRef)->guid = IID_IDispatch;
1943 (*ppRef)->reference = -1;
1944 (*ppRef)->index = TLB_REF_USE_GUID;
1945 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1946 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1947 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1948 nStdOleLen + 1);
1950 MultiByteToWideChar(CP_ACP,
1951 MB_PRECOMPOSED,
1952 szStdOle,
1954 (*ppRef)->pImpTLInfo->name,
1955 SysStringLen((*ppRef)->pImpTLInfo->name));
1957 (*ppRef)->pImpTLInfo->lcid = 0;
1958 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1959 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1962 break;
1963 default:
1964 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1965 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1966 ptiRet->impltypelist->hRef = tiBase.datatype1;
1967 break;
1970 ptiRet->ctCustData=
1971 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1973 TRACE_(typelib)("%s guid: %s kind:%s\n",
1974 debugstr_w(ptiRet->Name),
1975 debugstr_guid(&ptiRet->TypeAttr.guid),
1976 typekind_desc[ptiRet->TypeAttr.typekind]);
1978 return ptiRet;
1981 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
1982 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
1983 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
1984 * tradeoff here.
1986 static ITypeLibImpl *tlb_cache_first;
1987 static CRITICAL_SECTION cache_section;
1988 static CRITICAL_SECTION_DEBUG cache_section_debug =
1990 0, 0, &cache_section,
1991 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
1992 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
1994 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
1997 /****************************************************************************
1998 * TLB_ReadTypeLib
2000 * find the type of the typelib file and map the typelib resource into
2001 * the memory
2003 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2004 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2005 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2007 ITypeLibImpl *entry;
2008 int ret = TYPE_E_CANTLOADLIBRARY;
2009 DWORD dwSignature = 0;
2010 HANDLE hFile;
2012 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2014 *ppTypeLib = NULL;
2016 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2017 EnterCriticalSection(&cache_section);
2018 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2020 if (!strcmpiW(entry->path, pszFileName))
2022 TRACE("cache hit\n");
2023 *ppTypeLib = (ITypeLib2*)entry;
2024 ITypeLib_AddRef(*ppTypeLib);
2025 LeaveCriticalSection(&cache_section);
2026 return S_OK;
2029 LeaveCriticalSection(&cache_section);
2031 /* check the signature of the file */
2032 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2033 if (INVALID_HANDLE_VALUE != hFile)
2035 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2036 if (hMapping)
2038 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2039 if(pBase)
2041 /* retrieve file size */
2042 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2044 /* first try to load as *.tlb */
2045 dwSignature = FromLEDWord(*((DWORD*) pBase));
2046 if ( dwSignature == MSFT_SIGNATURE)
2048 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2050 else if ( dwSignature == SLTG_SIGNATURE)
2052 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2054 UnmapViewOfFile(pBase);
2056 CloseHandle(hMapping);
2058 CloseHandle(hFile);
2061 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2063 /* find the typelibrary resource*/
2064 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2065 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2066 if (hinstDLL)
2068 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2069 "TYPELIB");
2070 if (hrsrc)
2072 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2073 if (hGlobal)
2075 LPVOID pBase = LockResource(hGlobal);
2076 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2078 if (pBase)
2080 /* try to load as incore resource */
2081 dwSignature = FromLEDWord(*((DWORD*) pBase));
2082 if ( dwSignature == MSFT_SIGNATURE)
2084 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2086 else if ( dwSignature == SLTG_SIGNATURE)
2088 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2090 else
2092 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2095 FreeResource( hGlobal );
2098 FreeLibrary(hinstDLL);
2102 if(*ppTypeLib) {
2103 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2105 TRACE("adding to cache\n");
2106 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2107 lstrcpyW(impl->path, pszFileName);
2108 /* We should really canonicalise the path here. */
2110 /* FIXME: check if it has added already in the meantime */
2111 EnterCriticalSection(&cache_section);
2112 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2113 impl->prev = NULL;
2114 tlb_cache_first = impl;
2115 LeaveCriticalSection(&cache_section);
2116 ret = S_OK;
2117 } else
2118 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2120 return ret;
2123 /*================== ITypeLib(2) Methods ===================================*/
2125 /****************************************************************************
2126 * ITypeLib2_Constructor_MSFT
2128 * loading an MSFT typelib from an in-memory image
2130 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2132 TLBContext cx;
2133 long lPSegDir;
2134 MSFT_Header tlbHeader;
2135 MSFT_SegDir tlbSegDir;
2136 ITypeLibImpl * pTypeLibImpl;
2138 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2140 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2141 if (!pTypeLibImpl) return NULL;
2143 pTypeLibImpl->lpVtbl = &tlbvt;
2144 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2145 pTypeLibImpl->ref = 1;
2147 /* get pointer to beginning of typelib data */
2148 cx.pos = 0;
2149 cx.oStart=0;
2150 cx.mapping = pLib;
2151 cx.pLibInfo = pTypeLibImpl;
2152 cx.length = dwTLBLength;
2154 /* read header */
2155 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2156 TRACE("header:\n");
2157 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2158 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2159 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2160 return NULL;
2162 /* there is a small amount of information here until the next important
2163 * part:
2164 * the segment directory . Try to calculate the amount of data */
2165 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2167 /* now read the segment directory */
2168 TRACE("read segment directory (at %ld)\n",lPSegDir);
2169 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2170 cx.pTblDir = &tlbSegDir;
2172 /* just check two entries */
2173 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2175 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2176 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2177 return NULL;
2180 /* now fill our internal data */
2181 /* TLIBATTR fields */
2182 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2184 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2185 /* Windows seems to have zero here, is this correct? */
2186 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2187 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2188 else
2189 pTypeLibImpl->LibAttr.lcid = 0;
2191 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2192 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2193 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2194 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2196 /* name, eventually add to a hash table */
2197 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2199 /* help info */
2200 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2201 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2203 if( tlbHeader.varflags & HELPDLLFLAG)
2205 int offset;
2206 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2207 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2210 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2212 /* custom data */
2213 if(tlbHeader.CustomDataOffset >= 0)
2215 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2218 /* fill in typedescriptions */
2219 if(tlbSegDir.pTypdescTab.length > 0)
2221 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2222 INT16 td[4];
2223 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2224 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2225 for(i=0; i<cTD; )
2227 /* FIXME: add several sanity checks here */
2228 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2229 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2231 /* FIXME: check safearray */
2232 if(td[3] < 0)
2233 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2234 else
2235 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2237 else if(td[0] == VT_CARRAY)
2239 /* array descr table here */
2240 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2242 else if(td[0] == VT_USERDEFINED)
2244 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2246 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2249 /* second time around to fill the array subscript info */
2250 for(i=0;i<cTD;i++)
2252 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2253 if(tlbSegDir.pArrayDescriptions.offset>0)
2255 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2256 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2258 if(td[1]<0)
2259 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2260 else
2261 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2263 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2265 for(j = 0; j<td[2]; j++)
2267 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2268 sizeof(INT), &cx, DO_NOT_SEEK);
2269 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2270 sizeof(INT), &cx, DO_NOT_SEEK);
2273 else
2275 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2276 ERR("didn't find array description data\n");
2281 /* imported type libs */
2282 if(tlbSegDir.pImpFiles.offset>0)
2284 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2285 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2286 UINT16 size;
2288 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2290 char *name;
2291 DWORD len;
2293 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2294 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2295 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2297 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2298 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2299 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2300 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2302 size >>= 2;
2303 name = TLB_Alloc(size+1);
2304 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2305 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2306 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2307 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2308 TLB_Free(name);
2310 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2311 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2313 ppImpLib = &(*ppImpLib)->next;
2317 /* type info's */
2318 if(tlbHeader.nrtypeinfos >= 0 )
2320 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2321 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2322 int i;
2324 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2326 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2328 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2329 ppTI = &((*ppTI)->next);
2330 (pTypeLibImpl->TypeInfoCount)++;
2334 TRACE("(%p)\n", pTypeLibImpl);
2335 return (ITypeLib2*) pTypeLibImpl;
2339 static BSTR TLB_MultiByteToBSTR(char *ptr)
2341 DWORD len;
2342 WCHAR *nameW;
2343 BSTR ret;
2345 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2346 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2347 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2348 ret = SysAllocString(nameW);
2349 HeapFree(GetProcessHeap(), 0, nameW);
2350 return ret;
2353 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2355 char b[3];
2356 int i;
2357 short s;
2359 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2360 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2361 return FALSE;
2364 guid->Data4[0] = s >> 8;
2365 guid->Data4[1] = s & 0xff;
2367 b[2] = '\0';
2368 for(i = 0; i < 6; i++) {
2369 memcpy(b, str + 24 + 2 * i, 2);
2370 guid->Data4[i + 2] = strtol(b, NULL, 16);
2372 return TRUE;
2375 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2377 WORD bytelen;
2378 DWORD len;
2379 WCHAR *nameW;
2381 *pBstr = NULL;
2382 bytelen = *(WORD*)ptr;
2383 if(bytelen == 0xffff) return 2;
2384 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2385 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2386 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2387 *pBstr = SysAllocStringLen(nameW, len);
2388 HeapFree(GetProcessHeap(), 0, nameW);
2389 return bytelen + 2;
2392 static WORD SLTG_ReadStringA(char *ptr, char **str)
2394 WORD bytelen;
2396 *str = NULL;
2397 bytelen = *(WORD*)ptr;
2398 if(bytelen == 0xffff) return 2;
2399 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2400 memcpy(*str, ptr + 2, bytelen);
2401 (*str)[bytelen] = '\0';
2402 return bytelen + 2;
2405 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2407 char *ptr = pLibBlk;
2408 WORD w;
2410 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2411 FIXME("libblk magic = %04x\n", w);
2412 return 0;
2415 ptr += 6;
2416 if((w = *(WORD*)ptr) != 0xffff) {
2417 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2418 ptr += w;
2420 ptr += 2;
2422 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2424 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2426 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2427 ptr += 4;
2429 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2430 ptr += 2;
2432 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2433 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2434 else
2435 pTypeLibImpl->LibAttr.lcid = 0;
2436 ptr += 2;
2438 ptr += 4; /* skip res12 */
2440 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2441 ptr += 2;
2443 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2444 ptr += 2;
2446 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2447 ptr += 2;
2449 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2450 ptr += sizeof(GUID);
2452 return ptr - (char*)pLibBlk;
2455 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2457 BOOL done = FALSE;
2458 TYPEDESC *pTD = &pElem->tdesc;
2460 /* Handle [in/out] first */
2461 if((*pType & 0xc000) == 0xc000)
2462 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2463 else if(*pType & 0x8000)
2464 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2465 else if(*pType & 0x4000)
2466 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2467 else
2468 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2470 if(*pType & 0x2000)
2471 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2473 if(*pType & 0x80)
2474 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2476 while(!done) {
2477 if((*pType & 0xe00) == 0xe00) {
2478 pTD->vt = VT_PTR;
2479 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2480 sizeof(TYPEDESC));
2481 pTD = pTD->u.lptdesc;
2483 switch(*pType & 0x7f) {
2484 case VT_PTR:
2485 pTD->vt = VT_PTR;
2486 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2487 sizeof(TYPEDESC));
2488 pTD = pTD->u.lptdesc;
2489 break;
2491 case VT_USERDEFINED:
2492 pTD->vt = VT_USERDEFINED;
2493 pTD->u.hreftype = *(++pType) / 4;
2494 done = TRUE;
2495 break;
2497 case VT_CARRAY:
2499 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2500 array */
2502 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2504 pTD->vt = VT_CARRAY;
2505 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2506 sizeof(ARRAYDESC) +
2507 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2508 pTD->u.lpadesc->cDims = pSA->cDims;
2509 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2510 pSA->cDims * sizeof(SAFEARRAYBOUND));
2512 pTD = &pTD->u.lpadesc->tdescElem;
2513 break;
2516 case VT_SAFEARRAY:
2518 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2519 useful? */
2521 pType++;
2522 pTD->vt = VT_SAFEARRAY;
2523 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2524 sizeof(TYPEDESC));
2525 pTD = pTD->u.lptdesc;
2526 break;
2528 default:
2529 pTD->vt = *pType & 0x7f;
2530 done = TRUE;
2531 break;
2533 pType++;
2535 return pType;
2539 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2540 char *pNameTable)
2542 int ref;
2543 char *name;
2544 TLBRefType **ppRefType;
2546 if(pRef->magic != SLTG_REF_MAGIC) {
2547 FIXME("Ref magic = %x\n", pRef->magic);
2548 return;
2550 name = ( (char*)(&pRef->names) + pRef->number);
2552 ppRefType = &pTI->reflist;
2553 for(ref = 0; ref < pRef->number >> 3; ref++) {
2554 char *refname;
2555 unsigned int lib_offs, type_num;
2557 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2558 sizeof(**ppRefType));
2560 name += SLTG_ReadStringA(name, &refname);
2561 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2562 FIXME("Can't sscanf ref\n");
2563 if(lib_offs != 0xffff) {
2564 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2566 while(*import) {
2567 if((*import)->offset == lib_offs)
2568 break;
2569 import = &(*import)->next;
2571 if(!*import) {
2572 char fname[MAX_PATH+1];
2573 int len;
2575 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2576 sizeof(**import));
2577 (*import)->offset = lib_offs;
2578 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2579 &(*import)->guid);
2580 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2581 &(*import)->wVersionMajor,
2582 &(*import)->wVersionMinor,
2583 &(*import)->lcid, fname) != 4) {
2584 FIXME("can't sscanf ref %s\n",
2585 pNameTable + lib_offs + 40);
2587 len = strlen(fname);
2588 if(fname[len-1] != '#')
2589 FIXME("fname = %s\n", fname);
2590 fname[len-1] = '\0';
2591 (*import)->name = TLB_MultiByteToBSTR(fname);
2593 (*ppRefType)->pImpTLInfo = *import;
2594 } else { /* internal ref */
2595 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2597 (*ppRefType)->reference = ref;
2598 (*ppRefType)->index = type_num;
2600 HeapFree(GetProcessHeap(), 0, refname);
2601 ppRefType = &(*ppRefType)->next;
2603 if((BYTE)*name != SLTG_REF_MAGIC)
2604 FIXME("End of ref block magic = %x\n", *name);
2605 dump_TLBRefType(pTI->reflist);
2608 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2609 BOOL OneOnly)
2611 SLTG_ImplInfo *info;
2612 TLBImplType **ppImplType = &pTI->impltypelist;
2613 /* I don't really get this structure, usually it's 0x16 bytes
2614 long, but iuser.tlb contains some that are 0x18 bytes long.
2615 That's ok because we can use the next ptr to jump to the next
2616 one. But how do we know the length of the last one? The WORD
2617 at offs 0x8 might be the clue. For now I'm just assuming that
2618 the last one is the regular 0x16 bytes. */
2620 info = (SLTG_ImplInfo*)pBlk;
2621 while(1) {
2622 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2623 sizeof(**ppImplType));
2624 (*ppImplType)->hRef = info->ref;
2625 (*ppImplType)->implflags = info->impltypeflags;
2626 pTI->TypeAttr.cImplTypes++;
2627 ppImplType = &(*ppImplType)->next;
2629 if(info->next == 0xffff)
2630 break;
2631 if(OneOnly)
2632 FIXME("Interface inheriting more than one interface\n");
2633 info = (SLTG_ImplInfo*)(pBlk + info->next);
2635 info++; /* see comment at top of function */
2636 return (char*)info;
2639 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2640 char *pNameTable)
2642 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2643 SLTG_MemberHeader *pMemHeader;
2644 char *pFirstItem, *pNextItem;
2646 if(pTIHeader->href_table != 0xffffffff) {
2647 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2648 pNameTable);
2652 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2654 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2656 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2657 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2660 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2664 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2665 char *pNameTable)
2667 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2668 SLTG_MemberHeader *pMemHeader;
2669 SLTG_Function *pFunc;
2670 char *pFirstItem, *pNextItem;
2671 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2672 int num = 0;
2674 if(pTIHeader->href_table != 0xffffffff) {
2675 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2676 pNameTable);
2679 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2681 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2683 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2684 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2687 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2688 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2690 int param;
2691 WORD *pType, *pArg;
2693 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2694 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2695 FIXME("func magic = %02x\n", pFunc->magic);
2696 return NULL;
2698 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2699 sizeof(**ppFuncDesc));
2700 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2702 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2703 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2704 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2705 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2706 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2707 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2709 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2710 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2712 if(pFunc->retnextopt & 0x80)
2713 pType = &pFunc->rettype;
2714 else
2715 pType = (WORD*)(pFirstItem + pFunc->rettype);
2718 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2720 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2721 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2722 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2723 (*ppFuncDesc)->pParamDesc =
2724 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2725 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2727 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2729 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2730 char *paramName = pNameTable + *pArg;
2731 BOOL HaveOffs;
2732 /* If arg type follows then paramName points to the 2nd
2733 letter of the name, else the next WORD is an offset to
2734 the arg type and paramName points to the first letter.
2735 So let's take one char off paramName and see if we're
2736 pointing at an alpha-numeric char. However if *pArg is
2737 0xffff or 0xfffe then the param has no name, the former
2738 meaning that the next WORD is the type, the latter
2739 meaning the the next WORD is an offset to the type. */
2741 HaveOffs = FALSE;
2742 if(*pArg == 0xffff)
2743 paramName = NULL;
2744 else if(*pArg == 0xfffe) {
2745 paramName = NULL;
2746 HaveOffs = TRUE;
2748 else if(!isalnum(*(paramName-1)))
2749 HaveOffs = TRUE;
2751 pArg++;
2753 if(HaveOffs) { /* the next word is an offset to type */
2754 pType = (WORD*)(pFirstItem + *pArg);
2755 SLTG_DoType(pType, pFirstItem,
2756 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2757 pArg++;
2758 } else {
2759 if(paramName)
2760 paramName--;
2761 pArg = SLTG_DoType(pArg, pFirstItem,
2762 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2765 /* Are we an optional param ? */
2766 if((*ppFuncDesc)->funcdesc.cParams - param <=
2767 (*ppFuncDesc)->funcdesc.cParamsOpt)
2768 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2770 if(paramName) {
2771 (*ppFuncDesc)->pParamDesc[param].Name =
2772 TLB_MultiByteToBSTR(paramName);
2776 ppFuncDesc = &((*ppFuncDesc)->next);
2777 if(pFunc->next == 0xffff) break;
2779 pTI->TypeAttr.cFuncs = num;
2780 dump_TLBFuncDesc(pTI->funclist);
2781 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2784 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2785 char *pNameTable)
2787 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2788 SLTG_MemberHeader *pMemHeader;
2789 SLTG_RecordItem *pItem;
2790 char *pFirstItem;
2791 TLBVarDesc **ppVarDesc = &pTI->varlist;
2792 int num = 0;
2793 WORD *pType;
2794 char buf[300];
2796 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2798 pFirstItem = (char*)(pMemHeader + 1);
2799 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2800 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2801 if(pItem->magic != SLTG_RECORD_MAGIC) {
2802 FIXME("record magic = %02x\n", pItem->magic);
2803 return NULL;
2805 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2806 sizeof(**ppVarDesc));
2807 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2808 (*ppVarDesc)->vardesc.memid = pItem->memid;
2809 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2810 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2812 if(pItem->typepos == 0x02)
2813 pType = &pItem->type;
2814 else if(pItem->typepos == 0x00)
2815 pType = (WORD*)(pFirstItem + pItem->type);
2816 else {
2817 FIXME("typepos = %02x\n", pItem->typepos);
2818 break;
2821 SLTG_DoType(pType, pFirstItem,
2822 &(*ppVarDesc)->vardesc.elemdescVar);
2824 /* FIXME("helpcontext, helpstring\n"); */
2826 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2828 ppVarDesc = &((*ppVarDesc)->next);
2829 if(pItem->next == 0xffff) break;
2831 pTI->TypeAttr.cVars = num;
2832 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2835 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2836 char *pNameTable)
2838 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2839 SLTG_MemberHeader *pMemHeader;
2840 SLTG_AliasItem *pItem;
2841 int i, mustbelast;
2843 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2844 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2846 mustbelast = 0;
2847 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2848 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2849 if (pItem->vt == 0xffff) {
2850 if (i<(pMemHeader->cbExtra/4-1))
2851 FIXME("Endmarker too early in process alias data!\n");
2852 break;
2854 if (mustbelast) {
2855 FIXME("Chain extends over last entry?\n");
2856 break;
2858 if (pItem->vt == VT_USERDEFINED) {
2859 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2860 /* guessing here ... */
2861 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2862 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2863 mustbelast = 1;
2864 } else {
2865 FIXME("alias %d: 0x%x\n",i,pItem->vt);
2866 FIXME("alias %d: 0x%x\n",i,pItem->res02);
2868 pItem++;
2870 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2873 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
2874 char *pNameTable)
2876 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2877 SLTG_MemberHeader *pMemHeader;
2878 SLTG_AliasItem *pItem;
2880 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2881 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2882 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
2883 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
2884 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2887 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2888 char *pNameTable)
2890 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2891 SLTG_MemberHeader *pMemHeader;
2892 SLTG_EnumItem *pItem;
2893 char *pFirstItem;
2894 TLBVarDesc **ppVarDesc = &pTI->varlist;
2895 int num = 0;
2897 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2899 pFirstItem = (char*)(pMemHeader + 1);
2900 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2901 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2902 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2903 FIXME("enumitem magic = %04x\n", pItem->magic);
2904 return NULL;
2906 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2907 sizeof(**ppVarDesc));
2908 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2909 (*ppVarDesc)->vardesc.memid = pItem->memid;
2910 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2911 sizeof(VARIANT));
2912 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2913 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2914 *(INT*)(pItem->value + pFirstItem);
2915 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2916 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2917 /* FIXME("helpcontext, helpstring\n"); */
2919 ppVarDesc = &((*ppVarDesc)->next);
2920 if(pItem->next == 0xffff) break;
2922 pTI->TypeAttr.cVars = num;
2923 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2926 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2927 managable copy of it into this */
2928 typedef struct {
2929 WORD small_no;
2930 char *index_name;
2931 char *other_name;
2932 WORD res1a;
2933 WORD name_offs;
2934 WORD more_bytes;
2935 char *extra;
2936 WORD res20;
2937 DWORD helpcontext;
2938 WORD res26;
2939 GUID uuid;
2940 } SLTG_InternalOtherTypeInfo;
2942 /****************************************************************************
2943 * ITypeLib2_Constructor_SLTG
2945 * loading a SLTG typelib from an in-memory image
2947 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2949 ITypeLibImpl *pTypeLibImpl;
2950 SLTG_Header *pHeader;
2951 SLTG_BlkEntry *pBlkEntry;
2952 SLTG_Magic *pMagic;
2953 SLTG_Index *pIndex;
2954 SLTG_Pad9 *pPad9;
2955 LPVOID pBlk, pFirstBlk;
2956 SLTG_LibBlk *pLibBlk;
2957 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2958 char *pAfterOTIBlks = NULL;
2959 char *pNameTable, *ptr;
2960 int i;
2961 DWORD len, order;
2962 ITypeInfoImpl **ppTypeInfoImpl;
2964 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2966 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2967 if (!pTypeLibImpl) return NULL;
2969 pTypeLibImpl->lpVtbl = &tlbvt;
2970 pTypeLibImpl->ref = 1;
2972 pHeader = pLib;
2974 TRACE("header:\n");
2975 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2976 pHeader->nrOfFileBlks );
2977 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
2978 FIXME("Header type magic 0x%08lx not supported.\n",
2979 pHeader->SLTG_magic);
2980 return NULL;
2983 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2984 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2986 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2987 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2989 /* Next we have a magic block */
2990 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2992 /* Let's see if we're still in sync */
2993 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2994 sizeof(SLTG_COMPOBJ_MAGIC))) {
2995 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2996 return NULL;
2998 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2999 sizeof(SLTG_DIR_MAGIC))) {
3000 FIXME("dir magic = %s\n", pMagic->dir_magic);
3001 return NULL;
3004 pIndex = (SLTG_Index*)(pMagic+1);
3006 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3008 pFirstBlk = (LPVOID)(pPad9 + 1);
3010 /* We'll set up a ptr to the main library block, which is the last one. */
3012 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3013 pBlkEntry[order].next != 0;
3014 order = pBlkEntry[order].next - 1, i++) {
3015 pBlk = (char*)pBlk + pBlkEntry[order].len;
3017 pLibBlk = pBlk;
3019 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3021 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3022 interspersed */
3024 len += 0x40;
3026 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3028 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3029 sizeof(*pOtherTypeInfoBlks) *
3030 pTypeLibImpl->TypeInfoCount);
3033 ptr = (char*)pLibBlk + len;
3035 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3036 WORD w, extra;
3037 len = 0;
3039 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3041 w = *(WORD*)(ptr + 2);
3042 if(w != 0xffff) {
3043 len += w;
3044 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3045 w+1);
3046 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3047 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3049 w = *(WORD*)(ptr + 4 + len);
3050 if(w != 0xffff) {
3051 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3052 len += w;
3053 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3054 w+1);
3055 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3056 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3058 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3059 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3060 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3061 if(extra) {
3062 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3063 extra);
3064 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3065 len += extra;
3067 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3068 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3069 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3070 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3071 len += sizeof(SLTG_OtherTypeInfo);
3072 ptr += len;
3075 pAfterOTIBlks = ptr;
3077 /* Skip this WORD and get the next DWORD */
3078 len = *(DWORD*)(pAfterOTIBlks + 2);
3080 /* Now add this to pLibBLk look at what we're pointing at and
3081 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3082 dust and we should be pointing at the beginning of the name
3083 table */
3085 pNameTable = (char*)pLibBlk + len;
3087 switch(*(WORD*)pNameTable) {
3088 case 0xffff:
3089 break;
3090 case 0x0200:
3091 pNameTable += 0x20;
3092 break;
3093 default:
3094 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3095 break;
3098 pNameTable += 0x216;
3100 pNameTable += 2;
3102 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3104 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3107 /* Hopefully we now have enough ptrs set up to actually read in
3108 some TypeInfos. It's not clear which order to do them in, so
3109 I'll just follow the links along the BlkEntry chain and read
3110 them in in the order in which they're in the file */
3112 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3114 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3115 pBlkEntry[order].next != 0;
3116 order = pBlkEntry[order].next - 1, i++) {
3118 SLTG_TypeInfoHeader *pTIHeader;
3119 SLTG_TypeInfoTail *pTITail;
3121 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3122 pOtherTypeInfoBlks[i].index_name)) {
3123 FIXME("Index strings don't match\n");
3124 return NULL;
3127 pTIHeader = pBlk;
3128 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3129 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3130 return NULL;
3132 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3133 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3134 (*ppTypeInfoImpl)->index = i;
3135 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3136 pOtherTypeInfoBlks[i].name_offs +
3137 pNameTable);
3138 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3139 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3140 sizeof(GUID));
3141 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3142 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3143 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3144 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3145 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3147 if((pTIHeader->typeflags1 & 7) != 2)
3148 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3149 if(pTIHeader->typeflags3 != 2)
3150 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3152 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3153 debugstr_w((*ppTypeInfoImpl)->Name),
3154 typekind_desc[pTIHeader->typekind],
3155 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3156 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3158 switch(pTIHeader->typekind) {
3159 case TKIND_ENUM:
3160 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3161 break;
3163 case TKIND_RECORD:
3164 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3165 break;
3167 case TKIND_INTERFACE:
3168 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3169 break;
3171 case TKIND_COCLASS:
3172 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3173 break;
3175 case TKIND_ALIAS:
3176 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3177 if (pTITail->tdescalias_vt)
3178 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3179 break;
3181 case TKIND_DISPATCH:
3182 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3183 break;
3185 default:
3186 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3187 pTITail = NULL;
3188 break;
3192 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3193 but we've already set those */
3194 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3195 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3196 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3198 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3199 X(06);
3200 X(08);
3201 X(0a);
3202 X(0c);
3203 X(0e);
3204 X(10);
3205 X(12);
3206 X(16);
3207 X(18);
3208 X(1a);
3209 X(1c);
3210 X(1e);
3211 X(24);
3212 X(26);
3213 X(2a);
3214 X(2c);
3215 X(2e);
3216 X(30);
3217 X(32);
3218 X(34);
3220 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3221 pBlk = (char*)pBlk + pBlkEntry[order].len;
3224 if(i != pTypeLibImpl->TypeInfoCount) {
3225 FIXME("Somehow processed %d TypeInfos\n", i);
3226 return NULL;
3229 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3230 return (ITypeLib2*)pTypeLibImpl;
3233 /* ITypeLib::QueryInterface
3235 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3236 ITypeLib2 * iface,
3237 REFIID riid,
3238 VOID **ppvObject)
3240 ICOM_THIS( ITypeLibImpl, iface);
3242 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3244 *ppvObject=NULL;
3245 if(IsEqualIID(riid, &IID_IUnknown) ||
3246 IsEqualIID(riid,&IID_ITypeLib)||
3247 IsEqualIID(riid,&IID_ITypeLib2))
3249 *ppvObject = This;
3252 if(*ppvObject)
3254 ITypeLib2_AddRef(iface);
3255 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3256 return S_OK;
3258 TRACE("-- Interface: E_NOINTERFACE\n");
3259 return E_NOINTERFACE;
3262 /* ITypeLib::AddRef
3264 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3266 ICOM_THIS( ITypeLibImpl, iface);
3268 TRACE("(%p)->ref was %u\n",This, This->ref);
3270 return ++(This->ref);
3273 /* ITypeLib::Release
3275 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3277 ICOM_THIS( ITypeLibImpl, iface);
3279 --(This->ref);
3281 TRACE("(%p)->(%u)\n",This, This->ref);
3283 if (!This->ref)
3285 /* remove cache entry */
3286 TRACE("removing from cache list\n");
3287 EnterCriticalSection(&cache_section);
3288 if (This->next) This->next->prev = This->prev;
3289 if (This->prev) This->prev->next = This->next;
3290 else tlb_cache_first = This->next;
3291 LeaveCriticalSection(&cache_section);
3293 /* FIXME destroy child objects */
3294 TRACE(" destroying ITypeLib(%p)\n",This);
3296 if (This->Name)
3298 SysFreeString(This->Name);
3299 This->Name = NULL;
3302 if (This->DocString)
3304 SysFreeString(This->DocString);
3305 This->DocString = NULL;
3308 if (This->HelpFile)
3310 SysFreeString(This->HelpFile);
3311 This->HelpFile = NULL;
3314 if (This->HelpStringDll)
3316 SysFreeString(This->HelpStringDll);
3317 This->HelpStringDll = NULL;
3320 if (This->pTypeInfo) /* can be NULL */
3321 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3322 HeapFree(GetProcessHeap(),0,This);
3323 return 0;
3326 return This->ref;
3329 /* ITypeLib::GetTypeInfoCount
3331 * Returns the number of type descriptions in the type library
3333 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3335 ICOM_THIS( ITypeLibImpl, iface);
3336 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3337 return This->TypeInfoCount;
3340 /* ITypeLib::GetTypeInfo
3342 * retrieves the specified type description in the library.
3344 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3345 ITypeLib2 *iface,
3346 UINT index,
3347 ITypeInfo **ppTInfo)
3349 int i;
3351 ICOM_THIS( ITypeLibImpl, iface);
3352 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3354 TRACE("(%p)->(index=%d) \n", This, index);
3356 if (!ppTInfo) return E_INVALIDARG;
3358 /* search element n in list */
3359 for(i=0; i < index; i++)
3361 pTypeInfo = pTypeInfo->next;
3362 if (!pTypeInfo)
3364 TRACE("-- element not found\n");
3365 return TYPE_E_ELEMENTNOTFOUND;
3369 *ppTInfo = (ITypeInfo *) pTypeInfo;
3371 ITypeInfo_AddRef(*ppTInfo);
3372 TRACE("-- found (%p)\n",*ppTInfo);
3373 return S_OK;
3377 /* ITypeLibs::GetTypeInfoType
3379 * Retrieves the type of a type description.
3381 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3382 ITypeLib2 *iface,
3383 UINT index,
3384 TYPEKIND *pTKind)
3386 ICOM_THIS( ITypeLibImpl, iface);
3387 int i;
3388 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3390 TRACE("(%p) index %d \n",This, index);
3392 if(!pTKind) return E_INVALIDARG;
3394 /* search element n in list */
3395 for(i=0; i < index; i++)
3397 if(!pTInfo)
3399 TRACE("-- element not found\n");
3400 return TYPE_E_ELEMENTNOTFOUND;
3402 pTInfo = pTInfo->next;
3405 *pTKind = pTInfo->TypeAttr.typekind;
3406 TRACE("-- found Type (%d)\n", *pTKind);
3407 return S_OK;
3410 /* ITypeLib::GetTypeInfoOfGuid
3412 * Retrieves the type description that corresponds to the specified GUID.
3415 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3416 ITypeLib2 *iface,
3417 REFGUID guid,
3418 ITypeInfo **ppTInfo)
3420 ICOM_THIS( ITypeLibImpl, iface);
3421 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3423 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3425 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3427 /* search linked list for guid */
3428 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3430 pTypeInfo = pTypeInfo->next;
3432 if (!pTypeInfo)
3434 /* end of list reached */
3435 TRACE("-- element not found\n");
3436 return TYPE_E_ELEMENTNOTFOUND;
3440 TRACE("-- found (%p, %s)\n",
3441 pTypeInfo,
3442 debugstr_w(pTypeInfo->Name));
3444 *ppTInfo = (ITypeInfo*)pTypeInfo;
3445 ITypeInfo_AddRef(*ppTInfo);
3446 return S_OK;
3449 /* ITypeLib::GetLibAttr
3451 * Retrieves the structure that contains the library's attributes.
3454 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3455 ITypeLib2 *iface,
3456 LPTLIBATTR *ppTLibAttr)
3458 ICOM_THIS( ITypeLibImpl, iface);
3459 TRACE("(%p)\n",This);
3460 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3461 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3462 return S_OK;
3465 /* ITypeLib::GetTypeComp
3467 * Enables a client compiler to bind to a library's types, variables,
3468 * constants, and global functions.
3471 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3472 ITypeLib2 *iface,
3473 ITypeComp **ppTComp)
3475 ICOM_THIS( ITypeLibImpl, iface);
3477 TRACE("(%p)->(%p)\n",This,ppTComp);
3478 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3479 ITypeComp_AddRef(*ppTComp);
3481 return S_OK;
3484 /* ITypeLib::GetDocumentation
3486 * Retrieves the library's documentation string, the complete Help file name
3487 * and path, and the context identifier for the library Help topic in the Help
3488 * file.
3490 * On a successful return all non-null BSTR pointers will have been set,
3491 * possibly to NULL.
3493 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3494 ITypeLib2 *iface,
3495 INT index,
3496 BSTR *pBstrName,
3497 BSTR *pBstrDocString,
3498 DWORD *pdwHelpContext,
3499 BSTR *pBstrHelpFile)
3501 ICOM_THIS( ITypeLibImpl, iface);
3503 HRESULT result = E_INVALIDARG;
3505 ITypeInfo *pTInfo;
3508 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3509 This, index,
3510 pBstrName, pBstrDocString,
3511 pdwHelpContext, pBstrHelpFile);
3513 if(index<0)
3515 /* documentation for the typelib */
3516 if(pBstrName)
3518 if (This->Name)
3519 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3520 else
3521 *pBstrName = NULL;
3523 if(pBstrDocString)
3525 if (This->DocString)
3526 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3527 else if (This->Name)
3528 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3529 else
3530 *pBstrDocString = NULL;
3532 if(pdwHelpContext)
3534 *pdwHelpContext = This->dwHelpContext;
3536 if(pBstrHelpFile)
3538 if (This->HelpFile)
3539 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3540 else
3541 *pBstrHelpFile = NULL;
3544 result = S_OK;
3546 else
3548 /* for a typeinfo */
3549 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3551 if(SUCCEEDED(result))
3553 result = ITypeInfo_GetDocumentation(pTInfo,
3554 MEMBERID_NIL,
3555 pBstrName,
3556 pBstrDocString,
3557 pdwHelpContext, pBstrHelpFile);
3559 ITypeInfo_Release(pTInfo);
3562 return result;
3563 memerr3:
3564 if (pBstrDocString) SysFreeString (*pBstrDocString);
3565 memerr2:
3566 if (pBstrName) SysFreeString (*pBstrName);
3567 memerr1:
3568 return STG_E_INSUFFICIENTMEMORY;
3571 /* ITypeLib::IsName
3573 * Indicates whether a passed-in string contains the name of a type or member
3574 * described in the library.
3577 static HRESULT WINAPI ITypeLib2_fnIsName(
3578 ITypeLib2 *iface,
3579 LPOLESTR szNameBuf,
3580 ULONG lHashVal,
3581 BOOL *pfName)
3583 ICOM_THIS( ITypeLibImpl, iface);
3584 ITypeInfoImpl *pTInfo;
3585 TLBFuncDesc *pFInfo;
3586 TLBVarDesc *pVInfo;
3587 int i;
3588 UINT nNameBufLen = SysStringLen(szNameBuf);
3590 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3591 pfName);
3593 *pfName=TRUE;
3594 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3595 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3596 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3597 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3598 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3599 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3600 goto ITypeLib2_fnIsName_exit;
3602 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3603 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3606 *pfName=FALSE;
3608 ITypeLib2_fnIsName_exit:
3609 TRACE("(%p)slow! search for %s: %s found!\n", This,
3610 debugstr_w(szNameBuf), *pfName?"NOT":"");
3612 return S_OK;
3615 /* ITypeLib::FindName
3617 * Finds occurrences of a type description in a type library. This may be used
3618 * to quickly verify that a name exists in a type library.
3621 static HRESULT WINAPI ITypeLib2_fnFindName(
3622 ITypeLib2 *iface,
3623 LPOLESTR szNameBuf,
3624 ULONG lHashVal,
3625 ITypeInfo **ppTInfo,
3626 MEMBERID *rgMemId,
3627 UINT16 *pcFound)
3629 ICOM_THIS( ITypeLibImpl, iface);
3630 ITypeInfoImpl *pTInfo;
3631 TLBFuncDesc *pFInfo;
3632 TLBVarDesc *pVInfo;
3633 int i,j = 0;
3635 UINT nNameBufLen = SysStringLen(szNameBuf);
3637 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3638 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3639 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3640 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3641 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3642 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3643 goto ITypeLib2_fnFindName_exit;
3645 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3646 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3647 continue;
3648 ITypeLib2_fnFindName_exit:
3649 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3650 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3651 j++;
3653 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3654 This, *pcFound, debugstr_w(szNameBuf), j);
3656 *pcFound=j;
3658 return S_OK;
3661 /* ITypeLib::ReleaseTLibAttr
3663 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3666 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3667 ITypeLib2 *iface,
3668 TLIBATTR *pTLibAttr)
3670 ICOM_THIS( ITypeLibImpl, iface);
3671 TRACE("freeing (%p)\n",This);
3672 HeapFree(GetProcessHeap(),0,pTLibAttr);
3676 /* ITypeLib2::GetCustData
3678 * gets the custom data
3680 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3681 ITypeLib2 * iface,
3682 REFGUID guid,
3683 VARIANT *pVarVal)
3685 ICOM_THIS( ITypeLibImpl, iface);
3686 TLBCustData *pCData;
3688 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3690 if( IsEqualIID(guid, &pCData->guid)) break;
3693 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3695 if(pCData)
3697 VariantInit( pVarVal);
3698 VariantCopy( pVarVal, &pCData->data);
3699 return S_OK;
3701 return E_INVALIDARG; /* FIXME: correct? */
3704 /* ITypeLib2::GetLibStatistics
3706 * Returns statistics about a type library that are required for efficient
3707 * sizing of hash tables.
3710 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3711 ITypeLib2 * iface,
3712 ULONG *pcUniqueNames,
3713 ULONG *pcchUniqueNames)
3715 ICOM_THIS( ITypeLibImpl, iface);
3717 FIXME("(%p): stub!\n", This);
3719 if(pcUniqueNames) *pcUniqueNames=1;
3720 if(pcchUniqueNames) *pcchUniqueNames=1;
3721 return S_OK;
3724 /* ITypeLib2::GetDocumentation2
3726 * Retrieves the library's documentation string, the complete Help file name
3727 * and path, the localization context to use, and the context ID for the
3728 * library Help topic in the Help file.
3731 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3732 ITypeLib2 * iface,
3733 INT index,
3734 LCID lcid,
3735 BSTR *pbstrHelpString,
3736 DWORD *pdwHelpStringContext,
3737 BSTR *pbstrHelpStringDll)
3739 ICOM_THIS( ITypeLibImpl, iface);
3740 HRESULT result;
3741 ITypeInfo *pTInfo;
3743 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3745 /* the help string should be obtained from the helpstringdll,
3746 * using the _DLLGetDocumentation function, based on the supplied
3747 * lcid. Nice to do sometime...
3749 if(index<0)
3751 /* documentation for the typelib */
3752 if(pbstrHelpString)
3753 *pbstrHelpString=SysAllocString(This->DocString);
3754 if(pdwHelpStringContext)
3755 *pdwHelpStringContext=This->dwHelpContext;
3756 if(pbstrHelpStringDll)
3757 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3759 result = S_OK;
3761 else
3763 /* for a typeinfo */
3764 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3766 if(SUCCEEDED(result))
3768 ITypeInfo2 * pTInfo2;
3769 result = ITypeInfo_QueryInterface(pTInfo,
3770 &IID_ITypeInfo2,
3771 (LPVOID*) &pTInfo2);
3773 if(SUCCEEDED(result))
3775 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3776 MEMBERID_NIL,
3777 lcid,
3778 pbstrHelpString,
3779 pdwHelpStringContext,
3780 pbstrHelpStringDll);
3782 ITypeInfo2_Release(pTInfo2);
3785 ITypeInfo_Release(pTInfo);
3788 return result;
3791 /* ITypeLib2::GetAllCustData
3793 * Gets all custom data items for the library.
3796 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3797 ITypeLib2 * iface,
3798 CUSTDATA *pCustData)
3800 ICOM_THIS( ITypeLibImpl, iface);
3801 TLBCustData *pCData;
3802 int i;
3803 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3804 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3805 if(pCustData->prgCustData ){
3806 pCustData->cCustData=This->ctCustData;
3807 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3808 pCustData->prgCustData[i].guid=pCData->guid;
3809 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3811 }else{
3812 ERR(" OUT OF MEMORY! \n");
3813 return E_OUTOFMEMORY;
3815 return S_OK;
3818 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3819 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3820 ITypeLib2_fnQueryInterface,
3821 ITypeLib2_fnAddRef,
3822 ITypeLib2_fnRelease,
3823 ITypeLib2_fnGetTypeInfoCount,
3824 ITypeLib2_fnGetTypeInfo,
3825 ITypeLib2_fnGetTypeInfoType,
3826 ITypeLib2_fnGetTypeInfoOfGuid,
3827 ITypeLib2_fnGetLibAttr,
3828 ITypeLib2_fnGetTypeComp,
3829 ITypeLib2_fnGetDocumentation,
3830 ITypeLib2_fnIsName,
3831 ITypeLib2_fnFindName,
3832 ITypeLib2_fnReleaseTLibAttr,
3834 ITypeLib2_fnGetCustData,
3835 ITypeLib2_fnGetLibStatistics,
3836 ITypeLib2_fnGetDocumentation2,
3837 ITypeLib2_fnGetAllCustData
3841 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
3843 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3845 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
3848 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
3850 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3852 return ITypeInfo_AddRef((ITypeInfo *)This);
3855 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
3857 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3859 return ITypeInfo_Release((ITypeInfo *)This);
3862 static HRESULT WINAPI ITypeLibComp_fnBind(
3863 ITypeComp * iface,
3864 OLECHAR * szName,
3865 unsigned long lHash,
3866 unsigned short wFlags,
3867 ITypeInfo ** ppTInfo,
3868 DESCKIND * pDescKind,
3869 BINDPTR * pBindPtr)
3871 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
3872 return E_NOTIMPL;
3875 static HRESULT WINAPI ITypeLibComp_fnBindType(
3876 ITypeComp * iface,
3877 OLECHAR * szName,
3878 unsigned long lHash,
3879 ITypeInfo ** ppTInfo,
3880 ITypeComp ** ppTComp)
3882 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
3883 return E_NOTIMPL;
3886 static ICOM_VTABLE(ITypeComp) tlbtcvt =
3888 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3890 ITypeLibComp_fnQueryInterface,
3891 ITypeLibComp_fnAddRef,
3892 ITypeLibComp_fnRelease,
3894 ITypeLibComp_fnBind,
3895 ITypeLibComp_fnBindType
3898 /*================== ITypeInfo(2) Methods ===================================*/
3899 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3901 ITypeInfoImpl * pTypeInfoImpl;
3903 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3904 if (pTypeInfoImpl)
3906 pTypeInfoImpl->lpVtbl = &tinfvt;
3907 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
3908 pTypeInfoImpl->ref=1;
3910 TRACE("(%p)\n", pTypeInfoImpl);
3911 return (ITypeInfo2*) pTypeInfoImpl;
3914 /* ITypeInfo::QueryInterface
3916 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3917 ITypeInfo2 *iface,
3918 REFIID riid,
3919 VOID **ppvObject)
3921 ICOM_THIS( ITypeLibImpl, iface);
3923 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3925 *ppvObject=NULL;
3926 if(IsEqualIID(riid, &IID_IUnknown) ||
3927 IsEqualIID(riid,&IID_ITypeInfo)||
3928 IsEqualIID(riid,&IID_ITypeInfo2))
3929 *ppvObject = This;
3931 if(*ppvObject){
3932 ITypeInfo_AddRef(iface);
3933 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3934 return S_OK;
3936 TRACE("-- Interface: E_NOINTERFACE\n");
3937 return E_NOINTERFACE;
3940 /* ITypeInfo::AddRef
3942 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3944 ICOM_THIS( ITypeInfoImpl, iface);
3946 ++(This->ref);
3948 TRACE("(%p)->ref is %u\n",This, This->ref);
3949 return This->ref;
3952 /* ITypeInfo::Release
3954 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3956 ICOM_THIS( ITypeInfoImpl, iface);
3958 --(This->ref);
3960 TRACE("(%p)->(%u)\n",This, This->ref);
3962 if (!This->ref)
3964 FIXME("destroy child objects\n");
3966 TRACE("destroying ITypeInfo(%p)\n",This);
3967 if (This->Name)
3969 SysFreeString(This->Name);
3970 This->Name = 0;
3973 if (This->DocString)
3975 SysFreeString(This->DocString);
3976 This->DocString = 0;
3979 if (This->next)
3981 ITypeInfo_Release((ITypeInfo*)This->next);
3984 HeapFree(GetProcessHeap(),0,This);
3985 return 0;
3987 return This->ref;
3990 /* ITypeInfo::GetTypeAttr
3992 * Retrieves a TYPEATTR structure that contains the attributes of the type
3993 * description.
3996 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3997 LPTYPEATTR *ppTypeAttr)
3999 ICOM_THIS( ITypeInfoImpl, iface);
4000 TRACE("(%p)\n",This);
4001 /* FIXME: must do a copy here */
4002 *ppTypeAttr=&This->TypeAttr;
4003 return S_OK;
4006 /* ITypeInfo::GetTypeComp
4008 * Retrieves the ITypeComp interface for the type description, which enables a
4009 * client compiler to bind to the type description's members.
4012 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4013 ITypeComp * *ppTComp)
4015 ICOM_THIS( ITypeInfoImpl, iface);
4017 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4019 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4020 ITypeComp_AddRef(*ppTComp);
4021 return S_OK;
4024 /* ITypeInfo::GetFuncDesc
4026 * Retrieves the FUNCDESC structure that contains information about a
4027 * specified function.
4030 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4031 LPFUNCDESC *ppFuncDesc)
4033 ICOM_THIS( ITypeInfoImpl, iface);
4034 int i;
4035 TLBFuncDesc * pFDesc;
4036 TRACE("(%p) index %d\n", This, index);
4037 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4039 if(pFDesc){
4040 /* FIXME: must do a copy here */
4041 *ppFuncDesc=&pFDesc->funcdesc;
4042 return S_OK;
4044 return E_INVALIDARG;
4047 /* ITypeInfo::GetVarDesc
4049 * Retrieves a VARDESC structure that describes the specified variable.
4052 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4053 LPVARDESC *ppVarDesc)
4055 ICOM_THIS( ITypeInfoImpl, iface);
4056 int i;
4057 TLBVarDesc * pVDesc;
4058 TRACE("(%p) index %d\n", This, index);
4059 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4061 if(pVDesc){
4062 /* FIXME: must do a copy here */
4063 *ppVarDesc=&pVDesc->vardesc;
4064 return S_OK;
4066 return E_INVALIDARG;
4069 /* ITypeInfo_GetNames
4071 * Retrieves the variable with the specified member ID (or the name of the
4072 * property or method and its parameters) that correspond to the specified
4073 * function ID.
4075 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4076 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4078 ICOM_THIS( ITypeInfoImpl, iface);
4079 TLBFuncDesc * pFDesc;
4080 TLBVarDesc * pVDesc;
4081 int i;
4082 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4083 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4084 if(pFDesc)
4086 /* function found, now return function and parameter names */
4087 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4089 if(!i)
4090 *rgBstrNames=SysAllocString(pFDesc->Name);
4091 else
4092 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4094 *pcNames=i;
4096 else
4098 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4099 if(pVDesc)
4101 *rgBstrNames=SysAllocString(pVDesc->Name);
4102 *pcNames=1;
4104 else
4106 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
4108 /* recursive search */
4109 ITypeInfo *pTInfo;
4110 HRESULT result;
4111 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4112 &pTInfo);
4113 if(SUCCEEDED(result))
4115 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4116 ITypeInfo_Release(pTInfo);
4117 return result;
4119 WARN("Could not search inherited interface!\n");
4121 else
4123 WARN("no names found\n");
4125 *pcNames=0;
4126 return TYPE_E_ELEMENTNOTFOUND;
4129 return S_OK;
4133 /* ITypeInfo::GetRefTypeOfImplType
4135 * If a type description describes a COM class, it retrieves the type
4136 * description of the implemented interface types. For an interface,
4137 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4138 * if any exist.
4141 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4142 ITypeInfo2 *iface,
4143 UINT index,
4144 HREFTYPE *pRefType)
4146 ICOM_THIS( ITypeInfoImpl, iface);
4147 int(i);
4148 TLBImplType *pImpl = This->impltypelist;
4150 TRACE("(%p) index %d\n", This, index);
4151 if (TRACE_ON(ole)) dump_TypeInfo(This);
4153 if(index==(UINT)-1)
4155 /* only valid on dual interfaces;
4156 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4158 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4160 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4161 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4163 *pRefType = -1;
4165 else
4167 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4168 *pRefType = pImpl->hRef;
4171 else
4173 /* get element n from linked list */
4174 for(i=0; pImpl && i<index; i++)
4176 pImpl = pImpl->next;
4179 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4181 *pRefType = pImpl->hRef;
4183 TRACE("-- 0x%08lx\n", pImpl->hRef );
4186 return S_OK;
4190 /* ITypeInfo::GetImplTypeFlags
4192 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4193 * or base interface in a type description.
4195 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4196 UINT index, INT *pImplTypeFlags)
4198 ICOM_THIS( ITypeInfoImpl, iface);
4199 int i;
4200 TLBImplType *pImpl;
4202 TRACE("(%p) index %d\n", This, index);
4203 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4204 i++, pImpl=pImpl->next)
4206 if(i==index && pImpl){
4207 *pImplTypeFlags=pImpl->implflags;
4208 return S_OK;
4210 *pImplTypeFlags=0;
4211 return TYPE_E_ELEMENTNOTFOUND;
4214 /* GetIDsOfNames
4215 * Maps between member names and member IDs, and parameter names and
4216 * parameter IDs.
4218 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4219 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4221 ICOM_THIS( ITypeInfoImpl, iface);
4222 TLBFuncDesc * pFDesc;
4223 TLBVarDesc * pVDesc;
4224 HRESULT ret=S_OK;
4226 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4227 cNames);
4228 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4229 int i, j;
4230 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4231 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4232 for(i=1; i < cNames; i++){
4233 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4234 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4235 break;
4236 if( j<pFDesc->funcdesc.cParams)
4237 pMemId[i]=j;
4238 else
4239 ret=DISP_E_UNKNOWNNAME;
4241 return ret;
4244 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4245 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4246 if(cNames) *pMemId=pVDesc->vardesc.memid;
4247 return ret;
4250 /* not found, see if this is and interface with an inheritance */
4251 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
4252 This->TypeAttr.cImplTypes ){
4253 /* recursive search */
4254 ITypeInfo *pTInfo;
4255 ret=ITypeInfo_GetRefTypeInfo(iface,
4256 This->impltypelist->hRef, &pTInfo);
4257 if(SUCCEEDED(ret)){
4258 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4259 ITypeInfo_Release(pTInfo);
4260 return ret;
4262 WARN("Could not search inherited interface!\n");
4263 } else
4264 WARN("no names found\n");
4265 return DISP_E_UNKNOWNNAME;
4268 /* ITypeInfo::Invoke
4270 * Invokes a method, or accesses a property of an object, that implements the
4271 * interface described by the type description.
4273 DWORD
4274 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4275 DWORD res;
4277 if (TRACE_ON(ole)) {
4278 int i;
4279 TRACE("Calling %p(",func);
4280 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4281 TRACE(")\n");
4284 switch (callconv) {
4285 case CC_STDCALL:
4287 switch (nrargs) {
4288 case 0:
4289 res = func();
4290 break;
4291 case 1:
4292 res = func(args[0]);
4293 break;
4294 case 2:
4295 res = func(args[0],args[1]);
4296 break;
4297 case 3:
4298 res = func(args[0],args[1],args[2]);
4299 break;
4300 case 4:
4301 res = func(args[0],args[1],args[2],args[3]);
4302 break;
4303 case 5:
4304 res = func(args[0],args[1],args[2],args[3],args[4]);
4305 break;
4306 case 6:
4307 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4308 break;
4309 case 7:
4310 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4311 break;
4312 case 8:
4313 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4314 break;
4315 case 9:
4316 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4317 break;
4318 default:
4319 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4320 res = -1;
4321 break;
4323 break;
4324 default:
4325 FIXME("unsupported calling convention %d\n",callconv);
4326 res = -1;
4327 break;
4329 TRACE("returns %08lx\n",res);
4330 return res;
4333 extern int const _argsize(DWORD vt);
4335 /****************************************************************************
4336 * Helper functions for Dispcall / Invoke, which copies one variant
4337 * with target type onto the argument stack.
4339 static HRESULT
4340 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4341 DWORD *argpos, VARIANT *arg, VARTYPE vt
4343 UINT arglen = _argsize(vt)*sizeof(DWORD);
4344 VARTYPE oldvt;
4345 VARIANT va;
4347 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4348 memcpy(argpos,&arg,sizeof(void*));
4349 return S_OK;
4352 if (V_VT(arg) == vt) {
4353 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4354 return S_OK;
4357 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4358 memcpy(argpos, &V_UNION(arg,parray), sizeof(SAFEARRAY*));
4359 return S_OK;
4362 if (vt == VT_VARIANT) {
4363 memcpy(argpos, arg, arglen);
4364 return S_OK;
4366 /* Deref BYREF vars if there is need */
4367 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4368 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4369 return S_OK;
4371 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4372 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4373 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4374 return S_OK;
4376 if ((vt == VT_PTR) && tdesc)
4377 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4379 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4380 ITypeInfo *tinfo2;
4381 TYPEATTR *tattr;
4382 HRESULT hres;
4384 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4385 if (hres) {
4386 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing from vt 0x%x. Copying 4 byte.\n",tdesc->u.hreftype,V_VT(arg));
4387 memcpy(argpos, &V_UNION(arg,lVal), 4);
4388 return S_OK;
4390 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4391 switch (tattr->typekind) {
4392 case TKIND_ENUM:
4393 switch ( V_VT( arg ) ) {
4394 case VT_I2:
4395 *argpos = V_UNION(arg,iVal);
4396 return S_OK;
4397 case VT_I4:
4398 memcpy(argpos, &V_UNION(arg,lVal), 4);
4399 return S_OK;
4400 default:
4401 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4402 break;
4405 case TKIND_ALIAS:
4406 tdesc = &(tattr->tdescAlias);
4407 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4408 ITypeInfo_Release(tinfo2);
4409 return hres;
4411 case TKIND_INTERFACE:
4412 if (V_VT(arg) == VT_DISPATCH) {
4413 IDispatch *disp;
4414 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4415 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4416 return S_OK;
4418 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),&IID_IDispatch,(LPVOID*)&disp);
4419 if (SUCCEEDED(hres)) {
4420 memcpy(argpos,&disp,4);
4421 IUnknown_Release(V_UNION(arg,pdispVal));
4422 return S_OK;
4424 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4425 return E_FAIL;
4427 if (V_VT(arg) == VT_UNKNOWN) {
4428 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4429 return S_OK;
4431 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg),debugstr_guid(&(tattr->guid)));
4432 break;
4433 case TKIND_DISPATCH:
4434 if (V_VT(arg) == VT_DISPATCH) {
4435 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4436 return S_OK;
4438 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4439 break;
4440 case TKIND_RECORD:
4441 FIXME("TKIND_RECORD unhandled.\n");
4442 break;
4443 default:
4444 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4445 break;
4447 return E_FAIL;
4450 oldvt = V_VT(arg);
4451 VariantInit(&va);
4452 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4453 memcpy(argpos,&V_UNION(&va,lVal), arglen);
4454 FIXME("Should not use VariantChangeType here. (conversion from 0x%x -> 0x%x)\n",
4455 V_VT(arg), vt
4457 return S_OK;
4459 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4460 return E_FAIL;
4463 /***********************************************************************
4464 * DispCallFunc (OLEAUT32.@)
4466 HRESULT WINAPI
4467 DispCallFunc(
4468 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4469 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4471 int i, argsize, argspos;
4472 DWORD *args;
4473 HRESULT hres;
4475 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4476 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4478 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4479 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4480 argsize = 1;
4481 for (i=0;i<cActuals;i++) {
4482 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4483 dump_Variant(prgpvarg[i]);
4484 argsize += _argsize(prgvt[i]);
4486 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4487 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4488 argspos = 1;
4489 for (i=0;i<cActuals;i++) {
4490 VARIANT *arg = prgpvarg[i];
4491 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4492 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4493 argspos += _argsize(prgvt[i]);
4496 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4498 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4499 hres=S_OK;
4501 else
4503 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4504 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4505 FIXME("Method returned %lx\n",hres);
4507 HeapFree(GetProcessHeap(),0,args);
4508 return hres;
4511 static HRESULT WINAPI ITypeInfo_fnInvoke(
4512 ITypeInfo2 *iface,
4513 VOID *pIUnk,
4514 MEMBERID memid,
4515 UINT16 dwFlags,
4516 DISPPARAMS *pDispParams,
4517 VARIANT *pVarResult,
4518 EXCEPINFO *pExcepInfo,
4519 UINT *pArgErr)
4521 ICOM_THIS( ITypeInfoImpl, iface);
4522 TLBFuncDesc * pFDesc;
4523 TLBVarDesc * pVDesc;
4524 int i;
4525 HRESULT hres;
4527 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4528 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4530 dump_DispParms(pDispParams);
4532 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4533 if (pFDesc->funcdesc.memid == memid) {
4534 if (pFDesc->funcdesc.invkind & dwFlags)
4535 break;
4538 if (pFDesc) {
4539 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4540 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4541 switch (pFDesc->funcdesc.funckind) {
4542 case FUNC_PUREVIRTUAL:
4543 case FUNC_VIRTUAL: {
4544 DWORD res;
4545 int numargs, numargs2, argspos, args2pos;
4546 DWORD *args , *args2;
4549 numargs = 1; numargs2 = 0;
4550 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4551 if (i<pDispParams->cArgs)
4552 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4553 else {
4554 numargs += 1; /* sizeof(lpvoid) */
4555 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4559 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4560 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4562 args[0] = (DWORD)pIUnk;
4563 argspos = 1; args2pos = 0;
4564 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4565 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4566 if (i<pDispParams->cArgs) {
4567 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4568 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4569 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4570 if (FAILED(hres)) return hres;
4571 argspos += arglen;
4572 } else {
4573 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4574 if (tdesc->vt != VT_PTR)
4575 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4576 /*FIXME: give pointers for the rest, so propertyget works*/
4577 args[argspos] = (DWORD)&args2[args2pos];
4579 /* If pointer to variant, pass reference it. */
4580 if ((tdesc->vt == VT_PTR) &&
4581 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4582 pVarResult
4584 args[argspos]= (DWORD)pVarResult;
4585 argspos += 1;
4586 args2pos += arglen;
4589 if (pFDesc->funcdesc.cParamsOpt)
4590 FIXME("Does not support optional parameters (%d)\n",
4591 pFDesc->funcdesc.cParamsOpt
4594 res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4],
4595 pFDesc->funcdesc.callconv,
4596 numargs,
4597 args
4599 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4600 args2pos = 0;
4601 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4602 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4603 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4604 TYPEDESC i4_tdesc;
4605 i4_tdesc.vt = VT_I4;
4607 /* If we are a pointer to a variant, we are done already */
4608 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4609 continue;
4611 VariantInit(pVarResult);
4612 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4614 if (tdesc->vt == VT_PTR)
4615 tdesc = tdesc->u.lptdesc;
4616 if (tdesc->vt == VT_USERDEFINED) {
4617 ITypeInfo *tinfo2;
4618 TYPEATTR *tattr;
4620 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4621 if (hres) {
4622 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4623 return E_FAIL;
4625 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4626 switch (tattr->typekind) {
4627 case TKIND_ENUM:
4628 /* force the return type to be VT_I4 */
4629 tdesc = &i4_tdesc;
4630 break;
4631 case TKIND_ALIAS:
4632 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4633 tdesc = &(tattr->tdescAlias);
4634 break;
4636 case TKIND_INTERFACE:
4637 FIXME("TKIND_INTERFACE unhandled.\n");
4638 break;
4639 case TKIND_DISPATCH:
4640 FIXME("TKIND_DISPATCH unhandled.\n");
4641 break;
4642 case TKIND_RECORD:
4643 FIXME("TKIND_RECORD unhandled.\n");
4644 break;
4645 default:
4646 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4647 break;
4649 ITypeInfo_Release(tinfo2);
4651 V_VT(pVarResult) = tdesc->vt;
4653 /* HACK: VB5 likes this.
4654 * I do not know why. There is 1 example in MSDN which uses
4655 * this which appears broken (mixes int vals and
4656 * IDispatch*.).
4658 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4659 V_VT(pVarResult) = VT_DISPATCH;
4660 TRACE("storing into variant:\n");
4661 dump_Variant(pVarResult);
4662 args2pos += arglen;
4665 HeapFree(GetProcessHeap(),0,args2);
4666 HeapFree(GetProcessHeap(),0,args);
4667 return S_OK;
4669 case FUNC_DISPATCH: {
4670 IDispatch *disp;
4671 HRESULT hr;
4673 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4674 if (hr) {
4675 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4676 return hr;
4678 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4679 hr = IDispatch_Invoke(
4680 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4681 pVarResult,pExcepInfo,pArgErr
4683 if (hr)
4684 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4685 IDispatch_Release(disp);
4686 return hr;
4688 default:
4689 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4690 return E_FAIL;
4692 } else {
4693 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4694 if (pVDesc->vardesc.memid == memid) {
4695 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4696 dump_TLBVarDesc(pVDesc);
4697 break;
4701 /* not found, look for it in inherited interfaces */
4702 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4703 /* recursive search */
4704 ITypeInfo *pTInfo;
4705 HRESULT hr;
4706 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4707 if(SUCCEEDED(hr)){
4708 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4709 ITypeInfo_Release(pTInfo);
4710 return hr;
4712 WARN("Could not search inherited interface!\n");
4714 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4715 return DISP_E_MEMBERNOTFOUND;
4718 /* ITypeInfo::GetDocumentation
4720 * Retrieves the documentation string, the complete Help file name and path,
4721 * and the context ID for the Help topic for a specified type description.
4723 * (Can be tested by the Visual Basic Editor in Word for instance.)
4725 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4726 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4727 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4729 ICOM_THIS( ITypeInfoImpl, iface);
4730 TLBFuncDesc * pFDesc;
4731 TLBVarDesc * pVDesc;
4732 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4733 " HelpContext(%p) HelpFile(%p)\n",
4734 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4735 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4736 if(pBstrName)
4737 *pBstrName=SysAllocString(This->Name);
4738 if(pBstrDocString)
4739 *pBstrDocString=SysAllocString(This->DocString);
4740 if(pdwHelpContext)
4741 *pdwHelpContext=This->dwHelpContext;
4742 if(pBstrHelpFile)
4743 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4744 return S_OK;
4745 }else {/* for a member */
4746 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4747 if(pFDesc->funcdesc.memid==memid){
4748 if(pBstrName)
4749 *pBstrName = SysAllocString(pFDesc->Name);
4750 if(pBstrDocString)
4751 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4752 if(pdwHelpContext)
4753 *pdwHelpContext=pFDesc->helpcontext;
4754 return S_OK;
4756 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4757 if(pVDesc->vardesc.memid==memid){
4758 if(pBstrName)
4759 *pBstrName = SysAllocString(pVDesc->Name);
4760 if(pBstrDocString)
4761 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4762 if(pdwHelpContext)
4763 *pdwHelpContext=pVDesc->HelpContext;
4764 return S_OK;
4767 return TYPE_E_ELEMENTNOTFOUND;
4770 /* ITypeInfo::GetDllEntry
4772 * Retrieves a description or specification of an entry point for a function
4773 * in a DLL.
4775 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4776 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4777 WORD *pwOrdinal)
4779 ICOM_THIS( ITypeInfoImpl, iface);
4780 TLBFuncDesc *pFDesc;
4782 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4784 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4785 if(pFDesc->funcdesc.memid==memid){
4786 dump_TypeInfo(This);
4787 dump_TLBFuncDescOne(pFDesc);
4789 /* FIXME: This is wrong, but how do you find that out? */
4790 if (pBstrDllName) {
4791 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4792 *pBstrDllName = SysAllocString(oleaut32W);
4795 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4796 if (pBstrName)
4797 *pBstrName = SysAllocString(pFDesc->Entry);
4798 if (pwOrdinal)
4799 *pwOrdinal = -1;
4800 return S_OK;
4802 if (pBstrName)
4803 *pBstrName = NULL;
4804 if (pwOrdinal)
4805 *pwOrdinal = (DWORD)pFDesc->Entry;
4806 return S_OK;
4808 return E_FAIL;
4811 /* ITypeInfo::GetRefTypeInfo
4813 * If a type description references other type descriptions, it retrieves
4814 * the referenced type descriptions.
4816 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4817 ITypeInfo2 *iface,
4818 HREFTYPE hRefType,
4819 ITypeInfo **ppTInfo)
4821 ICOM_THIS( ITypeInfoImpl, iface);
4822 HRESULT result = E_FAIL;
4825 if (hRefType == -1 &&
4826 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4827 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4829 /* when we meet a DUAL dispinterface, we must create the interface
4830 * version of it.
4832 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4835 /* the interface version contains the same information as the dispinterface
4836 * copy the contents of the structs.
4838 *pTypeInfoImpl = *This;
4839 pTypeInfoImpl->ref = 1;
4841 /* change the type to interface */
4842 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4844 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4846 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4848 result = S_OK;
4850 } else {
4851 TLBRefType *pRefType;
4852 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4853 if(pRefType->reference == hRefType)
4854 break;
4856 if(!pRefType)
4857 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4858 if(pRefType && hRefType != -1) {
4859 ITypeLib *pTLib = NULL;
4861 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4862 int Index;
4863 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4864 } else {
4865 if(pRefType->pImpTLInfo->pImpTypeLib) {
4866 TRACE("typeinfo in imported typelib that is already loaded\n");
4867 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4868 ITypeLib2_AddRef((ITypeLib*) pTLib);
4869 result = S_OK;
4870 } else {
4871 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4872 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4873 pRefType->pImpTLInfo->wVersionMajor,
4874 pRefType->pImpTLInfo->wVersionMinor,
4875 pRefType->pImpTLInfo->lcid,
4876 &pTLib);
4878 if(!SUCCEEDED(result)) {
4879 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4880 result=LoadTypeLib(libnam, &pTLib);
4881 SysFreeString(libnam);
4883 if(SUCCEEDED(result)) {
4884 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4885 ITypeLib2_AddRef(pTLib);
4889 if(SUCCEEDED(result)) {
4890 if(pRefType->index == TLB_REF_USE_GUID)
4891 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4892 &pRefType->guid,
4893 ppTInfo);
4894 else
4895 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4896 ppTInfo);
4898 if (pTLib != NULL)
4899 ITypeLib2_Release(pTLib);
4903 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4904 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4905 return result;
4908 /* ITypeInfo::AddressOfMember
4910 * Retrieves the addresses of static functions or variables, such as those
4911 * defined in a DLL.
4913 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4914 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4916 ICOM_THIS( ITypeInfoImpl, iface);
4917 FIXME("(%p) stub!\n", This);
4918 return S_OK;
4921 /* ITypeInfo::CreateInstance
4923 * Creates a new instance of a type that describes a component object class
4924 * (coclass).
4926 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4927 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4929 ICOM_THIS( ITypeInfoImpl, iface);
4930 FIXME("(%p) stub!\n", This);
4931 return S_OK;
4934 /* ITypeInfo::GetMops
4936 * Retrieves marshalling information.
4938 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4939 BSTR *pBstrMops)
4941 ICOM_THIS( ITypeInfoImpl, iface);
4942 FIXME("(%p) stub!\n", This);
4943 return S_OK;
4946 /* ITypeInfo::GetContainingTypeLib
4948 * Retrieves the containing type library and the index of the type description
4949 * within that type library.
4951 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4952 ITypeLib * *ppTLib, UINT *pIndex)
4954 ICOM_THIS( ITypeInfoImpl, iface);
4956 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
4957 if (pIndex) {
4958 *pIndex=This->index;
4959 TRACE("returning pIndex=%d\n", *pIndex);
4962 if (ppTLib) {
4963 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4964 ITypeLib2_AddRef(*ppTLib);
4965 TRACE("returning ppTLib=%p\n", *ppTLib);
4968 return S_OK;
4971 /* ITypeInfo::ReleaseTypeAttr
4973 * Releases a TYPEATTR previously returned by GetTypeAttr.
4976 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4977 TYPEATTR* pTypeAttr)
4979 ICOM_THIS( ITypeInfoImpl, iface);
4980 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4983 /* ITypeInfo::ReleaseFuncDesc
4985 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4987 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
4988 ITypeInfo2 *iface,
4989 FUNCDESC *pFuncDesc)
4991 ICOM_THIS( ITypeInfoImpl, iface);
4992 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4995 /* ITypeInfo::ReleaseVarDesc
4997 * Releases a VARDESC previously returned by GetVarDesc.
4999 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5000 VARDESC *pVarDesc)
5002 ICOM_THIS( ITypeInfoImpl, iface);
5003 TRACE("(%p)->(%p)\n", This, pVarDesc);
5006 /* ITypeInfo2::GetTypeKind
5008 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5011 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5012 TYPEKIND *pTypeKind)
5014 ICOM_THIS( ITypeInfoImpl, iface);
5015 *pTypeKind=This->TypeAttr.typekind;
5016 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5017 return S_OK;
5020 /* ITypeInfo2::GetTypeFlags
5022 * Returns the type flags without any allocations. This returns a DWORD type
5023 * flag, which expands the type flags without growing the TYPEATTR (type
5024 * attribute).
5027 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5029 ICOM_THIS( ITypeInfoImpl, iface);
5030 *pTypeFlags=This->TypeAttr.wTypeFlags;
5031 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5032 return S_OK;
5035 /* ITypeInfo2::GetFuncIndexOfMemId
5036 * Binds to a specific member based on a known DISPID, where the member name
5037 * is not known (for example, when binding to a default member).
5040 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5041 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5043 ICOM_THIS( ITypeInfoImpl, iface);
5044 TLBFuncDesc *pFuncInfo;
5045 int i;
5046 HRESULT result;
5047 /* FIXME: should check for invKind??? */
5048 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
5049 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
5050 if(pFuncInfo){
5051 *pFuncIndex=i;
5052 result= S_OK;
5053 }else{
5054 *pFuncIndex=0;
5055 result=E_INVALIDARG;
5057 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5058 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
5059 return result;
5062 /* TypeInfo2::GetVarIndexOfMemId
5064 * Binds to a specific member based on a known DISPID, where the member name
5065 * is not known (for example, when binding to a default member).
5068 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5069 MEMBERID memid, UINT *pVarIndex)
5071 ICOM_THIS( ITypeInfoImpl, iface);
5072 TLBVarDesc *pVarInfo;
5073 int i;
5074 HRESULT result;
5075 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5076 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5078 if(pVarInfo){
5079 *pVarIndex=i;
5080 result= S_OK;
5081 }else{
5082 *pVarIndex=0;
5083 result=E_INVALIDARG;
5085 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5086 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
5087 return result;
5090 /* ITypeInfo2::GetCustData
5092 * Gets the custom data
5094 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5095 ITypeInfo2 * iface,
5096 REFGUID guid,
5097 VARIANT *pVarVal)
5099 ICOM_THIS( ITypeInfoImpl, iface);
5100 TLBCustData *pCData;
5102 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5103 if( IsEqualIID(guid, &pCData->guid)) break;
5105 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5107 if(pCData)
5109 VariantInit( pVarVal);
5110 VariantCopy( pVarVal, &pCData->data);
5111 return S_OK;
5113 return E_INVALIDARG; /* FIXME: correct? */
5116 /* ITypeInfo2::GetFuncCustData
5118 * Gets the custom data
5120 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5121 ITypeInfo2 * iface,
5122 UINT index,
5123 REFGUID guid,
5124 VARIANT *pVarVal)
5126 ICOM_THIS( ITypeInfoImpl, iface);
5127 TLBCustData *pCData=NULL;
5128 TLBFuncDesc * pFDesc;
5129 int i;
5130 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5131 pFDesc=pFDesc->next);
5133 if(pFDesc)
5134 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5135 if( IsEqualIID(guid, &pCData->guid)) break;
5137 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5139 if(pCData){
5140 VariantInit( pVarVal);
5141 VariantCopy( pVarVal, &pCData->data);
5142 return S_OK;
5144 return E_INVALIDARG; /* FIXME: correct? */
5147 /* ITypeInfo2::GetParamCustData
5149 * Gets the custom data
5151 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5152 ITypeInfo2 * iface,
5153 UINT indexFunc,
5154 UINT indexParam,
5155 REFGUID guid,
5156 VARIANT *pVarVal)
5158 ICOM_THIS( ITypeInfoImpl, iface);
5159 TLBCustData *pCData=NULL;
5160 TLBFuncDesc * pFDesc;
5161 int i;
5163 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5165 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5166 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5167 pCData = pCData->next)
5168 if( IsEqualIID(guid, &pCData->guid)) break;
5170 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5172 if(pCData)
5174 VariantInit( pVarVal);
5175 VariantCopy( pVarVal, &pCData->data);
5176 return S_OK;
5178 return E_INVALIDARG; /* FIXME: correct? */
5181 /* ITypeInfo2::GetVarCustData
5183 * Gets the custom data
5185 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5186 ITypeInfo2 * iface,
5187 UINT index,
5188 REFGUID guid,
5189 VARIANT *pVarVal)
5191 ICOM_THIS( ITypeInfoImpl, iface);
5192 TLBCustData *pCData=NULL;
5193 TLBVarDesc * pVDesc;
5194 int i;
5196 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5198 if(pVDesc)
5200 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5202 if( IsEqualIID(guid, &pCData->guid)) break;
5206 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5208 if(pCData)
5210 VariantInit( pVarVal);
5211 VariantCopy( pVarVal, &pCData->data);
5212 return S_OK;
5214 return E_INVALIDARG; /* FIXME: correct? */
5217 /* ITypeInfo2::GetImplCustData
5219 * Gets the custom data
5221 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5222 ITypeInfo2 * iface,
5223 UINT index,
5224 REFGUID guid,
5225 VARIANT *pVarVal)
5227 ICOM_THIS( ITypeInfoImpl, iface);
5228 TLBCustData *pCData=NULL;
5229 TLBImplType * pRDesc;
5230 int i;
5232 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5234 if(pRDesc)
5236 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5238 if( IsEqualIID(guid, &pCData->guid)) break;
5242 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5244 if(pCData)
5246 VariantInit( pVarVal);
5247 VariantCopy( pVarVal, &pCData->data);
5248 return S_OK;
5250 return E_INVALIDARG; /* FIXME: correct? */
5253 /* ITypeInfo2::GetDocumentation2
5255 * Retrieves the documentation string, the complete Help file name and path,
5256 * the localization context to use, and the context ID for the library Help
5257 * topic in the Help file.
5260 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5261 ITypeInfo2 * iface,
5262 MEMBERID memid,
5263 LCID lcid,
5264 BSTR *pbstrHelpString,
5265 DWORD *pdwHelpStringContext,
5266 BSTR *pbstrHelpStringDll)
5268 ICOM_THIS( ITypeInfoImpl, iface);
5269 TLBFuncDesc * pFDesc;
5270 TLBVarDesc * pVDesc;
5271 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5272 "HelpStringContext(%p) HelpStringDll(%p)\n",
5273 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5274 pbstrHelpStringDll );
5275 /* the help string should be obtained from the helpstringdll,
5276 * using the _DLLGetDocumentation function, based on the supplied
5277 * lcid. Nice to do sometime...
5279 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5280 if(pbstrHelpString)
5281 *pbstrHelpString=SysAllocString(This->Name);
5282 if(pdwHelpStringContext)
5283 *pdwHelpStringContext=This->dwHelpStringContext;
5284 if(pbstrHelpStringDll)
5285 *pbstrHelpStringDll=
5286 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5287 return S_OK;
5288 }else {/* for a member */
5289 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5290 if(pFDesc->funcdesc.memid==memid){
5291 if(pbstrHelpString)
5292 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5293 if(pdwHelpStringContext)
5294 *pdwHelpStringContext=pFDesc->HelpStringContext;
5295 if(pbstrHelpStringDll)
5296 *pbstrHelpStringDll=
5297 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5298 return S_OK;
5300 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5301 if(pVDesc->vardesc.memid==memid){
5302 if(pbstrHelpString)
5303 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5304 if(pdwHelpStringContext)
5305 *pdwHelpStringContext=pVDesc->HelpStringContext;
5306 if(pbstrHelpStringDll)
5307 *pbstrHelpStringDll=
5308 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5309 return S_OK;
5312 return TYPE_E_ELEMENTNOTFOUND;
5315 /* ITypeInfo2::GetAllCustData
5317 * Gets all custom data items for the Type info.
5320 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5321 ITypeInfo2 * iface,
5322 CUSTDATA *pCustData)
5324 ICOM_THIS( ITypeInfoImpl, iface);
5325 TLBCustData *pCData;
5326 int i;
5328 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5330 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5331 if(pCustData->prgCustData ){
5332 pCustData->cCustData=This->ctCustData;
5333 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5334 pCustData->prgCustData[i].guid=pCData->guid;
5335 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5337 }else{
5338 ERR(" OUT OF MEMORY! \n");
5339 return E_OUTOFMEMORY;
5341 return S_OK;
5344 /* ITypeInfo2::GetAllFuncCustData
5346 * Gets all custom data items for the specified Function
5349 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5350 ITypeInfo2 * iface,
5351 UINT index,
5352 CUSTDATA *pCustData)
5354 ICOM_THIS( ITypeInfoImpl, iface);
5355 TLBCustData *pCData;
5356 TLBFuncDesc * pFDesc;
5357 int i;
5358 TRACE("(%p) index %d\n", This, index);
5359 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5360 pFDesc=pFDesc->next)
5362 if(pFDesc){
5363 pCustData->prgCustData =
5364 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5365 if(pCustData->prgCustData ){
5366 pCustData->cCustData=pFDesc->ctCustData;
5367 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5368 pCData = pCData->next){
5369 pCustData->prgCustData[i].guid=pCData->guid;
5370 VariantCopy(& pCustData->prgCustData[i].varValue,
5371 & pCData->data);
5373 }else{
5374 ERR(" OUT OF MEMORY! \n");
5375 return E_OUTOFMEMORY;
5377 return S_OK;
5379 return TYPE_E_ELEMENTNOTFOUND;
5382 /* ITypeInfo2::GetAllParamCustData
5384 * Gets all custom data items for the Functions
5387 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5388 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5390 ICOM_THIS( ITypeInfoImpl, iface);
5391 TLBCustData *pCData=NULL;
5392 TLBFuncDesc * pFDesc;
5393 int i;
5394 TRACE("(%p) index %d\n", This, indexFunc);
5395 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5396 pFDesc=pFDesc->next)
5398 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5399 pCustData->prgCustData =
5400 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5401 sizeof(CUSTDATAITEM));
5402 if(pCustData->prgCustData ){
5403 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5404 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5405 pCData; i++, pCData = pCData->next){
5406 pCustData->prgCustData[i].guid=pCData->guid;
5407 VariantCopy(& pCustData->prgCustData[i].varValue,
5408 & pCData->data);
5410 }else{
5411 ERR(" OUT OF MEMORY! \n");
5412 return E_OUTOFMEMORY;
5414 return S_OK;
5416 return TYPE_E_ELEMENTNOTFOUND;
5419 /* ITypeInfo2::GetAllVarCustData
5421 * Gets all custom data items for the specified Variable
5424 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5425 UINT index, CUSTDATA *pCustData)
5427 ICOM_THIS( ITypeInfoImpl, iface);
5428 TLBCustData *pCData;
5429 TLBVarDesc * pVDesc;
5430 int i;
5431 TRACE("(%p) index %d\n", This, index);
5432 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5433 pVDesc=pVDesc->next)
5435 if(pVDesc){
5436 pCustData->prgCustData =
5437 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5438 if(pCustData->prgCustData ){
5439 pCustData->cCustData=pVDesc->ctCustData;
5440 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5441 pCData = pCData->next){
5442 pCustData->prgCustData[i].guid=pCData->guid;
5443 VariantCopy(& pCustData->prgCustData[i].varValue,
5444 & pCData->data);
5446 }else{
5447 ERR(" OUT OF MEMORY! \n");
5448 return E_OUTOFMEMORY;
5450 return S_OK;
5452 return TYPE_E_ELEMENTNOTFOUND;
5455 /* ITypeInfo2::GetAllImplCustData
5457 * Gets all custom data items for the specified implementation type
5460 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5461 ITypeInfo2 * iface,
5462 UINT index,
5463 CUSTDATA *pCustData)
5465 ICOM_THIS( ITypeInfoImpl, iface);
5466 TLBCustData *pCData;
5467 TLBImplType * pRDesc;
5468 int i;
5469 TRACE("(%p) index %d\n", This, index);
5470 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5471 pRDesc=pRDesc->next)
5473 if(pRDesc){
5474 pCustData->prgCustData =
5475 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5476 if(pCustData->prgCustData ){
5477 pCustData->cCustData=pRDesc->ctCustData;
5478 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5479 pCData = pCData->next){
5480 pCustData->prgCustData[i].guid=pCData->guid;
5481 VariantCopy(& pCustData->prgCustData[i].varValue,
5482 & pCData->data);
5484 }else{
5485 ERR(" OUT OF MEMORY! \n");
5486 return E_OUTOFMEMORY;
5488 return S_OK;
5490 return TYPE_E_ELEMENTNOTFOUND;
5493 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5495 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5497 ITypeInfo_fnQueryInterface,
5498 ITypeInfo_fnAddRef,
5499 ITypeInfo_fnRelease,
5501 ITypeInfo_fnGetTypeAttr,
5502 ITypeInfo_fnGetTypeComp,
5503 ITypeInfo_fnGetFuncDesc,
5504 ITypeInfo_fnGetVarDesc,
5505 ITypeInfo_fnGetNames,
5506 ITypeInfo_fnGetRefTypeOfImplType,
5507 ITypeInfo_fnGetImplTypeFlags,
5508 ITypeInfo_fnGetIDsOfNames,
5509 ITypeInfo_fnInvoke,
5510 ITypeInfo_fnGetDocumentation,
5511 ITypeInfo_fnGetDllEntry,
5512 ITypeInfo_fnGetRefTypeInfo,
5513 ITypeInfo_fnAddressOfMember,
5514 ITypeInfo_fnCreateInstance,
5515 ITypeInfo_fnGetMops,
5516 ITypeInfo_fnGetContainingTypeLib,
5517 ITypeInfo_fnReleaseTypeAttr,
5518 ITypeInfo_fnReleaseFuncDesc,
5519 ITypeInfo_fnReleaseVarDesc,
5521 ITypeInfo2_fnGetTypeKind,
5522 ITypeInfo2_fnGetTypeFlags,
5523 ITypeInfo2_fnGetFuncIndexOfMemId,
5524 ITypeInfo2_fnGetVarIndexOfMemId,
5525 ITypeInfo2_fnGetCustData,
5526 ITypeInfo2_fnGetFuncCustData,
5527 ITypeInfo2_fnGetParamCustData,
5528 ITypeInfo2_fnGetVarCustData,
5529 ITypeInfo2_fnGetImplTypeCustData,
5530 ITypeInfo2_fnGetDocumentation2,
5531 ITypeInfo2_fnGetAllCustData,
5532 ITypeInfo2_fnGetAllFuncCustData,
5533 ITypeInfo2_fnGetAllParamCustData,
5534 ITypeInfo2_fnGetAllVarCustData,
5535 ITypeInfo2_fnGetAllImplTypeCustData,
5538 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5540 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5542 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5545 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5547 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5549 return ITypeInfo_AddRef((ITypeInfo *)This);
5552 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5554 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5556 return ITypeInfo_Release((ITypeInfo *)This);
5559 static HRESULT WINAPI ITypeComp_fnBind(
5560 ITypeComp * iface,
5561 OLECHAR * szName,
5562 unsigned long lHash,
5563 unsigned short wFlags,
5564 ITypeInfo ** ppTInfo,
5565 DESCKIND * pDescKind,
5566 BINDPTR * pBindPtr)
5568 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5569 TLBFuncDesc * pFDesc;
5570 TLBVarDesc * pVDesc;
5572 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5574 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5575 if (pFDesc->funcdesc.invkind & wFlags)
5576 if (!strcmpW(pFDesc->Name, szName)) {
5577 break;
5580 if (pFDesc)
5582 *pDescKind = DESCKIND_FUNCDESC;
5583 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5584 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5585 return S_OK;
5586 } else {
5587 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5589 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5590 if (!strcmpW(pVDesc->Name, szName)) {
5591 *pDescKind = DESCKIND_VARDESC;
5592 pBindPtr->lpvardesc = &pVDesc->vardesc;
5593 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5594 return S_OK;
5599 /* not found, look for it in inherited interfaces */
5600 if ((This->TypeAttr.typekind == TKIND_INTERFACE) && This->TypeAttr.cImplTypes) {
5601 /* recursive search */
5602 ITypeInfo *pTInfo;
5603 ITypeComp *pTComp;
5604 HRESULT hr;
5605 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5606 if (SUCCEEDED(hr))
5608 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5609 ITypeInfo_Release(pTInfo);
5611 if (SUCCEEDED(hr))
5613 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5614 ITypeComp_Release(pTComp);
5615 return hr;
5617 WARN("Could not search inherited interface!\n");
5619 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5620 *pDescKind = DESCKIND_NONE;
5621 pBindPtr->lpfuncdesc = NULL;
5622 *ppTInfo = NULL;
5623 return DISP_E_MEMBERNOTFOUND;
5626 static HRESULT WINAPI ITypeComp_fnBindType(
5627 ITypeComp * iface,
5628 OLECHAR * szName,
5629 unsigned long lHash,
5630 ITypeInfo ** ppTInfo,
5631 ITypeComp ** ppTComp)
5633 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5635 /* strange behaviour (does nothing) but like the
5636 * original */
5638 if (!ppTInfo || !ppTComp)
5639 return E_POINTER;
5641 *ppTInfo = NULL;
5642 *ppTComp = NULL;
5644 return S_OK;
5647 static ICOM_VTABLE(ITypeComp) tcompvt =
5649 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5651 ITypeComp_fnQueryInterface,
5652 ITypeComp_fnAddRef,
5653 ITypeComp_fnRelease,
5655 ITypeComp_fnBind,
5656 ITypeComp_fnBindType