Added server_abort_thread to replace SYSDEPS_AbortThread.
[wine/hacks.git] / dlls / oleaut32 / typelib.c
blobe5b4049e20de8146a65632af0465a8f58f0732e7
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_UI1: sprintf(szVarType, "VT_UI"); break;
814 case VT_I2: sprintf(szVarType, "VT_I2"); break;
815 case VT_I4: sprintf(szVarType, "VT_I4"); break;
816 case VT_R4: sprintf(szVarType, "VT_R4"); break;
817 case VT_R8: sprintf(szVarType, "VT_R8"); break;
818 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
819 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
820 case VT_CY: sprintf(szVarType, "VT_CY"); break;
821 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
822 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
823 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
824 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
825 case VT_I1: sprintf(szVarType, "VT_I1"); break;
826 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
827 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
828 case VT_INT: sprintf(szVarType, "VT_INT"); break;
829 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
830 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
831 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
832 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
833 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
837 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
838 if (pTD->vt & VT_RESERVED)
839 szVarType += strlen(strcpy(szVarType, "reserved | "));
840 if (pTD->vt & VT_BYREF)
841 szVarType += strlen(strcpy(szVarType, "ref to "));
842 if (pTD->vt & VT_ARRAY)
843 szVarType += strlen(strcpy(szVarType, "array of "));
844 if (pTD->vt & VT_VECTOR)
845 szVarType += strlen(strcpy(szVarType, "vector of "));
846 switch(pTD->vt & VT_TYPEMASK) {
847 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
848 case VT_I2: sprintf(szVarType, "VT_I2"); break;
849 case VT_I4: sprintf(szVarType, "VT_I4"); break;
850 case VT_R4: sprintf(szVarType, "VT_R4"); break;
851 case VT_R8: sprintf(szVarType, "VT_R8"); break;
852 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
853 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
854 case VT_CY: sprintf(szVarType, "VT_CY"); break;
855 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
856 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
857 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
858 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
859 case VT_I1: sprintf(szVarType, "VT_I1"); break;
860 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
861 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
862 case VT_INT: sprintf(szVarType, "VT_INT"); break;
863 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
864 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
865 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
866 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
867 pTD->u.hreftype); break;
868 case VT_PTR: sprintf(szVarType, "ptr to ");
869 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
870 break;
871 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
872 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
873 break;
874 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
875 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
876 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
877 break;
879 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
883 void dump_ELEMDESC(ELEMDESC *edesc) {
884 char buf[200];
885 dump_TypeDesc(&edesc->tdesc,buf);
886 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
887 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
888 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
890 void dump_FUNCDESC(FUNCDESC *funcdesc) {
891 int i;
892 MESSAGE("memid is %08lx\n",funcdesc->memid);
893 for (i=0;i<funcdesc->cParams;i++) {
894 MESSAGE("Param %d:\n",i);
895 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
897 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
898 switch (funcdesc->funckind) {
899 case FUNC_VIRTUAL: MESSAGE("virtual");break;
900 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
901 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
902 case FUNC_STATIC: MESSAGE("static");break;
903 case FUNC_DISPATCH: MESSAGE("dispatch");break;
904 default: MESSAGE("unknown");break;
906 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
907 switch (funcdesc->invkind) {
908 case INVOKE_FUNC: MESSAGE("func");break;
909 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
910 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
911 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
913 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
914 switch (funcdesc->callconv) {
915 case CC_CDECL: MESSAGE("cdecl");break;
916 case CC_PASCAL: MESSAGE("pascal");break;
917 case CC_STDCALL: MESSAGE("stdcall");break;
918 case CC_SYSCALL: MESSAGE("syscall");break;
919 default:break;
921 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
922 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
923 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
926 void dump_IDLDESC(IDLDESC *idl) {
927 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
930 static const char * typekind_desc[] =
932 "TKIND_ENUM",
933 "TKIND_RECORD",
934 "TKIND_MODULE",
935 "TKIND_INTERFACE",
936 "TKIND_DISPATCH",
937 "TKIND_COCLASS",
938 "TKIND_ALIAS",
939 "TKIND_UNION",
940 "TKIND_MAX"
943 void dump_TYPEATTR(TYPEATTR *tattr) {
944 char buf[200];
945 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
946 MESSAGE("\tlcid: %ld\n",tattr->lcid);
947 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
948 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
949 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
950 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
951 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
952 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
953 MESSAGE("\tcVars: %d\n", tattr->cVars);
954 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
955 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
956 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
957 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
958 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
959 dump_TypeDesc(&tattr->tdescAlias,buf);
960 MESSAGE("\ttypedesc: %s\n", buf);
961 dump_IDLDESC(&tattr->idldescType);
964 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
966 int i;
967 if (!TRACE_ON(typelib))
968 return;
969 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
970 for (i=0;i<pfd->funcdesc.cParams;i++)
971 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
974 dump_FUNCDESC(&(pfd->funcdesc));
976 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
977 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
979 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
981 while (pfd)
983 dump_TLBFuncDescOne(pfd);
984 pfd = pfd->next;
987 static void dump_TLBVarDesc(TLBVarDesc * pvd)
989 while (pvd)
991 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
992 pvd = pvd->next;
996 static void dump_TLBImpLib(TLBImpLib *import)
998 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
999 debugstr_w(import->name));
1000 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1001 import->wVersionMinor, import->lcid, import->offset);
1004 static void dump_TLBRefType(TLBRefType * prt)
1006 while (prt)
1008 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1009 if(prt->index == -1)
1010 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1011 else
1012 TRACE_(typelib)("type no: %d\n", prt->index);
1014 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1015 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1016 TRACE_(typelib)("in lib\n");
1017 dump_TLBImpLib(prt->pImpTLInfo);
1019 prt = prt->next;
1023 static void dump_TLBImplType(TLBImplType * impl)
1025 while (impl) {
1026 TRACE_(typelib)(
1027 "implementing/inheriting interface hRef = %lx implflags %x\n",
1028 impl->hRef, impl->implflags);
1029 impl = impl->next;
1033 void dump_Variant(VARIANT * pvar)
1035 char szVarType[32];
1036 LPVOID ref;
1038 TRACE("(%p)\n", pvar);
1040 if (!pvar) return;
1042 ZeroMemory(szVarType, sizeof(szVarType));
1044 /* FIXME : we could have better trace here, depending on the VARTYPE
1045 * of the variant
1047 dump_VarType(V_VT(pvar),szVarType);
1049 TRACE("VARTYPE: %s\n", szVarType);
1051 if (V_VT(pvar) & VT_BYREF) {
1052 ref = V_UNION(pvar, byref);
1053 TRACE("%p\n", ref);
1055 else ref = &V_UNION(pvar, cVal);
1057 if (V_VT(pvar) & VT_ARRAY) {
1058 /* FIXME */
1059 return;
1061 if (V_VT(pvar) & VT_VECTOR) {
1062 /* FIXME */
1063 return;
1066 switch (V_VT(pvar) & VT_TYPEMASK)
1068 case VT_I2:
1069 TRACE("%d\n", *(short*)ref);
1070 break;
1072 case VT_UI4:
1073 case VT_UINT:
1074 TRACE("%u\n", *(UINT*)ref);
1075 break;
1077 case VT_I4:
1078 case VT_INT:
1079 TRACE("%d\n", *(INT*)ref);
1080 break;
1082 case VT_R4:
1083 TRACE("%3.3e\n", *(float*)ref);
1084 break;
1086 case VT_R8:
1087 TRACE("%3.3e\n", *(double*)ref);
1088 break;
1090 case VT_BOOL:
1091 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1092 break;
1094 case VT_BSTR:
1095 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1096 break;
1098 case VT_UNKNOWN:
1099 case VT_DISPATCH:
1100 TRACE("%p\n", *(LPVOID*)ref);
1101 break;
1103 case VT_VARIANT:
1104 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1105 break;
1107 case VT_DATE:
1109 struct tm TM;
1110 memset( &TM, 0, sizeof(TM) );
1112 if( DateToTm( *(DATE*)ref, 0, &TM ) == FALSE ) {
1113 TRACE("invalid date? (?)%ld %f\n", *(long*)ref, *(double *)ref);
1114 } else {
1115 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1116 TM.tm_year, TM.tm_mon+1, TM.tm_mday,
1117 TM.tm_hour, TM.tm_min, TM.tm_sec, *(double *)ref);
1119 break;
1122 case VT_CY:
1123 TRACE("%ld (hi), %lu (lo)\n", ((CY *)ref)->s.Hi, ((CY *)ref)->s.Lo);
1124 break;
1127 default:
1128 TRACE("(?)%ld\n", *(long*)ref);
1129 break;
1133 static void dump_DispParms(DISPPARAMS * pdp)
1135 int index = 0;
1137 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1139 while (index < pdp->cArgs)
1141 dump_Variant( &pdp->rgvarg[index] );
1142 ++index;
1146 static void dump_TypeInfo(ITypeInfoImpl * pty)
1148 TRACE("%p ref=%u\n", pty, pty->ref);
1149 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1150 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1151 TRACE("fct:%u var:%u impl:%u\n",
1152 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1153 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1154 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1155 dump_TLBFuncDesc(pty->funclist);
1156 dump_TLBVarDesc(pty->varlist);
1157 dump_TLBImplType(pty->impltypelist);
1160 void dump_VARDESC(VARDESC *v)
1162 MESSAGE("memid %ld\n",v->memid);
1163 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1164 MESSAGE("oInst %ld\n",v->u.oInst);
1165 dump_ELEMDESC(&(v->elemdescVar));
1166 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1167 MESSAGE("varkind %d\n",v->varkind);
1170 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1172 /* VT_LPWSTR is largest type that */
1173 /* may appear in type description*/
1174 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1175 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1176 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1177 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1178 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1179 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1180 {{0},30},{{0},31}
1183 static void TLB_abort()
1185 DebugBreak();
1187 static void * TLB_Alloc(unsigned size)
1189 void * ret;
1190 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1191 /* FIXME */
1192 ERR("cannot allocate memory\n");
1194 return ret;
1197 static void TLB_Free(void * ptr)
1199 HeapFree(GetProcessHeap(), 0, ptr);
1203 /**********************************************************************
1205 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1207 /* read function */
1208 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1210 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1211 pcx->pos, count, pcx->oStart, pcx->length, where);
1213 if (where != DO_NOT_SEEK)
1215 where += pcx->oStart;
1216 if (where > pcx->length)
1218 /* FIXME */
1219 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1220 TLB_abort();
1222 pcx->pos = where;
1224 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1225 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1226 pcx->pos += count;
1227 return count;
1230 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1231 long where )
1233 DWORD ret;
1235 ret = MSFT_Read(buffer, count, pcx, where);
1236 FromLEDWords(buffer, ret);
1238 return ret;
1241 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1242 long where )
1244 DWORD ret;
1246 ret = MSFT_Read(buffer, count, pcx, where);
1247 FromLEWords(buffer, ret);
1249 return ret;
1252 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1254 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1255 memset(pGuid,0, sizeof(GUID));
1256 return;
1258 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1259 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1260 pGuid->Data2 = FromLEWord(pGuid->Data2);
1261 pGuid->Data3 = FromLEWord(pGuid->Data3);
1262 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1265 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1267 char * name;
1268 MSFT_NameIntro niName;
1269 int lengthInChars;
1270 WCHAR* pwstring = NULL;
1271 BSTR bstrName = NULL;
1273 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1274 pcx->pTblDir->pNametab.offset+offset);
1275 niName.namelen &= 0xFF; /* FIXME: correct ? */
1276 name=TLB_Alloc((niName.namelen & 0xff) +1);
1277 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1278 name[niName.namelen & 0xff]='\0';
1280 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1281 name, -1, NULL, 0);
1283 /* no invalid characters in string */
1284 if (lengthInChars)
1286 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1288 /* don't check for invalid character since this has been done previously */
1289 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1291 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1292 lengthInChars = SysStringLen(bstrName);
1293 HeapFree(GetProcessHeap(), 0, pwstring);
1296 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1297 return bstrName;
1300 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1302 char * string;
1303 INT16 length;
1304 int lengthInChars;
1305 BSTR bstr = NULL;
1307 if(offset<0) return NULL;
1308 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1309 if(length <= 0) return 0;
1310 string=TLB_Alloc(length +1);
1311 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1312 string[length]='\0';
1314 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1315 string, -1, NULL, 0);
1317 /* no invalid characters in string */
1318 if (lengthInChars)
1320 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1322 /* don't check for invalid character since this has been done previously */
1323 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1325 bstr = SysAllocStringLen(pwstring, lengthInChars);
1326 lengthInChars = SysStringLen(bstr);
1327 HeapFree(GetProcessHeap(), 0, pwstring);
1330 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1331 return bstr;
1334 * read a value and fill a VARIANT structure
1336 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1338 int size;
1340 TRACE_(typelib)("\n");
1342 if(offset <0) { /* data are packed in here */
1343 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1344 V_UNION(pVar, iVal) = offset & 0xffff;
1345 return;
1347 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1348 pcx->pTblDir->pCustData.offset + offset );
1349 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1350 switch (V_VT(pVar)){
1351 case VT_EMPTY: /* FIXME: is this right? */
1352 case VT_NULL: /* FIXME: is this right? */
1353 case VT_I2 : /* this should not happen */
1354 case VT_I4 :
1355 case VT_R4 :
1356 case VT_ERROR :
1357 case VT_BOOL :
1358 case VT_I1 :
1359 case VT_UI1 :
1360 case VT_UI2 :
1361 case VT_UI4 :
1362 case VT_INT :
1363 case VT_UINT :
1364 case VT_VOID : /* FIXME: is this right? */
1365 case VT_HRESULT :
1366 size=4; break;
1367 case VT_R8 :
1368 case VT_CY :
1369 case VT_DATE :
1370 case VT_I8 :
1371 case VT_UI8 :
1372 case VT_DECIMAL : /* FIXME: is this right? */
1373 case VT_FILETIME :
1374 size=8;break;
1375 /* pointer types with known behaviour */
1376 case VT_BSTR :{
1377 char * ptr;
1378 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1379 if(size <= 0) {
1380 FIXME("BSTR length = %d?\n", size);
1381 } else {
1382 ptr=TLB_Alloc(size);/* allocate temp buffer */
1383 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1384 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1385 /* FIXME: do we need a AtoW conversion here? */
1386 V_UNION(pVar, bstrVal[size])=L'\0';
1387 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1388 TLB_Free(ptr);
1391 size=-4; break;
1392 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1393 case VT_DISPATCH :
1394 case VT_VARIANT :
1395 case VT_UNKNOWN :
1396 case VT_PTR :
1397 case VT_SAFEARRAY :
1398 case VT_CARRAY :
1399 case VT_USERDEFINED :
1400 case VT_LPSTR :
1401 case VT_LPWSTR :
1402 case VT_BLOB :
1403 case VT_STREAM :
1404 case VT_STORAGE :
1405 case VT_STREAMED_OBJECT :
1406 case VT_STORED_OBJECT :
1407 case VT_BLOB_OBJECT :
1408 case VT_CF :
1409 case VT_CLSID :
1410 default:
1411 size=0;
1412 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1413 V_VT(pVar));
1416 if(size>0) /* (big|small) endian correct? */
1417 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1418 return;
1421 * create a linked list with custom data
1423 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1425 MSFT_CDGuid entry;
1426 TLBCustData* pNew;
1427 int count=0;
1429 TRACE_(typelib)("\n");
1431 while(offset >=0){
1432 count++;
1433 pNew=TLB_Alloc(sizeof(TLBCustData));
1434 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1435 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1436 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1437 /* add new custom data at head of the list */
1438 pNew->next=*ppCustData;
1439 *ppCustData=pNew;
1440 offset = entry.next;
1442 return count;
1445 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1446 ITypeInfoImpl *pTI)
1448 if(type <0)
1449 pTd->vt=type & VT_TYPEMASK;
1450 else
1451 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1453 if(pTd->vt == VT_USERDEFINED)
1454 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1456 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1459 static void
1460 MSFT_DoFuncs(TLBContext* pcx,
1461 ITypeInfoImpl* pTI,
1462 int cFuncs,
1463 int cVars,
1464 int offset,
1465 TLBFuncDesc** pptfd)
1468 * member information is stored in a data structure at offset
1469 * indicated by the memoffset field of the typeinfo structure
1470 * There are several distinctive parts.
1471 * the first part starts with a field that holds the total length
1472 * of this (first) part excluding this field. Then follow the records,
1473 * for each member there is one record.
1475 * First entry is always the length of the record (excluding this
1476 * length word).
1477 * Rest of the record depends on the type of the member. If there is
1478 * a field indicating the member type (function variable intereface etc)
1479 * I have not found it yet. At this time we depend on the information
1480 * in the type info and the usual order how things are stored.
1482 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1483 * for each member;
1485 * Third is a equal sized array with file offsets to the name entry
1486 * of each member.
1488 * Forth and last (?) part is an array with offsets to the records in the
1489 * first part of this file segment.
1492 int infolen, nameoffset, reclength, nrattributes, i;
1493 int recoffset = offset + sizeof(INT);
1495 char recbuf[512];
1496 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1498 TRACE_(typelib)("\n");
1500 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1502 for ( i = 0; i < cFuncs ; i++ )
1504 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1506 /* name, eventually add to a hash table */
1507 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1508 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1510 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1512 /* read the function information record */
1513 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1515 reclength &= 0x1ff;
1517 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1519 /* do the attributes */
1520 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1521 / sizeof(int);
1523 if ( nrattributes > 0 )
1525 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1527 if ( nrattributes > 1 )
1529 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1530 pFuncRec->OptAttr[1]) ;
1532 if ( nrattributes > 2 )
1534 if ( pFuncRec->FKCCIC & 0x2000 )
1536 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1538 else
1540 (*pptfd)->Entry = MSFT_ReadString(pcx,
1541 pFuncRec->OptAttr[2]);
1543 if( nrattributes > 5 )
1545 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1547 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1549 MSFT_CustData(pcx,
1550 pFuncRec->OptAttr[6],
1551 &(*pptfd)->pCustData);
1558 /* fill the FuncDesc Structure */
1559 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1560 offset + infolen + ( i + 1) * sizeof(INT));
1562 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1563 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1564 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1565 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1566 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1567 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1568 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1570 MSFT_GetTdesc(pcx,
1571 pFuncRec->DataType,
1572 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1573 pTI);
1575 /* do the parameters/arguments */
1576 if(pFuncRec->nrargs)
1578 int j = 0;
1579 MSFT_ParameterInfo paraminfo;
1581 (*pptfd)->funcdesc.lprgelemdescParam =
1582 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1584 (*pptfd)->pParamDesc =
1585 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1587 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1588 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1590 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1592 TYPEDESC* lpArgTypeDesc = 0;
1594 MSFT_GetTdesc(pcx,
1595 paraminfo.DataType,
1596 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1597 pTI);
1599 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1601 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1603 /* SEEK value = jump to offset,
1604 * from there jump to the end of record,
1605 * go back by (j-1) arguments
1607 MSFT_ReadLEDWords( &paraminfo ,
1608 sizeof(MSFT_ParameterInfo), pcx,
1609 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1610 * sizeof(MSFT_ParameterInfo)));
1611 lpArgTypeDesc =
1612 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1614 while ( lpArgTypeDesc != NULL )
1616 switch ( lpArgTypeDesc->vt )
1618 case VT_PTR:
1619 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1620 break;
1622 case VT_CARRAY:
1623 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1624 break;
1626 case VT_USERDEFINED:
1627 MSFT_DoRefType(pcx, pTI,
1628 lpArgTypeDesc->u.hreftype);
1630 lpArgTypeDesc = NULL;
1631 break;
1633 default:
1634 lpArgTypeDesc = NULL;
1640 /* parameter is the return value! */
1641 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1643 TYPEDESC* lpArgTypeDesc;
1645 (*pptfd)->funcdesc.elemdescFunc =
1646 (*pptfd)->funcdesc.lprgelemdescParam[j];
1648 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1650 while ( lpArgTypeDesc != NULL )
1652 switch ( lpArgTypeDesc->vt )
1654 case VT_PTR:
1655 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1656 break;
1657 case VT_CARRAY:
1658 lpArgTypeDesc =
1659 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1661 break;
1663 case VT_USERDEFINED:
1664 MSFT_DoRefType(pcx,
1665 pTI,
1666 lpArgTypeDesc->u.hreftype);
1668 lpArgTypeDesc = NULL;
1669 break;
1671 default:
1672 lpArgTypeDesc = NULL;
1677 /* second time around */
1678 for(j=0;j<pFuncRec->nrargs;j++)
1680 /* name */
1681 (*pptfd)->pParamDesc[j].Name =
1682 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1684 /* default value */
1685 if ( (PARAMFLAG_FHASDEFAULT &
1686 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1687 ((pFuncRec->FKCCIC) & 0x1000) )
1689 INT* pInt = (INT *)((char *)pFuncRec +
1690 reclength -
1691 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1693 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1695 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1696 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1698 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1699 pInt[j], pcx);
1701 /* custom info */
1702 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1704 MSFT_CustData(pcx,
1705 pFuncRec->OptAttr[7+j],
1706 &(*pptfd)->pParamDesc[j].pCustData);
1711 /* scode is not used: archaic win16 stuff FIXME: right? */
1712 (*pptfd)->funcdesc.cScodes = 0 ;
1713 (*pptfd)->funcdesc.lprgscode = NULL ;
1715 pptfd = & ((*pptfd)->next);
1716 recoffset += reclength;
1720 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1721 int cVars, int offset, TLBVarDesc ** pptvd)
1723 int infolen, nameoffset, reclength;
1724 char recbuf[256];
1725 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1726 int i;
1727 int recoffset;
1729 TRACE_(typelib)("\n");
1731 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1732 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1733 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1734 recoffset += offset+sizeof(INT);
1735 for(i=0;i<cVars;i++){
1736 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1737 /* name, eventually add to a hash table */
1738 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1739 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1740 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1741 /* read the variable information record */
1742 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1743 reclength &=0xff;
1744 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1745 /* Optional data */
1746 if(reclength >(6*sizeof(INT)) )
1747 (*pptvd)->HelpContext=pVarRec->HelpContext;
1748 if(reclength >(7*sizeof(INT)) )
1749 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1750 if(reclength >(8*sizeof(INT)) )
1751 if(reclength >(9*sizeof(INT)) )
1752 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1753 /* fill the VarDesc Structure */
1754 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1755 offset + infolen + ( i + 1) * sizeof(INT));
1756 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1757 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1758 MSFT_GetTdesc(pcx, pVarRec->DataType,
1759 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1760 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1761 if(pVarRec->VarKind == VAR_CONST ){
1762 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1763 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1764 pVarRec->OffsValue, pcx);
1765 } else
1766 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1767 pptvd=&((*pptvd)->next);
1768 recoffset += reclength;
1771 /* fill in data for a hreftype (offset). When the refernced type is contained
1772 * in the typelib, it's just an (file) offset in the type info base dir.
1773 * If comes from import, it's an offset+1 in the ImpInfo table
1774 * */
1775 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1776 int offset)
1778 int j;
1779 TLBRefType **ppRefType = &pTI->reflist;
1781 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1783 while(*ppRefType) {
1784 if((*ppRefType)->reference == offset)
1785 return;
1786 ppRefType = &(*ppRefType)->next;
1789 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1790 sizeof(**ppRefType));
1792 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1793 /* external typelib */
1794 MSFT_ImpInfo impinfo;
1795 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1797 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1799 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1800 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1801 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1802 if(pImpLib->offset==impinfo.oImpFile) break;
1803 pImpLib=pImpLib->next;
1805 if(pImpLib){
1806 (*ppRefType)->reference=offset;
1807 (*ppRefType)->pImpTLInfo = pImpLib;
1808 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1809 (*ppRefType)->index = TLB_REF_USE_GUID;
1810 }else{
1811 ERR("Cannot find a reference\n");
1812 (*ppRefType)->reference=-1;
1813 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1815 }else{
1816 /* in this typelib */
1817 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1818 (*ppRefType)->reference=offset;
1819 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1823 /* process Implemented Interfaces of a com class */
1824 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1825 int offset)
1827 int i;
1828 MSFT_RefRecord refrec;
1829 TLBImplType **ppImpl = &pTI->impltypelist;
1831 TRACE_(typelib)("\n");
1833 for(i=0;i<count;i++){
1834 if(offset<0) break; /* paranoia */
1835 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1836 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1837 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1838 (*ppImpl)->hRef = refrec.reftype;
1839 (*ppImpl)->implflags=refrec.flags;
1840 (*ppImpl)->ctCustData=
1841 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1842 offset=refrec.onext;
1843 ppImpl=&((*ppImpl)->next);
1847 * process a typeinfo record
1849 ITypeInfoImpl * MSFT_DoTypeInfo(
1850 TLBContext *pcx,
1851 int count,
1852 ITypeLibImpl * pLibInfo)
1854 MSFT_TypeInfoBase tiBase;
1855 ITypeInfoImpl *ptiRet;
1857 TRACE_(typelib)("count=%u\n", count);
1859 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1860 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
1861 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1862 /* this is where we are coming from */
1863 ptiRet->pTypeLib = pLibInfo;
1864 ptiRet->index=count;
1865 /* fill in the typeattr fields */
1866 WARN("Assign constructor/destructor memid\n");
1868 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1869 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1870 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1871 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1872 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1873 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1874 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1875 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1876 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1877 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1878 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1879 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1880 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1881 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1882 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1883 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1884 MSFT_GetTdesc(pcx, tiBase.datatype1,
1885 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1887 /* FIXME: */
1888 /* IDLDESC idldescType; *//* never saw this one != zero */
1890 /* name, eventually add to a hash table */
1891 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1892 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1893 /* help info */
1894 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1895 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1896 ptiRet->dwHelpContext=tiBase.helpcontext;
1897 /* note: InfoType's Help file and HelpStringDll come from the containing
1898 * library. Further HelpString and Docstring appear to be the same thing :(
1900 /* functions */
1901 if(ptiRet->TypeAttr.cFuncs >0 )
1902 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1903 ptiRet->TypeAttr.cVars,
1904 tiBase.memoffset, & ptiRet->funclist);
1905 /* variables */
1906 if(ptiRet->TypeAttr.cVars >0 )
1907 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1908 ptiRet->TypeAttr.cVars,
1909 tiBase.memoffset, & ptiRet->varlist);
1910 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1911 switch(ptiRet->TypeAttr.typekind)
1913 case TKIND_COCLASS:
1914 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1915 tiBase.datatype1);
1916 break;
1917 case TKIND_DISPATCH:
1918 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1920 if (tiBase.datatype1 != -1)
1922 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1923 ptiRet->impltypelist->hRef = tiBase.datatype1;
1925 else
1926 { /* FIXME: This is a really bad hack to add IDispatch */
1927 const char* szStdOle = "stdole2.tlb\0";
1928 int nStdOleLen = strlen(szStdOle);
1929 TLBRefType **ppRef = &ptiRet->reflist;
1931 while(*ppRef) {
1932 if((*ppRef)->reference == -1)
1933 break;
1934 ppRef = &(*ppRef)->next;
1936 if(!*ppRef) {
1937 *ppRef = TLB_Alloc(sizeof(**ppRef));
1938 (*ppRef)->guid = IID_IDispatch;
1939 (*ppRef)->reference = -1;
1940 (*ppRef)->index = TLB_REF_USE_GUID;
1941 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1942 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1943 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1944 nStdOleLen + 1);
1946 MultiByteToWideChar(CP_ACP,
1947 MB_PRECOMPOSED,
1948 szStdOle,
1950 (*ppRef)->pImpTLInfo->name,
1951 SysStringLen((*ppRef)->pImpTLInfo->name));
1953 (*ppRef)->pImpTLInfo->lcid = 0;
1954 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1955 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1958 break;
1959 default:
1960 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1961 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1962 ptiRet->impltypelist->hRef = tiBase.datatype1;
1963 break;
1966 ptiRet->ctCustData=
1967 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1969 TRACE_(typelib)("%s guid: %s kind:%s\n",
1970 debugstr_w(ptiRet->Name),
1971 debugstr_guid(&ptiRet->TypeAttr.guid),
1972 typekind_desc[ptiRet->TypeAttr.typekind]);
1974 return ptiRet;
1977 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
1978 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
1979 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
1980 * tradeoff here.
1982 static ITypeLibImpl *tlb_cache_first;
1983 static CRITICAL_SECTION cache_section;
1984 static CRITICAL_SECTION_DEBUG cache_section_debug =
1986 0, 0, &cache_section,
1987 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
1988 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
1990 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
1993 /****************************************************************************
1994 * TLB_ReadTypeLib
1996 * find the type of the typelib file and map the typelib resource into
1997 * the memory
1999 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2000 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2001 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2003 ITypeLibImpl *entry;
2004 int ret = TYPE_E_CANTLOADLIBRARY;
2005 DWORD dwSignature = 0;
2006 HANDLE hFile;
2008 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2010 *ppTypeLib = NULL;
2012 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2013 EnterCriticalSection(&cache_section);
2014 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2016 if (!strcmpiW(entry->path, pszFileName))
2018 TRACE("cache hit\n");
2019 *ppTypeLib = (ITypeLib2*)entry;
2020 ITypeLib_AddRef(*ppTypeLib);
2021 LeaveCriticalSection(&cache_section);
2022 return S_OK;
2025 LeaveCriticalSection(&cache_section);
2027 /* check the signature of the file */
2028 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2029 if (INVALID_HANDLE_VALUE != hFile)
2031 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2032 if (hMapping)
2034 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2035 if(pBase)
2037 /* retrieve file size */
2038 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2040 /* first try to load as *.tlb */
2041 dwSignature = FromLEDWord(*((DWORD*) pBase));
2042 if ( dwSignature == MSFT_SIGNATURE)
2044 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2046 else if ( dwSignature == SLTG_SIGNATURE)
2048 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2050 UnmapViewOfFile(pBase);
2052 CloseHandle(hMapping);
2054 CloseHandle(hFile);
2057 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2059 /* find the typelibrary resource*/
2060 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2061 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2062 if (hinstDLL)
2064 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2065 "TYPELIB");
2066 if (hrsrc)
2068 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2069 if (hGlobal)
2071 LPVOID pBase = LockResource(hGlobal);
2072 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2074 if (pBase)
2076 /* try to load as incore resource */
2077 dwSignature = FromLEDWord(*((DWORD*) pBase));
2078 if ( dwSignature == MSFT_SIGNATURE)
2080 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2082 else if ( dwSignature == SLTG_SIGNATURE)
2084 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2086 else
2088 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2091 FreeResource( hGlobal );
2094 FreeLibrary(hinstDLL);
2098 if(*ppTypeLib) {
2099 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2101 TRACE("adding to cache\n");
2102 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2103 lstrcpyW(impl->path, pszFileName);
2104 /* We should really canonicalise the path here. */
2106 /* FIXME: check if it has added already in the meantime */
2107 EnterCriticalSection(&cache_section);
2108 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2109 impl->prev = NULL;
2110 tlb_cache_first = impl;
2111 LeaveCriticalSection(&cache_section);
2112 ret = S_OK;
2113 } else
2114 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2116 return ret;
2119 /*================== ITypeLib(2) Methods ===================================*/
2121 /****************************************************************************
2122 * ITypeLib2_Constructor_MSFT
2124 * loading an MSFT typelib from an in-memory image
2126 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2128 TLBContext cx;
2129 long lPSegDir;
2130 MSFT_Header tlbHeader;
2131 MSFT_SegDir tlbSegDir;
2132 ITypeLibImpl * pTypeLibImpl;
2134 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2136 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2137 if (!pTypeLibImpl) return NULL;
2139 pTypeLibImpl->lpVtbl = &tlbvt;
2140 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2141 pTypeLibImpl->ref = 1;
2143 /* get pointer to beginning of typelib data */
2144 cx.pos = 0;
2145 cx.oStart=0;
2146 cx.mapping = pLib;
2147 cx.pLibInfo = pTypeLibImpl;
2148 cx.length = dwTLBLength;
2150 /* read header */
2151 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2152 TRACE("header:\n");
2153 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2154 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2155 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2156 return NULL;
2158 /* there is a small amount of information here until the next important
2159 * part:
2160 * the segment directory . Try to calculate the amount of data */
2161 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2163 /* now read the segment directory */
2164 TRACE("read segment directory (at %ld)\n",lPSegDir);
2165 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2166 cx.pTblDir = &tlbSegDir;
2168 /* just check two entries */
2169 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2171 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2172 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2173 return NULL;
2176 /* now fill our internal data */
2177 /* TLIBATTR fields */
2178 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2180 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2181 /* Windows seems to have zero here, is this correct? */
2182 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2183 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2184 else
2185 pTypeLibImpl->LibAttr.lcid = 0;
2187 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2188 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2189 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2190 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2192 /* name, eventually add to a hash table */
2193 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2195 /* help info */
2196 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2197 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2199 if( tlbHeader.varflags & HELPDLLFLAG)
2201 int offset;
2202 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2203 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2206 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2208 /* custom data */
2209 if(tlbHeader.CustomDataOffset >= 0)
2211 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2214 /* fill in typedescriptions */
2215 if(tlbSegDir.pTypdescTab.length > 0)
2217 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2218 INT16 td[4];
2219 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2220 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2221 for(i=0; i<cTD; )
2223 /* FIXME: add several sanity checks here */
2224 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2225 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2227 /* FIXME: check safearray */
2228 if(td[3] < 0)
2229 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2230 else
2231 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2233 else if(td[0] == VT_CARRAY)
2235 /* array descr table here */
2236 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2238 else if(td[0] == VT_USERDEFINED)
2240 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2242 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2245 /* second time around to fill the array subscript info */
2246 for(i=0;i<cTD;i++)
2248 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2249 if(tlbSegDir.pArrayDescriptions.offset>0)
2251 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2252 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2254 if(td[1]<0)
2255 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2256 else
2257 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2259 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2261 for(j = 0; j<td[2]; j++)
2263 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2264 sizeof(INT), &cx, DO_NOT_SEEK);
2265 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2266 sizeof(INT), &cx, DO_NOT_SEEK);
2269 else
2271 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2272 ERR("didn't find array description data\n");
2277 /* imported type libs */
2278 if(tlbSegDir.pImpFiles.offset>0)
2280 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2281 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2282 UINT16 size;
2284 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2286 char *name;
2287 DWORD len;
2289 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2290 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2291 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2293 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2294 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2295 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2296 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2298 size >>= 2;
2299 name = TLB_Alloc(size+1);
2300 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2301 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2302 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2303 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2304 TLB_Free(name);
2306 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2307 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2309 ppImpLib = &(*ppImpLib)->next;
2313 /* type info's */
2314 if(tlbHeader.nrtypeinfos >= 0 )
2316 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2317 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2318 int i;
2320 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2322 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2324 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2325 ppTI = &((*ppTI)->next);
2326 (pTypeLibImpl->TypeInfoCount)++;
2330 TRACE("(%p)\n", pTypeLibImpl);
2331 return (ITypeLib2*) pTypeLibImpl;
2335 static BSTR TLB_MultiByteToBSTR(char *ptr)
2337 DWORD len;
2338 WCHAR *nameW;
2339 BSTR ret;
2341 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2342 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2343 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2344 ret = SysAllocString(nameW);
2345 HeapFree(GetProcessHeap(), 0, nameW);
2346 return ret;
2349 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2351 char b[3];
2352 int i;
2353 short s;
2355 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2356 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2357 return FALSE;
2360 guid->Data4[0] = s >> 8;
2361 guid->Data4[1] = s & 0xff;
2363 b[2] = '\0';
2364 for(i = 0; i < 6; i++) {
2365 memcpy(b, str + 24 + 2 * i, 2);
2366 guid->Data4[i + 2] = strtol(b, NULL, 16);
2368 return TRUE;
2371 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2373 WORD bytelen;
2374 DWORD len;
2375 WCHAR *nameW;
2377 *pBstr = NULL;
2378 bytelen = *(WORD*)ptr;
2379 if(bytelen == 0xffff) return 2;
2380 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2381 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2382 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2383 *pBstr = SysAllocStringLen(nameW, len);
2384 HeapFree(GetProcessHeap(), 0, nameW);
2385 return bytelen + 2;
2388 static WORD SLTG_ReadStringA(char *ptr, char **str)
2390 WORD bytelen;
2392 *str = NULL;
2393 bytelen = *(WORD*)ptr;
2394 if(bytelen == 0xffff) return 2;
2395 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2396 memcpy(*str, ptr + 2, bytelen);
2397 (*str)[bytelen] = '\0';
2398 return bytelen + 2;
2401 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2403 char *ptr = pLibBlk;
2404 WORD w;
2406 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2407 FIXME("libblk magic = %04x\n", w);
2408 return 0;
2411 ptr += 6;
2412 if((w = *(WORD*)ptr) != 0xffff) {
2413 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2414 ptr += w;
2416 ptr += 2;
2418 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2420 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2422 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2423 ptr += 4;
2425 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2426 ptr += 2;
2428 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2429 ptr += 2;
2431 ptr += 4; /* skip res12 */
2433 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2434 ptr += 2;
2436 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2437 ptr += 2;
2439 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2440 ptr += 2;
2442 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2443 ptr += sizeof(GUID);
2445 return ptr - (char*)pLibBlk;
2448 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2450 BOOL done = FALSE;
2451 TYPEDESC *pTD = &pElem->tdesc;
2453 /* Handle [in/out] first */
2454 if((*pType & 0xc000) == 0xc000)
2455 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2456 else if(*pType & 0x8000)
2457 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2458 else if(*pType & 0x4000)
2459 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2460 else
2461 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2463 if(*pType & 0x2000)
2464 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2466 if(*pType & 0x80)
2467 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2469 while(!done) {
2470 if((*pType & 0xe00) == 0xe00) {
2471 pTD->vt = VT_PTR;
2472 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2473 sizeof(TYPEDESC));
2474 pTD = pTD->u.lptdesc;
2476 switch(*pType & 0x7f) {
2477 case VT_PTR:
2478 pTD->vt = VT_PTR;
2479 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2480 sizeof(TYPEDESC));
2481 pTD = pTD->u.lptdesc;
2482 break;
2484 case VT_USERDEFINED:
2485 pTD->vt = VT_USERDEFINED;
2486 pTD->u.hreftype = *(++pType) / 4;
2487 done = TRUE;
2488 break;
2490 case VT_CARRAY:
2492 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2493 array */
2495 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2497 pTD->vt = VT_CARRAY;
2498 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2499 sizeof(ARRAYDESC) +
2500 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2501 pTD->u.lpadesc->cDims = pSA->cDims;
2502 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2503 pSA->cDims * sizeof(SAFEARRAYBOUND));
2505 pTD = &pTD->u.lpadesc->tdescElem;
2506 break;
2509 case VT_SAFEARRAY:
2511 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2512 useful? */
2514 pType++;
2515 pTD->vt = VT_SAFEARRAY;
2516 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2517 sizeof(TYPEDESC));
2518 pTD = pTD->u.lptdesc;
2519 break;
2521 default:
2522 pTD->vt = *pType & 0x7f;
2523 done = TRUE;
2524 break;
2526 pType++;
2528 return pType;
2532 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2533 char *pNameTable)
2535 int ref;
2536 char *name;
2537 TLBRefType **ppRefType;
2539 if(pRef->magic != SLTG_REF_MAGIC) {
2540 FIXME("Ref magic = %x\n", pRef->magic);
2541 return;
2543 name = ( (char*)(&pRef->names) + pRef->number);
2545 ppRefType = &pTI->reflist;
2546 for(ref = 0; ref < pRef->number >> 3; ref++) {
2547 char *refname;
2548 unsigned int lib_offs, type_num;
2550 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2551 sizeof(**ppRefType));
2553 name += SLTG_ReadStringA(name, &refname);
2554 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2555 FIXME("Can't sscanf ref\n");
2556 if(lib_offs != 0xffff) {
2557 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2559 while(*import) {
2560 if((*import)->offset == lib_offs)
2561 break;
2562 import = &(*import)->next;
2564 if(!*import) {
2565 char fname[MAX_PATH+1];
2566 int len;
2568 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2569 sizeof(**import));
2570 (*import)->offset = lib_offs;
2571 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2572 &(*import)->guid);
2573 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2574 &(*import)->wVersionMajor,
2575 &(*import)->wVersionMinor,
2576 &(*import)->lcid, fname) != 4) {
2577 FIXME("can't sscanf ref %s\n",
2578 pNameTable + lib_offs + 40);
2580 len = strlen(fname);
2581 if(fname[len-1] != '#')
2582 FIXME("fname = %s\n", fname);
2583 fname[len-1] = '\0';
2584 (*import)->name = TLB_MultiByteToBSTR(fname);
2586 (*ppRefType)->pImpTLInfo = *import;
2587 } else { /* internal ref */
2588 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2590 (*ppRefType)->reference = ref;
2591 (*ppRefType)->index = type_num;
2593 HeapFree(GetProcessHeap(), 0, refname);
2594 ppRefType = &(*ppRefType)->next;
2596 if((BYTE)*name != SLTG_REF_MAGIC)
2597 FIXME("End of ref block magic = %x\n", *name);
2598 dump_TLBRefType(pTI->reflist);
2601 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2602 BOOL OneOnly)
2604 SLTG_ImplInfo *info;
2605 TLBImplType **ppImplType = &pTI->impltypelist;
2606 /* I don't really get this structure, usually it's 0x16 bytes
2607 long, but iuser.tlb contains some that are 0x18 bytes long.
2608 That's ok because we can use the next ptr to jump to the next
2609 one. But how do we know the length of the last one? The WORD
2610 at offs 0x8 might be the clue. For now I'm just assuming that
2611 the last one is the regular 0x16 bytes. */
2613 info = (SLTG_ImplInfo*)pBlk;
2614 while(1) {
2615 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2616 sizeof(**ppImplType));
2617 (*ppImplType)->hRef = info->ref;
2618 (*ppImplType)->implflags = info->impltypeflags;
2619 pTI->TypeAttr.cImplTypes++;
2620 ppImplType = &(*ppImplType)->next;
2622 if(info->next == 0xffff)
2623 break;
2624 if(OneOnly)
2625 FIXME("Interface inheriting more than one interface\n");
2626 info = (SLTG_ImplInfo*)(pBlk + info->next);
2628 info++; /* see comment at top of function */
2629 return (char*)info;
2632 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2633 char *pNameTable)
2635 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2636 SLTG_MemberHeader *pMemHeader;
2637 char *pFirstItem, *pNextItem;
2639 if(pTIHeader->href_table != 0xffffffff) {
2640 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2641 pNameTable);
2645 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2647 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2649 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2650 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2653 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2657 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2658 char *pNameTable)
2660 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2661 SLTG_MemberHeader *pMemHeader;
2662 SLTG_Function *pFunc;
2663 char *pFirstItem, *pNextItem;
2664 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2665 int num = 0;
2667 if(pTIHeader->href_table != 0xffffffff) {
2668 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2669 pNameTable);
2672 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2674 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2676 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2677 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2680 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2681 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2683 int param;
2684 WORD *pType, *pArg;
2686 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2687 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2688 FIXME("func magic = %02x\n", pFunc->magic);
2689 return NULL;
2691 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2692 sizeof(**ppFuncDesc));
2693 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2695 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2696 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2697 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2698 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2699 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2700 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2702 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2703 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2705 if(pFunc->retnextopt & 0x80)
2706 pType = &pFunc->rettype;
2707 else
2708 pType = (WORD*)(pFirstItem + pFunc->rettype);
2711 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2713 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2714 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2715 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2716 (*ppFuncDesc)->pParamDesc =
2717 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2718 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2720 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2722 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2723 char *paramName = pNameTable + *pArg;
2724 BOOL HaveOffs;
2725 /* If arg type follows then paramName points to the 2nd
2726 letter of the name, else the next WORD is an offset to
2727 the arg type and paramName points to the first letter.
2728 So let's take one char off paramName and see if we're
2729 pointing at an alpha-numeric char. However if *pArg is
2730 0xffff or 0xfffe then the param has no name, the former
2731 meaning that the next WORD is the type, the latter
2732 meaning the the next WORD is an offset to the type. */
2734 HaveOffs = FALSE;
2735 if(*pArg == 0xffff)
2736 paramName = NULL;
2737 else if(*pArg == 0xfffe) {
2738 paramName = NULL;
2739 HaveOffs = TRUE;
2741 else if(!isalnum(*(paramName-1)))
2742 HaveOffs = TRUE;
2744 pArg++;
2746 if(HaveOffs) { /* the next word is an offset to type */
2747 pType = (WORD*)(pFirstItem + *pArg);
2748 SLTG_DoType(pType, pFirstItem,
2749 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2750 pArg++;
2751 } else {
2752 if(paramName)
2753 paramName--;
2754 pArg = SLTG_DoType(pArg, pFirstItem,
2755 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2758 /* Are we an optional param ? */
2759 if((*ppFuncDesc)->funcdesc.cParams - param <=
2760 (*ppFuncDesc)->funcdesc.cParamsOpt)
2761 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2763 if(paramName) {
2764 (*ppFuncDesc)->pParamDesc[param].Name =
2765 TLB_MultiByteToBSTR(paramName);
2769 ppFuncDesc = &((*ppFuncDesc)->next);
2770 if(pFunc->next == 0xffff) break;
2772 pTI->TypeAttr.cFuncs = num;
2773 dump_TLBFuncDesc(pTI->funclist);
2774 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2777 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2778 char *pNameTable)
2780 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2781 SLTG_MemberHeader *pMemHeader;
2782 SLTG_RecordItem *pItem;
2783 char *pFirstItem;
2784 TLBVarDesc **ppVarDesc = &pTI->varlist;
2785 int num = 0;
2786 WORD *pType;
2787 char buf[300];
2789 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2791 pFirstItem = (char*)(pMemHeader + 1);
2792 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2793 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2794 if(pItem->magic != SLTG_RECORD_MAGIC) {
2795 FIXME("record magic = %02x\n", pItem->magic);
2796 return NULL;
2798 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2799 sizeof(**ppVarDesc));
2800 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2801 (*ppVarDesc)->vardesc.memid = pItem->memid;
2802 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2803 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2805 if(pItem->typepos == 0x02)
2806 pType = &pItem->type;
2807 else if(pItem->typepos == 0x00)
2808 pType = (WORD*)(pFirstItem + pItem->type);
2809 else {
2810 FIXME("typepos = %02x\n", pItem->typepos);
2811 break;
2814 SLTG_DoType(pType, pFirstItem,
2815 &(*ppVarDesc)->vardesc.elemdescVar);
2817 /* FIXME("helpcontext, helpstring\n"); */
2819 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2821 ppVarDesc = &((*ppVarDesc)->next);
2822 if(pItem->next == 0xffff) break;
2824 pTI->TypeAttr.cVars = num;
2825 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2828 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2829 char *pNameTable)
2831 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2832 SLTG_MemberHeader *pMemHeader;
2833 SLTG_AliasItem *pItem;
2834 int i, mustbelast;
2836 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2837 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2839 mustbelast = 0;
2840 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2841 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2842 if (pItem->vt == 0xffff) {
2843 if (i<(pMemHeader->cbExtra/4-1))
2844 FIXME("Endmarker too early in process alias data!\n");
2845 break;
2847 if (mustbelast) {
2848 FIXME("Chain extends over last entry?\n");
2849 break;
2851 if (pItem->vt == VT_USERDEFINED) {
2852 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2853 /* guessing here ... */
2854 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2855 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2856 mustbelast = 1;
2857 } else {
2858 FIXME("alias %d: 0x%x\n",i,pItem->vt);
2859 FIXME("alias %d: 0x%x\n",i,pItem->res02);
2861 pItem++;
2863 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2866 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
2867 char *pNameTable)
2869 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2870 SLTG_MemberHeader *pMemHeader;
2871 SLTG_AliasItem *pItem;
2873 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2874 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2875 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
2876 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
2877 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2880 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2881 char *pNameTable)
2883 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2884 SLTG_MemberHeader *pMemHeader;
2885 SLTG_EnumItem *pItem;
2886 char *pFirstItem;
2887 TLBVarDesc **ppVarDesc = &pTI->varlist;
2888 int num = 0;
2890 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2892 pFirstItem = (char*)(pMemHeader + 1);
2893 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2894 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2895 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2896 FIXME("enumitem magic = %04x\n", pItem->magic);
2897 return NULL;
2899 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2900 sizeof(**ppVarDesc));
2901 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2902 (*ppVarDesc)->vardesc.memid = pItem->memid;
2903 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2904 sizeof(VARIANT));
2905 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2906 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2907 *(INT*)(pItem->value + pFirstItem);
2908 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2909 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2910 /* FIXME("helpcontext, helpstring\n"); */
2912 ppVarDesc = &((*ppVarDesc)->next);
2913 if(pItem->next == 0xffff) break;
2915 pTI->TypeAttr.cVars = num;
2916 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2919 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2920 managable copy of it into this */
2921 typedef struct {
2922 WORD small_no;
2923 char *index_name;
2924 char *other_name;
2925 WORD res1a;
2926 WORD name_offs;
2927 WORD more_bytes;
2928 char *extra;
2929 WORD res20;
2930 DWORD helpcontext;
2931 WORD res26;
2932 GUID uuid;
2933 } SLTG_InternalOtherTypeInfo;
2935 /****************************************************************************
2936 * ITypeLib2_Constructor_SLTG
2938 * loading a SLTG typelib from an in-memory image
2940 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2942 ITypeLibImpl *pTypeLibImpl;
2943 SLTG_Header *pHeader;
2944 SLTG_BlkEntry *pBlkEntry;
2945 SLTG_Magic *pMagic;
2946 SLTG_Index *pIndex;
2947 SLTG_Pad9 *pPad9;
2948 LPVOID pBlk, pFirstBlk;
2949 SLTG_LibBlk *pLibBlk;
2950 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2951 char *pAfterOTIBlks = NULL;
2952 char *pNameTable, *ptr;
2953 int i;
2954 DWORD len, order;
2955 ITypeInfoImpl **ppTypeInfoImpl;
2957 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2959 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2960 if (!pTypeLibImpl) return NULL;
2962 pTypeLibImpl->lpVtbl = &tlbvt;
2963 pTypeLibImpl->ref = 1;
2965 pHeader = pLib;
2967 TRACE("header:\n");
2968 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2969 pHeader->nrOfFileBlks );
2970 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
2971 FIXME("Header type magic 0x%08lx not supported.\n",
2972 pHeader->SLTG_magic);
2973 return NULL;
2976 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2977 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2979 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2980 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2982 /* Next we have a magic block */
2983 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2985 /* Let's see if we're still in sync */
2986 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2987 sizeof(SLTG_COMPOBJ_MAGIC))) {
2988 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2989 return NULL;
2991 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2992 sizeof(SLTG_DIR_MAGIC))) {
2993 FIXME("dir magic = %s\n", pMagic->dir_magic);
2994 return NULL;
2997 pIndex = (SLTG_Index*)(pMagic+1);
2999 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3001 pFirstBlk = (LPVOID)(pPad9 + 1);
3003 /* We'll set up a ptr to the main library block, which is the last one. */
3005 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3006 pBlkEntry[order].next != 0;
3007 order = pBlkEntry[order].next - 1, i++) {
3008 pBlk = (char*)pBlk + pBlkEntry[order].len;
3010 pLibBlk = pBlk;
3012 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3014 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3015 interspersed */
3017 len += 0x40;
3019 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3021 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3022 sizeof(*pOtherTypeInfoBlks) *
3023 pTypeLibImpl->TypeInfoCount);
3026 ptr = (char*)pLibBlk + len;
3028 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3029 WORD w, extra;
3030 len = 0;
3032 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3034 w = *(WORD*)(ptr + 2);
3035 if(w != 0xffff) {
3036 len += w;
3037 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3038 w+1);
3039 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3040 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3042 w = *(WORD*)(ptr + 4 + len);
3043 if(w != 0xffff) {
3044 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3045 len += w;
3046 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3047 w+1);
3048 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3049 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3051 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3052 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3053 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3054 if(extra) {
3055 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3056 extra);
3057 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3058 len += extra;
3060 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3061 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3062 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3063 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3064 len += sizeof(SLTG_OtherTypeInfo);
3065 ptr += len;
3068 pAfterOTIBlks = ptr;
3070 /* Skip this WORD and get the next DWORD */
3071 len = *(DWORD*)(pAfterOTIBlks + 2);
3073 /* Now add this to pLibBLk look at what we're pointing at and
3074 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3075 dust and we should be pointing at the beginning of the name
3076 table */
3078 pNameTable = (char*)pLibBlk + len;
3080 switch(*(WORD*)pNameTable) {
3081 case 0xffff:
3082 break;
3083 case 0x0200:
3084 pNameTable += 0x20;
3085 break;
3086 default:
3087 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3088 break;
3091 pNameTable += 0x216;
3093 pNameTable += 2;
3095 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3097 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3100 /* Hopefully we now have enough ptrs set up to actually read in
3101 some TypeInfos. It's not clear which order to do them in, so
3102 I'll just follow the links along the BlkEntry chain and read
3103 them in in the order in which they're in the file */
3105 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3107 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3108 pBlkEntry[order].next != 0;
3109 order = pBlkEntry[order].next - 1, i++) {
3111 SLTG_TypeInfoHeader *pTIHeader;
3112 SLTG_TypeInfoTail *pTITail;
3114 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3115 pOtherTypeInfoBlks[i].index_name)) {
3116 FIXME("Index strings don't match\n");
3117 return NULL;
3120 pTIHeader = pBlk;
3121 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3122 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3123 return NULL;
3125 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3126 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3127 (*ppTypeInfoImpl)->index = i;
3128 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3129 pOtherTypeInfoBlks[i].name_offs +
3130 pNameTable);
3131 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3132 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3133 sizeof(GUID));
3134 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3135 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3136 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3137 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3138 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3140 if((pTIHeader->typeflags1 & 7) != 2)
3141 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3142 if(pTIHeader->typeflags3 != 2)
3143 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3145 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3146 debugstr_w((*ppTypeInfoImpl)->Name),
3147 typekind_desc[pTIHeader->typekind],
3148 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3149 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3151 switch(pTIHeader->typekind) {
3152 case TKIND_ENUM:
3153 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3154 break;
3156 case TKIND_RECORD:
3157 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3158 break;
3160 case TKIND_INTERFACE:
3161 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3162 break;
3164 case TKIND_COCLASS:
3165 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3166 break;
3168 case TKIND_ALIAS:
3169 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3170 if (pTITail->tdescalias_vt)
3171 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3172 break;
3174 case TKIND_DISPATCH:
3175 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3176 break;
3178 default:
3179 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3180 pTITail = NULL;
3181 break;
3185 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3186 but we've already set those */
3187 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3188 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3189 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3191 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3192 X(06);
3193 X(08);
3194 X(0a);
3195 X(0c);
3196 X(0e);
3197 X(10);
3198 X(12);
3199 X(16);
3200 X(18);
3201 X(1a);
3202 X(1c);
3203 X(1e);
3204 X(24);
3205 X(26);
3206 X(2a);
3207 X(2c);
3208 X(2e);
3209 X(30);
3210 X(32);
3211 X(34);
3213 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3214 pBlk = (char*)pBlk + pBlkEntry[order].len;
3217 if(i != pTypeLibImpl->TypeInfoCount) {
3218 FIXME("Somehow processed %d TypeInfos\n", i);
3219 return NULL;
3222 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3223 return (ITypeLib2*)pTypeLibImpl;
3226 /* ITypeLib::QueryInterface
3228 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3229 ITypeLib2 * iface,
3230 REFIID riid,
3231 VOID **ppvObject)
3233 ICOM_THIS( ITypeLibImpl, iface);
3235 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3237 *ppvObject=NULL;
3238 if(IsEqualIID(riid, &IID_IUnknown) ||
3239 IsEqualIID(riid,&IID_ITypeLib)||
3240 IsEqualIID(riid,&IID_ITypeLib2))
3242 *ppvObject = This;
3245 if(*ppvObject)
3247 ITypeLib2_AddRef(iface);
3248 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3249 return S_OK;
3251 TRACE("-- Interface: E_NOINTERFACE\n");
3252 return E_NOINTERFACE;
3255 /* ITypeLib::AddRef
3257 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3259 ICOM_THIS( ITypeLibImpl, iface);
3261 TRACE("(%p)->ref was %u\n",This, This->ref);
3263 return ++(This->ref);
3266 /* ITypeLib::Release
3268 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3270 ICOM_THIS( ITypeLibImpl, iface);
3272 --(This->ref);
3274 TRACE("(%p)->(%u)\n",This, This->ref);
3276 if (!This->ref)
3278 /* remove cache entry */
3279 TRACE("removing from cache list\n");
3280 EnterCriticalSection(&cache_section);
3281 if (This->next) This->next->prev = This->prev;
3282 if (This->prev) This->prev->next = This->next;
3283 else tlb_cache_first = This->next;
3284 LeaveCriticalSection(&cache_section);
3286 /* FIXME destroy child objects */
3287 TRACE(" destroying ITypeLib(%p)\n",This);
3289 if (This->Name)
3291 SysFreeString(This->Name);
3292 This->Name = NULL;
3295 if (This->DocString)
3297 SysFreeString(This->DocString);
3298 This->DocString = NULL;
3301 if (This->HelpFile)
3303 SysFreeString(This->HelpFile);
3304 This->HelpFile = NULL;
3307 if (This->HelpStringDll)
3309 SysFreeString(This->HelpStringDll);
3310 This->HelpStringDll = NULL;
3313 if (This->pTypeInfo) /* can be NULL */
3314 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3315 HeapFree(GetProcessHeap(),0,This);
3316 return 0;
3319 return This->ref;
3322 /* ITypeLib::GetTypeInfoCount
3324 * Returns the number of type descriptions in the type library
3326 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3328 ICOM_THIS( ITypeLibImpl, iface);
3329 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3330 return This->TypeInfoCount;
3333 /* ITypeLib::GetTypeInfo
3335 * retrieves the specified type description in the library.
3337 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3338 ITypeLib2 *iface,
3339 UINT index,
3340 ITypeInfo **ppTInfo)
3342 int i;
3344 ICOM_THIS( ITypeLibImpl, iface);
3345 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3347 TRACE("(%p)->(index=%d) \n", This, index);
3349 if (!ppTInfo) return E_INVALIDARG;
3351 /* search element n in list */
3352 for(i=0; i < index; i++)
3354 pTypeInfo = pTypeInfo->next;
3355 if (!pTypeInfo)
3357 TRACE("-- element not found\n");
3358 return TYPE_E_ELEMENTNOTFOUND;
3362 *ppTInfo = (ITypeInfo *) pTypeInfo;
3364 ITypeInfo_AddRef(*ppTInfo);
3365 TRACE("-- found (%p)\n",*ppTInfo);
3366 return S_OK;
3370 /* ITypeLibs::GetTypeInfoType
3372 * Retrieves the type of a type description.
3374 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3375 ITypeLib2 *iface,
3376 UINT index,
3377 TYPEKIND *pTKind)
3379 ICOM_THIS( ITypeLibImpl, iface);
3380 int i;
3381 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3383 TRACE("(%p) index %d \n",This, index);
3385 if(!pTKind) return E_INVALIDARG;
3387 /* search element n in list */
3388 for(i=0; i < index; i++)
3390 if(!pTInfo)
3392 TRACE("-- element not found\n");
3393 return TYPE_E_ELEMENTNOTFOUND;
3395 pTInfo = pTInfo->next;
3398 *pTKind = pTInfo->TypeAttr.typekind;
3399 TRACE("-- found Type (%d)\n", *pTKind);
3400 return S_OK;
3403 /* ITypeLib::GetTypeInfoOfGuid
3405 * Retrieves the type description that corresponds to the specified GUID.
3408 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3409 ITypeLib2 *iface,
3410 REFGUID guid,
3411 ITypeInfo **ppTInfo)
3413 ICOM_THIS( ITypeLibImpl, iface);
3414 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3416 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3418 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3420 /* search linked list for guid */
3421 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3423 pTypeInfo = pTypeInfo->next;
3425 if (!pTypeInfo)
3427 /* end of list reached */
3428 TRACE("-- element not found\n");
3429 return TYPE_E_ELEMENTNOTFOUND;
3433 TRACE("-- found (%p, %s)\n",
3434 pTypeInfo,
3435 debugstr_w(pTypeInfo->Name));
3437 *ppTInfo = (ITypeInfo*)pTypeInfo;
3438 ITypeInfo_AddRef(*ppTInfo);
3439 return S_OK;
3442 /* ITypeLib::GetLibAttr
3444 * Retrieves the structure that contains the library's attributes.
3447 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3448 ITypeLib2 *iface,
3449 LPTLIBATTR *ppTLibAttr)
3451 ICOM_THIS( ITypeLibImpl, iface);
3452 TRACE("(%p)\n",This);
3453 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3454 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3455 return S_OK;
3458 /* ITypeLib::GetTypeComp
3460 * Enables a client compiler to bind to a library's types, variables,
3461 * constants, and global functions.
3464 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3465 ITypeLib2 *iface,
3466 ITypeComp **ppTComp)
3468 ICOM_THIS( ITypeLibImpl, iface);
3470 TRACE("(%p)->(%p)\n",This,ppTComp);
3471 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3472 ITypeComp_AddRef(*ppTComp);
3474 return S_OK;
3477 /* ITypeLib::GetDocumentation
3479 * Retrieves the library's documentation string, the complete Help file name
3480 * and path, and the context identifier for the library Help topic in the Help
3481 * file.
3483 * On a successful return all non-null BSTR pointers will have been set,
3484 * possibly to NULL.
3486 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3487 ITypeLib2 *iface,
3488 INT index,
3489 BSTR *pBstrName,
3490 BSTR *pBstrDocString,
3491 DWORD *pdwHelpContext,
3492 BSTR *pBstrHelpFile)
3494 ICOM_THIS( ITypeLibImpl, iface);
3496 HRESULT result = E_INVALIDARG;
3498 ITypeInfo *pTInfo;
3501 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3502 This, index,
3503 pBstrName, pBstrDocString,
3504 pdwHelpContext, pBstrHelpFile);
3506 if(index<0)
3508 /* documentation for the typelib */
3509 if(pBstrName)
3511 if (This->Name)
3512 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3513 else
3514 *pBstrName = NULL;
3516 if(pBstrDocString)
3518 if (This->DocString)
3519 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3520 else if (This->Name)
3521 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3522 else
3523 *pBstrDocString = NULL;
3525 if(pdwHelpContext)
3527 *pdwHelpContext = This->dwHelpContext;
3529 if(pBstrHelpFile)
3531 if (This->HelpFile)
3532 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3533 else
3534 *pBstrHelpFile = NULL;
3537 result = S_OK;
3539 else
3541 /* for a typeinfo */
3542 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3544 if(SUCCEEDED(result))
3546 result = ITypeInfo_GetDocumentation(pTInfo,
3547 MEMBERID_NIL,
3548 pBstrName,
3549 pBstrDocString,
3550 pdwHelpContext, pBstrHelpFile);
3552 ITypeInfo_Release(pTInfo);
3555 return result;
3556 memerr3:
3557 if (pBstrDocString) SysFreeString (*pBstrDocString);
3558 memerr2:
3559 if (pBstrName) SysFreeString (*pBstrName);
3560 memerr1:
3561 return STG_E_INSUFFICIENTMEMORY;
3564 /* ITypeLib::IsName
3566 * Indicates whether a passed-in string contains the name of a type or member
3567 * described in the library.
3570 static HRESULT WINAPI ITypeLib2_fnIsName(
3571 ITypeLib2 *iface,
3572 LPOLESTR szNameBuf,
3573 ULONG lHashVal,
3574 BOOL *pfName)
3576 ICOM_THIS( ITypeLibImpl, iface);
3577 ITypeInfoImpl *pTInfo;
3578 TLBFuncDesc *pFInfo;
3579 TLBVarDesc *pVInfo;
3580 int i;
3581 UINT nNameBufLen = SysStringLen(szNameBuf);
3583 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3584 pfName);
3586 *pfName=TRUE;
3587 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3588 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3589 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3590 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3591 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3592 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3593 goto ITypeLib2_fnIsName_exit;
3595 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3596 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3599 *pfName=FALSE;
3601 ITypeLib2_fnIsName_exit:
3602 TRACE("(%p)slow! search for %s: %s found!\n", This,
3603 debugstr_w(szNameBuf), *pfName?"NOT":"");
3605 return S_OK;
3608 /* ITypeLib::FindName
3610 * Finds occurrences of a type description in a type library. This may be used
3611 * to quickly verify that a name exists in a type library.
3614 static HRESULT WINAPI ITypeLib2_fnFindName(
3615 ITypeLib2 *iface,
3616 LPOLESTR szNameBuf,
3617 ULONG lHashVal,
3618 ITypeInfo **ppTInfo,
3619 MEMBERID *rgMemId,
3620 UINT16 *pcFound)
3622 ICOM_THIS( ITypeLibImpl, iface);
3623 ITypeInfoImpl *pTInfo;
3624 TLBFuncDesc *pFInfo;
3625 TLBVarDesc *pVInfo;
3626 int i,j = 0;
3628 UINT nNameBufLen = SysStringLen(szNameBuf);
3630 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3631 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3632 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3633 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3634 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3635 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3636 goto ITypeLib2_fnFindName_exit;
3638 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3639 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3640 continue;
3641 ITypeLib2_fnFindName_exit:
3642 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3643 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3644 j++;
3646 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3647 This, *pcFound, debugstr_w(szNameBuf), j);
3649 *pcFound=j;
3651 return S_OK;
3654 /* ITypeLib::ReleaseTLibAttr
3656 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3659 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3660 ITypeLib2 *iface,
3661 TLIBATTR *pTLibAttr)
3663 ICOM_THIS( ITypeLibImpl, iface);
3664 TRACE("freeing (%p)\n",This);
3665 HeapFree(GetProcessHeap(),0,pTLibAttr);
3669 /* ITypeLib2::GetCustData
3671 * gets the custom data
3673 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3674 ITypeLib2 * iface,
3675 REFGUID guid,
3676 VARIANT *pVarVal)
3678 ICOM_THIS( ITypeLibImpl, iface);
3679 TLBCustData *pCData;
3681 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3683 if( IsEqualIID(guid, &pCData->guid)) break;
3686 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3688 if(pCData)
3690 VariantInit( pVarVal);
3691 VariantCopy( pVarVal, &pCData->data);
3692 return S_OK;
3694 return E_INVALIDARG; /* FIXME: correct? */
3697 /* ITypeLib2::GetLibStatistics
3699 * Returns statistics about a type library that are required for efficient
3700 * sizing of hash tables.
3703 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3704 ITypeLib2 * iface,
3705 ULONG *pcUniqueNames,
3706 ULONG *pcchUniqueNames)
3708 ICOM_THIS( ITypeLibImpl, iface);
3710 FIXME("(%p): stub!\n", This);
3712 if(pcUniqueNames) *pcUniqueNames=1;
3713 if(pcchUniqueNames) *pcchUniqueNames=1;
3714 return S_OK;
3717 /* ITypeLib2::GetDocumentation2
3719 * Retrieves the library's documentation string, the complete Help file name
3720 * and path, the localization context to use, and the context ID for the
3721 * library Help topic in the Help file.
3724 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3725 ITypeLib2 * iface,
3726 INT index,
3727 LCID lcid,
3728 BSTR *pbstrHelpString,
3729 DWORD *pdwHelpStringContext,
3730 BSTR *pbstrHelpStringDll)
3732 ICOM_THIS( ITypeLibImpl, iface);
3733 HRESULT result;
3734 ITypeInfo *pTInfo;
3736 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3738 /* the help string should be obtained from the helpstringdll,
3739 * using the _DLLGetDocumentation function, based on the supplied
3740 * lcid. Nice to do sometime...
3742 if(index<0)
3744 /* documentation for the typelib */
3745 if(pbstrHelpString)
3746 *pbstrHelpString=SysAllocString(This->DocString);
3747 if(pdwHelpStringContext)
3748 *pdwHelpStringContext=This->dwHelpContext;
3749 if(pbstrHelpStringDll)
3750 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3752 result = S_OK;
3754 else
3756 /* for a typeinfo */
3757 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3759 if(SUCCEEDED(result))
3761 ITypeInfo2 * pTInfo2;
3762 result = ITypeInfo_QueryInterface(pTInfo,
3763 &IID_ITypeInfo2,
3764 (LPVOID*) &pTInfo2);
3766 if(SUCCEEDED(result))
3768 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3769 MEMBERID_NIL,
3770 lcid,
3771 pbstrHelpString,
3772 pdwHelpStringContext,
3773 pbstrHelpStringDll);
3775 ITypeInfo2_Release(pTInfo2);
3778 ITypeInfo_Release(pTInfo);
3781 return result;
3784 /* ITypeLib2::GetAllCustData
3786 * Gets all custom data items for the library.
3789 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3790 ITypeLib2 * iface,
3791 CUSTDATA *pCustData)
3793 ICOM_THIS( ITypeLibImpl, iface);
3794 TLBCustData *pCData;
3795 int i;
3796 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3797 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3798 if(pCustData->prgCustData ){
3799 pCustData->cCustData=This->ctCustData;
3800 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3801 pCustData->prgCustData[i].guid=pCData->guid;
3802 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3804 }else{
3805 ERR(" OUT OF MEMORY! \n");
3806 return E_OUTOFMEMORY;
3808 return S_OK;
3811 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3812 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3813 ITypeLib2_fnQueryInterface,
3814 ITypeLib2_fnAddRef,
3815 ITypeLib2_fnRelease,
3816 ITypeLib2_fnGetTypeInfoCount,
3817 ITypeLib2_fnGetTypeInfo,
3818 ITypeLib2_fnGetTypeInfoType,
3819 ITypeLib2_fnGetTypeInfoOfGuid,
3820 ITypeLib2_fnGetLibAttr,
3821 ITypeLib2_fnGetTypeComp,
3822 ITypeLib2_fnGetDocumentation,
3823 ITypeLib2_fnIsName,
3824 ITypeLib2_fnFindName,
3825 ITypeLib2_fnReleaseTLibAttr,
3827 ITypeLib2_fnGetCustData,
3828 ITypeLib2_fnGetLibStatistics,
3829 ITypeLib2_fnGetDocumentation2,
3830 ITypeLib2_fnGetAllCustData
3834 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
3836 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3838 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
3841 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
3843 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3845 return ITypeInfo_AddRef((ITypeInfo *)This);
3848 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
3850 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3852 return ITypeInfo_Release((ITypeInfo *)This);
3855 static HRESULT WINAPI ITypeLibComp_fnBind(
3856 ITypeComp * iface,
3857 OLECHAR * szName,
3858 unsigned long lHash,
3859 unsigned short wFlags,
3860 ITypeInfo ** ppTInfo,
3861 DESCKIND * pDescKind,
3862 BINDPTR * pBindPtr)
3864 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
3865 return E_NOTIMPL;
3868 static HRESULT WINAPI ITypeLibComp_fnBindType(
3869 ITypeComp * iface,
3870 OLECHAR * szName,
3871 unsigned long lHash,
3872 ITypeInfo ** ppTInfo,
3873 ITypeComp ** ppTComp)
3875 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
3876 return E_NOTIMPL;
3879 static ICOM_VTABLE(ITypeComp) tlbtcvt =
3881 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3883 ITypeLibComp_fnQueryInterface,
3884 ITypeLibComp_fnAddRef,
3885 ITypeLibComp_fnRelease,
3887 ITypeLibComp_fnBind,
3888 ITypeLibComp_fnBindType
3891 /*================== ITypeInfo(2) Methods ===================================*/
3892 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3894 ITypeInfoImpl * pTypeInfoImpl;
3896 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3897 if (pTypeInfoImpl)
3899 pTypeInfoImpl->lpVtbl = &tinfvt;
3900 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
3901 pTypeInfoImpl->ref=1;
3903 TRACE("(%p)\n", pTypeInfoImpl);
3904 return (ITypeInfo2*) pTypeInfoImpl;
3907 /* ITypeInfo::QueryInterface
3909 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3910 ITypeInfo2 *iface,
3911 REFIID riid,
3912 VOID **ppvObject)
3914 ICOM_THIS( ITypeLibImpl, iface);
3916 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3918 *ppvObject=NULL;
3919 if(IsEqualIID(riid, &IID_IUnknown) ||
3920 IsEqualIID(riid,&IID_ITypeInfo)||
3921 IsEqualIID(riid,&IID_ITypeInfo2))
3922 *ppvObject = This;
3924 if(*ppvObject){
3925 ITypeInfo_AddRef(iface);
3926 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3927 return S_OK;
3929 TRACE("-- Interface: E_NOINTERFACE\n");
3930 return E_NOINTERFACE;
3933 /* ITypeInfo::AddRef
3935 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3937 ICOM_THIS( ITypeInfoImpl, iface);
3939 ++(This->ref);
3941 TRACE("(%p)->ref is %u\n",This, This->ref);
3942 return This->ref;
3945 /* ITypeInfo::Release
3947 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3949 ICOM_THIS( ITypeInfoImpl, iface);
3951 --(This->ref);
3953 TRACE("(%p)->(%u)\n",This, This->ref);
3955 if (!This->ref)
3957 FIXME("destroy child objects\n");
3959 TRACE("destroying ITypeInfo(%p)\n",This);
3960 if (This->Name)
3962 SysFreeString(This->Name);
3963 This->Name = 0;
3966 if (This->DocString)
3968 SysFreeString(This->DocString);
3969 This->DocString = 0;
3972 if (This->next)
3974 ITypeInfo_Release((ITypeInfo*)This->next);
3977 HeapFree(GetProcessHeap(),0,This);
3978 return 0;
3980 return This->ref;
3983 /* ITypeInfo::GetTypeAttr
3985 * Retrieves a TYPEATTR structure that contains the attributes of the type
3986 * description.
3989 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3990 LPTYPEATTR *ppTypeAttr)
3992 ICOM_THIS( ITypeInfoImpl, iface);
3993 TRACE("(%p)\n",This);
3994 /* FIXME: must do a copy here */
3995 *ppTypeAttr=&This->TypeAttr;
3996 return S_OK;
3999 /* ITypeInfo::GetTypeComp
4001 * Retrieves the ITypeComp interface for the type description, which enables a
4002 * client compiler to bind to the type description's members.
4005 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4006 ITypeComp * *ppTComp)
4008 ICOM_THIS( ITypeInfoImpl, iface);
4010 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4012 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4013 ITypeComp_AddRef(*ppTComp);
4014 return S_OK;
4017 /* ITypeInfo::GetFuncDesc
4019 * Retrieves the FUNCDESC structure that contains information about a
4020 * specified function.
4023 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4024 LPFUNCDESC *ppFuncDesc)
4026 ICOM_THIS( ITypeInfoImpl, iface);
4027 int i;
4028 TLBFuncDesc * pFDesc;
4029 TRACE("(%p) index %d\n", This, index);
4030 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4032 if(pFDesc){
4033 /* FIXME: must do a copy here */
4034 *ppFuncDesc=&pFDesc->funcdesc;
4035 return S_OK;
4037 return E_INVALIDARG;
4040 /* ITypeInfo::GetVarDesc
4042 * Retrieves a VARDESC structure that describes the specified variable.
4045 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4046 LPVARDESC *ppVarDesc)
4048 ICOM_THIS( ITypeInfoImpl, iface);
4049 int i;
4050 TLBVarDesc * pVDesc;
4051 TRACE("(%p) index %d\n", This, index);
4052 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4054 if(pVDesc){
4055 /* FIXME: must do a copy here */
4056 *ppVarDesc=&pVDesc->vardesc;
4057 return S_OK;
4059 return E_INVALIDARG;
4062 /* ITypeInfo_GetNames
4064 * Retrieves the variable with the specified member ID (or the name of the
4065 * property or method and its parameters) that correspond to the specified
4066 * function ID.
4068 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4069 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4071 ICOM_THIS( ITypeInfoImpl, iface);
4072 TLBFuncDesc * pFDesc;
4073 TLBVarDesc * pVDesc;
4074 int i;
4075 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4076 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4077 if(pFDesc)
4079 /* function found, now return function and parameter names */
4080 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4082 if(!i)
4083 *rgBstrNames=SysAllocString(pFDesc->Name);
4084 else
4085 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4087 *pcNames=i;
4089 else
4091 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4092 if(pVDesc)
4094 *rgBstrNames=SysAllocString(pVDesc->Name);
4095 *pcNames=1;
4097 else
4099 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
4101 /* recursive search */
4102 ITypeInfo *pTInfo;
4103 HRESULT result;
4104 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4105 &pTInfo);
4106 if(SUCCEEDED(result))
4108 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4109 ITypeInfo_Release(pTInfo);
4110 return result;
4112 WARN("Could not search inherited interface!\n");
4114 else
4116 WARN("no names found\n");
4118 *pcNames=0;
4119 return TYPE_E_ELEMENTNOTFOUND;
4122 return S_OK;
4126 /* ITypeInfo::GetRefTypeOfImplType
4128 * If a type description describes a COM class, it retrieves the type
4129 * description of the implemented interface types. For an interface,
4130 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4131 * if any exist.
4134 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4135 ITypeInfo2 *iface,
4136 UINT index,
4137 HREFTYPE *pRefType)
4139 ICOM_THIS( ITypeInfoImpl, iface);
4140 int(i);
4141 TLBImplType *pImpl = This->impltypelist;
4143 TRACE("(%p) index %d\n", This, index);
4144 if (TRACE_ON(ole)) dump_TypeInfo(This);
4146 if(index==(UINT)-1)
4148 /* only valid on dual interfaces;
4149 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4151 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4153 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4154 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4156 *pRefType = -1;
4158 else
4160 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4161 *pRefType = pImpl->hRef;
4164 else
4166 /* get element n from linked list */
4167 for(i=0; pImpl && i<index; i++)
4169 pImpl = pImpl->next;
4172 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4174 *pRefType = pImpl->hRef;
4176 TRACE("-- 0x%08lx\n", pImpl->hRef );
4179 return S_OK;
4183 /* ITypeInfo::GetImplTypeFlags
4185 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4186 * or base interface in a type description.
4188 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4189 UINT index, INT *pImplTypeFlags)
4191 ICOM_THIS( ITypeInfoImpl, iface);
4192 int i;
4193 TLBImplType *pImpl;
4195 TRACE("(%p) index %d\n", This, index);
4196 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4197 i++, pImpl=pImpl->next)
4199 if(i==index && pImpl){
4200 *pImplTypeFlags=pImpl->implflags;
4201 return S_OK;
4203 *pImplTypeFlags=0;
4204 return TYPE_E_ELEMENTNOTFOUND;
4207 /* GetIDsOfNames
4208 * Maps between member names and member IDs, and parameter names and
4209 * parameter IDs.
4211 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4212 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4214 ICOM_THIS( ITypeInfoImpl, iface);
4215 TLBFuncDesc * pFDesc;
4216 TLBVarDesc * pVDesc;
4217 HRESULT ret=S_OK;
4219 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4220 cNames);
4221 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4222 int i, j;
4223 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4224 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4225 for(i=1; i < cNames; i++){
4226 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4227 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4228 break;
4229 if( j<pFDesc->funcdesc.cParams)
4230 pMemId[i]=j;
4231 else
4232 ret=DISP_E_UNKNOWNNAME;
4234 return ret;
4237 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4238 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4239 if(cNames) *pMemId=pVDesc->vardesc.memid;
4240 return ret;
4243 /* not found, see if this is and interface with an inheritance */
4244 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
4245 This->TypeAttr.cImplTypes ){
4246 /* recursive search */
4247 ITypeInfo *pTInfo;
4248 ret=ITypeInfo_GetRefTypeInfo(iface,
4249 This->impltypelist->hRef, &pTInfo);
4250 if(SUCCEEDED(ret)){
4251 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4252 ITypeInfo_Release(pTInfo);
4253 return ret;
4255 WARN("Could not search inherited interface!\n");
4256 } else
4257 WARN("no names found\n");
4258 return DISP_E_UNKNOWNNAME;
4261 /* ITypeInfo::Invoke
4263 * Invokes a method, or accesses a property of an object, that implements the
4264 * interface described by the type description.
4266 DWORD
4267 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4268 DWORD res;
4270 if (TRACE_ON(ole)) {
4271 int i;
4272 TRACE("Calling %p(",func);
4273 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4274 TRACE(")\n");
4277 switch (callconv) {
4278 case CC_STDCALL:
4280 switch (nrargs) {
4281 case 0:
4282 res = func();
4283 break;
4284 case 1:
4285 res = func(args[0]);
4286 break;
4287 case 2:
4288 res = func(args[0],args[1]);
4289 break;
4290 case 3:
4291 res = func(args[0],args[1],args[2]);
4292 break;
4293 case 4:
4294 res = func(args[0],args[1],args[2],args[3]);
4295 break;
4296 case 5:
4297 res = func(args[0],args[1],args[2],args[3],args[4]);
4298 break;
4299 case 6:
4300 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4301 break;
4302 case 7:
4303 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4304 break;
4305 case 8:
4306 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4307 break;
4308 case 9:
4309 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4310 break;
4311 default:
4312 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4313 res = -1;
4314 break;
4316 break;
4317 default:
4318 FIXME("unsupported calling convention %d\n",callconv);
4319 res = -1;
4320 break;
4322 TRACE("returns %08lx\n",res);
4323 return res;
4326 extern int const _argsize(DWORD vt);
4328 /****************************************************************************
4329 * Helper functions for Dispcall / Invoke, which copies one variant
4330 * with target type onto the argument stack.
4332 static HRESULT
4333 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4334 DWORD *argpos, VARIANT *arg, VARTYPE vt
4336 UINT arglen = _argsize(vt)*sizeof(DWORD);
4337 VARTYPE oldvt;
4338 VARIANT va;
4340 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4341 memcpy(argpos,&arg,sizeof(void*));
4342 return S_OK;
4345 if (V_VT(arg) == vt) {
4346 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4347 return S_OK;
4350 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4351 memcpy(argpos, &V_UNION(arg,parray), sizeof(SAFEARRAY*));
4352 return S_OK;
4355 if (vt == VT_VARIANT) {
4356 memcpy(argpos, arg, arglen);
4357 return S_OK;
4359 /* Deref BYREF vars if there is need */
4360 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4361 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4362 return S_OK;
4364 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4365 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4366 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4367 return S_OK;
4369 if ((vt == VT_PTR) && tdesc)
4370 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4372 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4373 ITypeInfo *tinfo2;
4374 TYPEATTR *tattr;
4375 HRESULT hres;
4377 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4378 if (hres) {
4379 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));
4380 memcpy(argpos, &V_UNION(arg,lVal), 4);
4381 return S_OK;
4383 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4384 switch (tattr->typekind) {
4385 case TKIND_ENUM:
4386 switch ( V_VT( arg ) ) {
4387 case VT_I2:
4388 *argpos = V_UNION(arg,iVal);
4389 return S_OK;
4390 case VT_I4:
4391 memcpy(argpos, &V_UNION(arg,lVal), 4);
4392 return S_OK;
4393 default:
4394 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4395 break;
4398 case TKIND_ALIAS:
4399 tdesc = &(tattr->tdescAlias);
4400 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4401 ITypeInfo_Release(tinfo2);
4402 return hres;
4404 case TKIND_INTERFACE:
4405 if (V_VT(arg) == VT_DISPATCH) {
4406 IDispatch *disp;
4407 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4408 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4409 return S_OK;
4411 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),&IID_IDispatch,(LPVOID*)&disp);
4412 if (SUCCEEDED(hres)) {
4413 memcpy(argpos,&disp,4);
4414 IUnknown_Release(V_UNION(arg,pdispVal));
4415 return S_OK;
4417 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4418 return E_FAIL;
4420 if (V_VT(arg) == VT_UNKNOWN) {
4421 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4422 return S_OK;
4424 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg),debugstr_guid(&(tattr->guid)));
4425 break;
4426 case TKIND_DISPATCH:
4427 if (V_VT(arg) == VT_DISPATCH) {
4428 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4429 return S_OK;
4431 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4432 break;
4433 case TKIND_RECORD:
4434 FIXME("TKIND_RECORD unhandled.\n");
4435 break;
4436 default:
4437 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4438 break;
4440 return E_FAIL;
4443 oldvt = V_VT(arg);
4444 VariantInit(&va);
4445 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4446 memcpy(argpos,&V_UNION(&va,lVal), arglen);
4447 FIXME("Should not use VariantChangeType here. (conversion from 0x%x -> 0x%x)\n",
4448 V_VT(arg), vt
4450 return S_OK;
4452 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4453 return E_FAIL;
4456 /***********************************************************************
4457 * DispCallFunc (OLEAUT32.@)
4459 HRESULT WINAPI
4460 DispCallFunc(
4461 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4462 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4464 int i, argsize, argspos;
4465 DWORD *args;
4466 HRESULT hres;
4468 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4469 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4471 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4472 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4473 argsize = 1;
4474 for (i=0;i<cActuals;i++) {
4475 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4476 dump_Variant(prgpvarg[i]);
4477 argsize += _argsize(prgvt[i]);
4479 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4480 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4481 argspos = 1;
4482 for (i=0;i<cActuals;i++) {
4483 VARIANT *arg = prgpvarg[i];
4484 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4485 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4486 argspos += _argsize(prgvt[i]);
4489 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4491 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4492 hres=S_OK;
4494 else
4496 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4497 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4498 FIXME("Method returned %lx\n",hres);
4500 HeapFree(GetProcessHeap(),0,args);
4501 return hres;
4504 static HRESULT WINAPI ITypeInfo_fnInvoke(
4505 ITypeInfo2 *iface,
4506 VOID *pIUnk,
4507 MEMBERID memid,
4508 UINT16 dwFlags,
4509 DISPPARAMS *pDispParams,
4510 VARIANT *pVarResult,
4511 EXCEPINFO *pExcepInfo,
4512 UINT *pArgErr)
4514 ICOM_THIS( ITypeInfoImpl, iface);
4515 TLBFuncDesc * pFDesc;
4516 TLBVarDesc * pVDesc;
4517 int i;
4518 HRESULT hres;
4520 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4521 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4523 dump_DispParms(pDispParams);
4525 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4526 if (pFDesc->funcdesc.memid == memid) {
4527 if (pFDesc->funcdesc.invkind & dwFlags)
4528 break;
4531 if (pFDesc) {
4532 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4533 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4534 switch (pFDesc->funcdesc.funckind) {
4535 case FUNC_PUREVIRTUAL:
4536 case FUNC_VIRTUAL: {
4537 DWORD res;
4538 int numargs, numargs2, argspos, args2pos;
4539 DWORD *args , *args2;
4542 numargs = 1; numargs2 = 0;
4543 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4544 if (i<pDispParams->cArgs)
4545 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4546 else {
4547 numargs += 1; /* sizeof(lpvoid) */
4548 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4552 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4553 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4555 args[0] = (DWORD)pIUnk;
4556 argspos = 1; args2pos = 0;
4557 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4558 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4559 if (i<pDispParams->cArgs) {
4560 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4561 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4562 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4563 if (FAILED(hres)) return hres;
4564 argspos += arglen;
4565 } else {
4566 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4567 if (tdesc->vt != VT_PTR)
4568 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4569 /*FIXME: give pointers for the rest, so propertyget works*/
4570 args[argspos] = (DWORD)&args2[args2pos];
4572 /* If pointer to variant, pass reference it. */
4573 if ((tdesc->vt == VT_PTR) &&
4574 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4575 pVarResult
4577 args[argspos]= (DWORD)pVarResult;
4578 argspos += 1;
4579 args2pos += arglen;
4582 if (pFDesc->funcdesc.cParamsOpt)
4583 FIXME("Does not support optional parameters (%d)\n",
4584 pFDesc->funcdesc.cParamsOpt
4587 res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4],
4588 pFDesc->funcdesc.callconv,
4589 numargs,
4590 args
4592 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4593 args2pos = 0;
4594 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4595 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4596 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4597 TYPEDESC i4_tdesc;
4598 i4_tdesc.vt = VT_I4;
4600 /* If we are a pointer to a variant, we are done already */
4601 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4602 continue;
4604 VariantInit(pVarResult);
4605 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4607 if (tdesc->vt == VT_PTR)
4608 tdesc = tdesc->u.lptdesc;
4609 if (tdesc->vt == VT_USERDEFINED) {
4610 ITypeInfo *tinfo2;
4611 TYPEATTR *tattr;
4613 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4614 if (hres) {
4615 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4616 return E_FAIL;
4618 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4619 switch (tattr->typekind) {
4620 case TKIND_ENUM:
4621 /* force the return type to be VT_I4 */
4622 tdesc = &i4_tdesc;
4623 break;
4624 case TKIND_ALIAS:
4625 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4626 tdesc = &(tattr->tdescAlias);
4627 break;
4629 case TKIND_INTERFACE:
4630 FIXME("TKIND_INTERFACE unhandled.\n");
4631 break;
4632 case TKIND_DISPATCH:
4633 FIXME("TKIND_DISPATCH unhandled.\n");
4634 break;
4635 case TKIND_RECORD:
4636 FIXME("TKIND_RECORD unhandled.\n");
4637 break;
4638 default:
4639 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4640 break;
4642 ITypeInfo_Release(tinfo2);
4644 V_VT(pVarResult) = tdesc->vt;
4646 /* HACK: VB5 likes this.
4647 * I do not know why. There is 1 example in MSDN which uses
4648 * this which appears broken (mixes int vals and
4649 * IDispatch*.).
4651 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4652 V_VT(pVarResult) = VT_DISPATCH;
4653 TRACE("storing into variant:\n");
4654 dump_Variant(pVarResult);
4655 args2pos += arglen;
4658 HeapFree(GetProcessHeap(),0,args2);
4659 HeapFree(GetProcessHeap(),0,args);
4660 return S_OK;
4662 case FUNC_DISPATCH: {
4663 IDispatch *disp;
4664 HRESULT hr;
4666 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4667 if (hr) {
4668 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4669 return hr;
4671 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4672 hr = IDispatch_Invoke(
4673 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4674 pVarResult,pExcepInfo,pArgErr
4676 if (hr)
4677 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4678 IDispatch_Release(disp);
4679 return hr;
4681 default:
4682 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4683 return E_FAIL;
4685 } else {
4686 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4687 if (pVDesc->vardesc.memid == memid) {
4688 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4689 dump_TLBVarDesc(pVDesc);
4690 break;
4694 /* not found, look for it in inherited interfaces */
4695 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4696 /* recursive search */
4697 ITypeInfo *pTInfo;
4698 HRESULT hr;
4699 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4700 if(SUCCEEDED(hr)){
4701 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4702 ITypeInfo_Release(pTInfo);
4703 return hr;
4705 WARN("Could not search inherited interface!\n");
4707 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4708 return DISP_E_MEMBERNOTFOUND;
4711 /* ITypeInfo::GetDocumentation
4713 * Retrieves the documentation string, the complete Help file name and path,
4714 * and the context ID for the Help topic for a specified type description.
4716 * (Can be tested by the Visual Basic Editor in Word for instance.)
4718 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4719 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4720 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4722 ICOM_THIS( ITypeInfoImpl, iface);
4723 TLBFuncDesc * pFDesc;
4724 TLBVarDesc * pVDesc;
4725 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4726 " HelpContext(%p) HelpFile(%p)\n",
4727 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4728 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4729 if(pBstrName)
4730 *pBstrName=SysAllocString(This->Name);
4731 if(pBstrDocString)
4732 *pBstrDocString=SysAllocString(This->DocString);
4733 if(pdwHelpContext)
4734 *pdwHelpContext=This->dwHelpContext;
4735 if(pBstrHelpFile)
4736 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4737 return S_OK;
4738 }else {/* for a member */
4739 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4740 if(pFDesc->funcdesc.memid==memid){
4741 if(pBstrName)
4742 *pBstrName = SysAllocString(pFDesc->Name);
4743 if(pBstrDocString)
4744 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4745 if(pdwHelpContext)
4746 *pdwHelpContext=pFDesc->helpcontext;
4747 return S_OK;
4749 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4750 if(pVDesc->vardesc.memid==memid){
4751 if(pBstrName)
4752 *pBstrName = SysAllocString(pVDesc->Name);
4753 if(pBstrDocString)
4754 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4755 if(pdwHelpContext)
4756 *pdwHelpContext=pVDesc->HelpContext;
4757 return S_OK;
4760 return TYPE_E_ELEMENTNOTFOUND;
4763 /* ITypeInfo::GetDllEntry
4765 * Retrieves a description or specification of an entry point for a function
4766 * in a DLL.
4768 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4769 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4770 WORD *pwOrdinal)
4772 ICOM_THIS( ITypeInfoImpl, iface);
4773 TLBFuncDesc *pFDesc;
4775 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4777 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4778 if(pFDesc->funcdesc.memid==memid){
4779 dump_TypeInfo(This);
4780 dump_TLBFuncDescOne(pFDesc);
4782 /* FIXME: This is wrong, but how do you find that out? */
4783 if (pBstrDllName) {
4784 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4785 *pBstrDllName = SysAllocString(oleaut32W);
4788 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4789 if (pBstrName)
4790 *pBstrName = SysAllocString(pFDesc->Entry);
4791 if (pwOrdinal)
4792 *pwOrdinal = -1;
4793 return S_OK;
4795 if (pBstrName)
4796 *pBstrName = NULL;
4797 if (pwOrdinal)
4798 *pwOrdinal = (DWORD)pFDesc->Entry;
4799 return S_OK;
4801 return E_FAIL;
4804 /* ITypeInfo::GetRefTypeInfo
4806 * If a type description references other type descriptions, it retrieves
4807 * the referenced type descriptions.
4809 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4810 ITypeInfo2 *iface,
4811 HREFTYPE hRefType,
4812 ITypeInfo **ppTInfo)
4814 ICOM_THIS( ITypeInfoImpl, iface);
4815 HRESULT result = E_FAIL;
4818 if (hRefType == -1 &&
4819 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4820 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4822 /* when we meet a DUAL dispinterface, we must create the interface
4823 * version of it.
4825 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4828 /* the interface version contains the same information as the dispinterface
4829 * copy the contents of the structs.
4831 *pTypeInfoImpl = *This;
4832 pTypeInfoImpl->ref = 1;
4834 /* change the type to interface */
4835 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4837 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4839 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4841 result = S_OK;
4843 } else {
4844 TLBRefType *pRefType;
4845 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4846 if(pRefType->reference == hRefType)
4847 break;
4849 if(!pRefType)
4850 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4851 if(pRefType && hRefType != -1) {
4852 ITypeLib *pTLib = NULL;
4854 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4855 int Index;
4856 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4857 } else {
4858 if(pRefType->pImpTLInfo->pImpTypeLib) {
4859 TRACE("typeinfo in imported typelib that is already loaded\n");
4860 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4861 ITypeLib2_AddRef((ITypeLib*) pTLib);
4862 result = S_OK;
4863 } else {
4864 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4865 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4866 pRefType->pImpTLInfo->wVersionMajor,
4867 pRefType->pImpTLInfo->wVersionMinor,
4868 pRefType->pImpTLInfo->lcid,
4869 &pTLib);
4871 if(!SUCCEEDED(result)) {
4872 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4873 result=LoadTypeLib(libnam, &pTLib);
4874 SysFreeString(libnam);
4876 if(SUCCEEDED(result)) {
4877 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4878 ITypeLib2_AddRef(pTLib);
4882 if(SUCCEEDED(result)) {
4883 if(pRefType->index == TLB_REF_USE_GUID)
4884 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4885 &pRefType->guid,
4886 ppTInfo);
4887 else
4888 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4889 ppTInfo);
4891 if (pTLib != NULL)
4892 ITypeLib2_Release(pTLib);
4896 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4897 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4898 return result;
4901 /* ITypeInfo::AddressOfMember
4903 * Retrieves the addresses of static functions or variables, such as those
4904 * defined in a DLL.
4906 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4907 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4909 ICOM_THIS( ITypeInfoImpl, iface);
4910 FIXME("(%p) stub!\n", This);
4911 return S_OK;
4914 /* ITypeInfo::CreateInstance
4916 * Creates a new instance of a type that describes a component object class
4917 * (coclass).
4919 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4920 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4922 ICOM_THIS( ITypeInfoImpl, iface);
4923 FIXME("(%p) stub!\n", This);
4924 return S_OK;
4927 /* ITypeInfo::GetMops
4929 * Retrieves marshalling information.
4931 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4932 BSTR *pBstrMops)
4934 ICOM_THIS( ITypeInfoImpl, iface);
4935 FIXME("(%p) stub!\n", This);
4936 return S_OK;
4939 /* ITypeInfo::GetContainingTypeLib
4941 * Retrieves the containing type library and the index of the type description
4942 * within that type library.
4944 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4945 ITypeLib * *ppTLib, UINT *pIndex)
4947 ICOM_THIS( ITypeInfoImpl, iface);
4949 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
4950 if (pIndex) {
4951 *pIndex=This->index;
4952 TRACE("returning pIndex=%d\n", *pIndex);
4955 if (ppTLib) {
4956 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4957 ITypeLib2_AddRef(*ppTLib);
4958 TRACE("returning ppTLib=%p\n", *ppTLib);
4961 return S_OK;
4964 /* ITypeInfo::ReleaseTypeAttr
4966 * Releases a TYPEATTR previously returned by GetTypeAttr.
4969 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4970 TYPEATTR* pTypeAttr)
4972 ICOM_THIS( ITypeInfoImpl, iface);
4973 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4976 /* ITypeInfo::ReleaseFuncDesc
4978 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4980 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
4981 ITypeInfo2 *iface,
4982 FUNCDESC *pFuncDesc)
4984 ICOM_THIS( ITypeInfoImpl, iface);
4985 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4988 /* ITypeInfo::ReleaseVarDesc
4990 * Releases a VARDESC previously returned by GetVarDesc.
4992 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4993 VARDESC *pVarDesc)
4995 ICOM_THIS( ITypeInfoImpl, iface);
4996 TRACE("(%p)->(%p)\n", This, pVarDesc);
4999 /* ITypeInfo2::GetTypeKind
5001 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5004 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5005 TYPEKIND *pTypeKind)
5007 ICOM_THIS( ITypeInfoImpl, iface);
5008 *pTypeKind=This->TypeAttr.typekind;
5009 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5010 return S_OK;
5013 /* ITypeInfo2::GetTypeFlags
5015 * Returns the type flags without any allocations. This returns a DWORD type
5016 * flag, which expands the type flags without growing the TYPEATTR (type
5017 * attribute).
5020 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5022 ICOM_THIS( ITypeInfoImpl, iface);
5023 *pTypeFlags=This->TypeAttr.wTypeFlags;
5024 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5025 return S_OK;
5028 /* ITypeInfo2::GetFuncIndexOfMemId
5029 * Binds to a specific member based on a known DISPID, where the member name
5030 * is not known (for example, when binding to a default member).
5033 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5034 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5036 ICOM_THIS( ITypeInfoImpl, iface);
5037 TLBFuncDesc *pFuncInfo;
5038 int i;
5039 HRESULT result;
5040 /* FIXME: should check for invKind??? */
5041 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
5042 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
5043 if(pFuncInfo){
5044 *pFuncIndex=i;
5045 result= S_OK;
5046 }else{
5047 *pFuncIndex=0;
5048 result=E_INVALIDARG;
5050 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5051 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
5052 return result;
5055 /* TypeInfo2::GetVarIndexOfMemId
5057 * Binds to a specific member based on a known DISPID, where the member name
5058 * is not known (for example, when binding to a default member).
5061 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5062 MEMBERID memid, UINT *pVarIndex)
5064 ICOM_THIS( ITypeInfoImpl, iface);
5065 TLBVarDesc *pVarInfo;
5066 int i;
5067 HRESULT result;
5068 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5069 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5071 if(pVarInfo){
5072 *pVarIndex=i;
5073 result= S_OK;
5074 }else{
5075 *pVarIndex=0;
5076 result=E_INVALIDARG;
5078 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5079 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
5080 return result;
5083 /* ITypeInfo2::GetCustData
5085 * Gets the custom data
5087 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5088 ITypeInfo2 * iface,
5089 REFGUID guid,
5090 VARIANT *pVarVal)
5092 ICOM_THIS( ITypeInfoImpl, iface);
5093 TLBCustData *pCData;
5095 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5096 if( IsEqualIID(guid, &pCData->guid)) break;
5098 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5100 if(pCData)
5102 VariantInit( pVarVal);
5103 VariantCopy( pVarVal, &pCData->data);
5104 return S_OK;
5106 return E_INVALIDARG; /* FIXME: correct? */
5109 /* ITypeInfo2::GetFuncCustData
5111 * Gets the custom data
5113 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5114 ITypeInfo2 * iface,
5115 UINT index,
5116 REFGUID guid,
5117 VARIANT *pVarVal)
5119 ICOM_THIS( ITypeInfoImpl, iface);
5120 TLBCustData *pCData=NULL;
5121 TLBFuncDesc * pFDesc;
5122 int i;
5123 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5124 pFDesc=pFDesc->next);
5126 if(pFDesc)
5127 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5128 if( IsEqualIID(guid, &pCData->guid)) break;
5130 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5132 if(pCData){
5133 VariantInit( pVarVal);
5134 VariantCopy( pVarVal, &pCData->data);
5135 return S_OK;
5137 return E_INVALIDARG; /* FIXME: correct? */
5140 /* ITypeInfo2::GetParamCustData
5142 * Gets the custom data
5144 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5145 ITypeInfo2 * iface,
5146 UINT indexFunc,
5147 UINT indexParam,
5148 REFGUID guid,
5149 VARIANT *pVarVal)
5151 ICOM_THIS( ITypeInfoImpl, iface);
5152 TLBCustData *pCData=NULL;
5153 TLBFuncDesc * pFDesc;
5154 int i;
5156 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5158 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5159 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5160 pCData = pCData->next)
5161 if( IsEqualIID(guid, &pCData->guid)) break;
5163 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5165 if(pCData)
5167 VariantInit( pVarVal);
5168 VariantCopy( pVarVal, &pCData->data);
5169 return S_OK;
5171 return E_INVALIDARG; /* FIXME: correct? */
5174 /* ITypeInfo2::GetVarCustData
5176 * Gets the custom data
5178 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5179 ITypeInfo2 * iface,
5180 UINT index,
5181 REFGUID guid,
5182 VARIANT *pVarVal)
5184 ICOM_THIS( ITypeInfoImpl, iface);
5185 TLBCustData *pCData=NULL;
5186 TLBVarDesc * pVDesc;
5187 int i;
5189 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5191 if(pVDesc)
5193 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5195 if( IsEqualIID(guid, &pCData->guid)) break;
5199 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5201 if(pCData)
5203 VariantInit( pVarVal);
5204 VariantCopy( pVarVal, &pCData->data);
5205 return S_OK;
5207 return E_INVALIDARG; /* FIXME: correct? */
5210 /* ITypeInfo2::GetImplCustData
5212 * Gets the custom data
5214 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5215 ITypeInfo2 * iface,
5216 UINT index,
5217 REFGUID guid,
5218 VARIANT *pVarVal)
5220 ICOM_THIS( ITypeInfoImpl, iface);
5221 TLBCustData *pCData=NULL;
5222 TLBImplType * pRDesc;
5223 int i;
5225 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5227 if(pRDesc)
5229 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5231 if( IsEqualIID(guid, &pCData->guid)) break;
5235 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5237 if(pCData)
5239 VariantInit( pVarVal);
5240 VariantCopy( pVarVal, &pCData->data);
5241 return S_OK;
5243 return E_INVALIDARG; /* FIXME: correct? */
5246 /* ITypeInfo2::GetDocumentation2
5248 * Retrieves the documentation string, the complete Help file name and path,
5249 * the localization context to use, and the context ID for the library Help
5250 * topic in the Help file.
5253 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5254 ITypeInfo2 * iface,
5255 MEMBERID memid,
5256 LCID lcid,
5257 BSTR *pbstrHelpString,
5258 DWORD *pdwHelpStringContext,
5259 BSTR *pbstrHelpStringDll)
5261 ICOM_THIS( ITypeInfoImpl, iface);
5262 TLBFuncDesc * pFDesc;
5263 TLBVarDesc * pVDesc;
5264 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5265 "HelpStringContext(%p) HelpStringDll(%p)\n",
5266 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5267 pbstrHelpStringDll );
5268 /* the help string should be obtained from the helpstringdll,
5269 * using the _DLLGetDocumentation function, based on the supplied
5270 * lcid. Nice to do sometime...
5272 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5273 if(pbstrHelpString)
5274 *pbstrHelpString=SysAllocString(This->Name);
5275 if(pdwHelpStringContext)
5276 *pdwHelpStringContext=This->dwHelpStringContext;
5277 if(pbstrHelpStringDll)
5278 *pbstrHelpStringDll=
5279 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5280 return S_OK;
5281 }else {/* for a member */
5282 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5283 if(pFDesc->funcdesc.memid==memid){
5284 if(pbstrHelpString)
5285 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5286 if(pdwHelpStringContext)
5287 *pdwHelpStringContext=pFDesc->HelpStringContext;
5288 if(pbstrHelpStringDll)
5289 *pbstrHelpStringDll=
5290 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5291 return S_OK;
5293 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5294 if(pVDesc->vardesc.memid==memid){
5295 if(pbstrHelpString)
5296 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5297 if(pdwHelpStringContext)
5298 *pdwHelpStringContext=pVDesc->HelpStringContext;
5299 if(pbstrHelpStringDll)
5300 *pbstrHelpStringDll=
5301 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5302 return S_OK;
5305 return TYPE_E_ELEMENTNOTFOUND;
5308 /* ITypeInfo2::GetAllCustData
5310 * Gets all custom data items for the Type info.
5313 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5314 ITypeInfo2 * iface,
5315 CUSTDATA *pCustData)
5317 ICOM_THIS( ITypeInfoImpl, iface);
5318 TLBCustData *pCData;
5319 int i;
5321 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5323 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5324 if(pCustData->prgCustData ){
5325 pCustData->cCustData=This->ctCustData;
5326 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5327 pCustData->prgCustData[i].guid=pCData->guid;
5328 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5330 }else{
5331 ERR(" OUT OF MEMORY! \n");
5332 return E_OUTOFMEMORY;
5334 return S_OK;
5337 /* ITypeInfo2::GetAllFuncCustData
5339 * Gets all custom data items for the specified Function
5342 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5343 ITypeInfo2 * iface,
5344 UINT index,
5345 CUSTDATA *pCustData)
5347 ICOM_THIS( ITypeInfoImpl, iface);
5348 TLBCustData *pCData;
5349 TLBFuncDesc * pFDesc;
5350 int i;
5351 TRACE("(%p) index %d\n", This, index);
5352 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5353 pFDesc=pFDesc->next)
5355 if(pFDesc){
5356 pCustData->prgCustData =
5357 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5358 if(pCustData->prgCustData ){
5359 pCustData->cCustData=pFDesc->ctCustData;
5360 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5361 pCData = pCData->next){
5362 pCustData->prgCustData[i].guid=pCData->guid;
5363 VariantCopy(& pCustData->prgCustData[i].varValue,
5364 & pCData->data);
5366 }else{
5367 ERR(" OUT OF MEMORY! \n");
5368 return E_OUTOFMEMORY;
5370 return S_OK;
5372 return TYPE_E_ELEMENTNOTFOUND;
5375 /* ITypeInfo2::GetAllParamCustData
5377 * Gets all custom data items for the Functions
5380 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5381 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5383 ICOM_THIS( ITypeInfoImpl, iface);
5384 TLBCustData *pCData=NULL;
5385 TLBFuncDesc * pFDesc;
5386 int i;
5387 TRACE("(%p) index %d\n", This, indexFunc);
5388 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5389 pFDesc=pFDesc->next)
5391 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5392 pCustData->prgCustData =
5393 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5394 sizeof(CUSTDATAITEM));
5395 if(pCustData->prgCustData ){
5396 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5397 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5398 pCData; i++, pCData = pCData->next){
5399 pCustData->prgCustData[i].guid=pCData->guid;
5400 VariantCopy(& pCustData->prgCustData[i].varValue,
5401 & pCData->data);
5403 }else{
5404 ERR(" OUT OF MEMORY! \n");
5405 return E_OUTOFMEMORY;
5407 return S_OK;
5409 return TYPE_E_ELEMENTNOTFOUND;
5412 /* ITypeInfo2::GetAllVarCustData
5414 * Gets all custom data items for the specified Variable
5417 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5418 UINT index, CUSTDATA *pCustData)
5420 ICOM_THIS( ITypeInfoImpl, iface);
5421 TLBCustData *pCData;
5422 TLBVarDesc * pVDesc;
5423 int i;
5424 TRACE("(%p) index %d\n", This, index);
5425 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5426 pVDesc=pVDesc->next)
5428 if(pVDesc){
5429 pCustData->prgCustData =
5430 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5431 if(pCustData->prgCustData ){
5432 pCustData->cCustData=pVDesc->ctCustData;
5433 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5434 pCData = pCData->next){
5435 pCustData->prgCustData[i].guid=pCData->guid;
5436 VariantCopy(& pCustData->prgCustData[i].varValue,
5437 & pCData->data);
5439 }else{
5440 ERR(" OUT OF MEMORY! \n");
5441 return E_OUTOFMEMORY;
5443 return S_OK;
5445 return TYPE_E_ELEMENTNOTFOUND;
5448 /* ITypeInfo2::GetAllImplCustData
5450 * Gets all custom data items for the specified implementation type
5453 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5454 ITypeInfo2 * iface,
5455 UINT index,
5456 CUSTDATA *pCustData)
5458 ICOM_THIS( ITypeInfoImpl, iface);
5459 TLBCustData *pCData;
5460 TLBImplType * pRDesc;
5461 int i;
5462 TRACE("(%p) index %d\n", This, index);
5463 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5464 pRDesc=pRDesc->next)
5466 if(pRDesc){
5467 pCustData->prgCustData =
5468 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5469 if(pCustData->prgCustData ){
5470 pCustData->cCustData=pRDesc->ctCustData;
5471 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5472 pCData = pCData->next){
5473 pCustData->prgCustData[i].guid=pCData->guid;
5474 VariantCopy(& pCustData->prgCustData[i].varValue,
5475 & pCData->data);
5477 }else{
5478 ERR(" OUT OF MEMORY! \n");
5479 return E_OUTOFMEMORY;
5481 return S_OK;
5483 return TYPE_E_ELEMENTNOTFOUND;
5486 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5488 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5490 ITypeInfo_fnQueryInterface,
5491 ITypeInfo_fnAddRef,
5492 ITypeInfo_fnRelease,
5494 ITypeInfo_fnGetTypeAttr,
5495 ITypeInfo_fnGetTypeComp,
5496 ITypeInfo_fnGetFuncDesc,
5497 ITypeInfo_fnGetVarDesc,
5498 ITypeInfo_fnGetNames,
5499 ITypeInfo_fnGetRefTypeOfImplType,
5500 ITypeInfo_fnGetImplTypeFlags,
5501 ITypeInfo_fnGetIDsOfNames,
5502 ITypeInfo_fnInvoke,
5503 ITypeInfo_fnGetDocumentation,
5504 ITypeInfo_fnGetDllEntry,
5505 ITypeInfo_fnGetRefTypeInfo,
5506 ITypeInfo_fnAddressOfMember,
5507 ITypeInfo_fnCreateInstance,
5508 ITypeInfo_fnGetMops,
5509 ITypeInfo_fnGetContainingTypeLib,
5510 ITypeInfo_fnReleaseTypeAttr,
5511 ITypeInfo_fnReleaseFuncDesc,
5512 ITypeInfo_fnReleaseVarDesc,
5514 ITypeInfo2_fnGetTypeKind,
5515 ITypeInfo2_fnGetTypeFlags,
5516 ITypeInfo2_fnGetFuncIndexOfMemId,
5517 ITypeInfo2_fnGetVarIndexOfMemId,
5518 ITypeInfo2_fnGetCustData,
5519 ITypeInfo2_fnGetFuncCustData,
5520 ITypeInfo2_fnGetParamCustData,
5521 ITypeInfo2_fnGetVarCustData,
5522 ITypeInfo2_fnGetImplTypeCustData,
5523 ITypeInfo2_fnGetDocumentation2,
5524 ITypeInfo2_fnGetAllCustData,
5525 ITypeInfo2_fnGetAllFuncCustData,
5526 ITypeInfo2_fnGetAllParamCustData,
5527 ITypeInfo2_fnGetAllVarCustData,
5528 ITypeInfo2_fnGetAllImplTypeCustData,
5531 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5533 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5535 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5538 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5540 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5542 return ITypeInfo_AddRef((ITypeInfo *)This);
5545 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5547 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5549 return ITypeInfo_Release((ITypeInfo *)This);
5552 static HRESULT WINAPI ITypeComp_fnBind(
5553 ITypeComp * iface,
5554 OLECHAR * szName,
5555 unsigned long lHash,
5556 unsigned short wFlags,
5557 ITypeInfo ** ppTInfo,
5558 DESCKIND * pDescKind,
5559 BINDPTR * pBindPtr)
5561 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5562 TLBFuncDesc * pFDesc;
5563 TLBVarDesc * pVDesc;
5565 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5567 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5568 if (pFDesc->funcdesc.invkind & wFlags)
5569 if (!strcmpW(pFDesc->Name, szName)) {
5570 break;
5573 if (pFDesc)
5575 *pDescKind = DESCKIND_FUNCDESC;
5576 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5577 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5578 return S_OK;
5579 } else {
5580 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5582 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5583 if (!strcmpW(pVDesc->Name, szName)) {
5584 *pDescKind = DESCKIND_VARDESC;
5585 pBindPtr->lpvardesc = &pVDesc->vardesc;
5586 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5587 return S_OK;
5592 /* not found, look for it in inherited interfaces */
5593 if ((This->TypeAttr.typekind == TKIND_INTERFACE) && This->TypeAttr.cImplTypes) {
5594 /* recursive search */
5595 ITypeInfo *pTInfo;
5596 ITypeComp *pTComp;
5597 HRESULT hr;
5598 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5599 if (SUCCEEDED(hr))
5601 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5602 ITypeInfo_Release(pTInfo);
5604 if (SUCCEEDED(hr))
5606 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5607 ITypeComp_Release(pTComp);
5608 return hr;
5610 WARN("Could not search inherited interface!\n");
5612 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5613 *pDescKind = DESCKIND_NONE;
5614 pBindPtr->lpfuncdesc = NULL;
5615 *ppTInfo = NULL;
5616 return DISP_E_MEMBERNOTFOUND;
5619 static HRESULT WINAPI ITypeComp_fnBindType(
5620 ITypeComp * iface,
5621 OLECHAR * szName,
5622 unsigned long lHash,
5623 ITypeInfo ** ppTInfo,
5624 ITypeComp ** ppTComp)
5626 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5628 /* strange behaviour (does nothing) but like the
5629 * original */
5631 if (!ppTInfo || !ppTComp)
5632 return E_POINTER;
5634 *ppTInfo = NULL;
5635 *ppTComp = NULL;
5637 return S_OK;
5640 static ICOM_VTABLE(ITypeComp) tcompvt =
5642 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5644 ITypeComp_fnQueryInterface,
5645 ITypeComp_fnAddRef,
5646 ITypeComp_fnRelease,
5648 ITypeComp_fnBind,
5649 ITypeComp_fnBindType