Fixed a couple of races with exiting threads in suspend_for_ptrace().
[wine/gsoc_dplay.git] / dlls / oleaut32 / typelib.c
blobc321d57d74d95d1edfd795f2c541ff61945305a2
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
47 * behaviour.
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
55 #include "config.h"
56 #include "wine/port.h"
58 #include <stdlib.h>
59 #include <string.h>
60 #include <stdio.h>
61 #include <ctype.h>
63 #define NONAMELESSUNION
64 #define NONAMELESSSTRUCT
65 #include "winerror.h"
66 #include "winnls.h" /* for PRIMARYLANGID */
67 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
68 #include "winuser.h"
70 #include "wine/unicode.h"
71 #include "objbase.h"
72 #include "heap.h"
73 #include "ole2disp.h"
74 #include "typelib.h"
75 #include "wine/debug.h"
76 #include "parsedt.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib);
81 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
82 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
84 /****************************************************************************
85 * FromLExxx
87 * Takes p_iVal (which is in little endian) and returns it
88 * in the host machine's byte order.
90 #ifdef WORDS_BIGENDIAN
91 static WORD FromLEWord(WORD p_iVal)
93 return (((p_iVal & 0x00FF) << 8) |
94 ((p_iVal & 0xFF00) >> 8));
98 static DWORD FromLEDWord(DWORD p_iVal)
100 return (((p_iVal & 0x000000FF) << 24) |
101 ((p_iVal & 0x0000FF00) << 8) |
102 ((p_iVal & 0x00FF0000) >> 8) |
103 ((p_iVal & 0xFF000000) >> 24));
105 #else
106 #define FromLEWord(X) (X)
107 #define FromLEDWord(X) (X)
108 #endif
111 /****************************************************************************
112 * FromLExxx
114 * Fix byte order in any structure if necessary
116 #ifdef WORDS_BIGENDIAN
117 static void FromLEWords(void *p_Val, int p_iSize)
119 WORD *Val = p_Val;
121 p_iSize /= sizeof(WORD);
123 while (p_iSize) {
124 *Val = FromLEWord(*Val);
125 Val++;
126 p_iSize--;
131 static void FromLEDWords(void *p_Val, int p_iSize)
133 DWORD *Val = p_Val;
135 p_iSize /= sizeof(DWORD);
137 while (p_iSize) {
138 *Val = FromLEDWord(*Val);
139 Val++;
140 p_iSize--;
143 #else
144 #define FromLEWords(X,Y) /*nothing*/
145 #define FromLEDWords(X,Y) /*nothing*/
146 #endif
149 /****************************************************************************
150 * QueryPathOfRegTypeLib [OLEAUT32.164]
151 * RETURNS
152 * path of typelib
154 HRESULT WINAPI
155 QueryPathOfRegTypeLib(
156 REFGUID guid, /* [in] referenced guid */
157 WORD wMaj, /* [in] major version */
158 WORD wMin, /* [in] minor version */
159 LCID lcid, /* [in] locale id */
160 LPBSTR path ) /* [out] path of typelib */
162 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
163 string termination character on output strings */
165 HRESULT hr = E_FAIL;
167 LCID myLCID = lcid;
169 char szXGUID[80];
170 char szTypeLibKey[100];
171 char szPath[MAX_PATH];
172 DWORD dwPathLen = sizeof(szPath);
174 if ( !HIWORD(guid) )
176 sprintf(szXGUID,
177 "<guid 0x%08lx>",
178 (DWORD) guid);
180 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
181 return E_FAIL;
184 while (hr != S_OK)
186 sprintf(szTypeLibKey,
187 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
188 guid->Data1, guid->Data2, guid->Data3,
189 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
190 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
191 wMaj,
192 wMin,
193 myLCID);
195 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
197 if (!lcid)
198 break;
199 else if (myLCID == lcid)
201 /* try with sub-langid */
202 myLCID = SUBLANGID(lcid);
204 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
206 /* try with system langid */
207 myLCID = 0;
209 else
211 break;
214 else
216 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
217 BSTR bstrPath = SysAllocStringLen(NULL,len);
219 MultiByteToWideChar(CP_ACP,
220 MB_PRECOMPOSED,
221 szPath,
222 dwPathLen,
223 bstrPath,
224 len);
225 *path = bstrPath;
226 hr = S_OK;
230 if (hr != S_OK)
231 TRACE_(typelib)("%s not found\n", szTypeLibKey);
233 return hr;
236 /******************************************************************************
237 * CreateTypeLib [OLEAUT32.160] creates a typelib
239 * RETURNS
240 * Success: S_OK
241 * Failure: Status
243 HRESULT WINAPI CreateTypeLib(
244 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
246 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
247 return E_FAIL;
249 /******************************************************************************
250 * LoadTypeLib [OLEAUT32.161]
251 * Loads and registers a type library
252 * NOTES
253 * Docs: OLECHAR FAR* szFile
254 * Docs: iTypeLib FAR* FAR* pptLib
256 * RETURNS
257 * Success: S_OK
258 * Failure: Status
260 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
262 HRESULT WINAPI LoadTypeLib(
263 const OLECHAR *szFile,/* [in] Name of file to load from */
264 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
266 TRACE("\n");
267 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
270 /******************************************************************************
271 * LoadTypeLibEx [OLEAUT32.183]
272 * Loads and optionally registers a type library
274 * RETURNS
275 * Success: S_OK
276 * Failure: Status
278 HRESULT WINAPI LoadTypeLibEx(
279 LPCOLESTR szFile, /* [in] Name of file to load from */
280 REGKIND regkind, /* [in] Specify kind of registration */
281 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
283 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
284 WCHAR *pIndexStr;
285 HRESULT res;
286 INT index = 1;
288 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
289 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
290 NULL)) {
292 /* Look for a trailing '\\' followed by an index */
293 pIndexStr = strrchrW(szFile, '\\');
294 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
295 index = atoiW(pIndexStr);
296 memcpy(szFileCopy, szFile,
297 (pIndexStr - szFile - 1) * sizeof(WCHAR));
298 szFileCopy[pIndexStr - szFile - 1] = '\0';
299 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
300 szPath,NULL))
301 return TYPE_E_CANTLOADLIBRARY;
302 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
303 return TYPE_E_CANTLOADLIBRARY;
304 } else {
305 WCHAR tstpath[260];
306 WCHAR stdole32tlb[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
307 int i;
309 lstrcpyW(tstpath,szFile);
310 CharLowerW(tstpath);
311 for (i=0;i<strlenW(tstpath);i++) {
312 if (tstpath[i] == 's') {
313 if (!strcmpW(tstpath+i,stdole32tlb)) {
314 MESSAGE("\n");
315 MESSAGE("**************************************************************************\n");
316 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
317 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
318 MESSAGE("on the Microsoft Download Pages.\n");
319 MESSAGE("**************************************************************************\n");
320 break;
324 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile));
325 return TYPE_E_CANTLOADLIBRARY;
329 TRACE("File %s index %d\n", debugstr_w(szPath), index);
331 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
333 if (SUCCEEDED(res))
334 switch(regkind)
336 case REGKIND_DEFAULT:
337 /* FIXME: is this correct? */
338 if (!szFile || !szFile[0] ||
339 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
340 break;
341 /* else fall-through */
342 case REGKIND_REGISTER:
343 /* FIXME: Help path? */
344 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
346 IUnknown_Release(*pptLib);
347 *pptLib = 0;
349 break;
350 case REGKIND_NONE:
351 break;
354 TRACE(" returns %08lx\n",res);
355 return res;
358 /******************************************************************************
359 * LoadRegTypeLib [OLEAUT32.162]
361 HRESULT WINAPI LoadRegTypeLib(
362 REFGUID rguid, /* [in] referenced guid */
363 WORD wVerMajor, /* [in] major version */
364 WORD wVerMinor, /* [in] minor version */
365 LCID lcid, /* [in] locale id */
366 ITypeLib **ppTLib) /* [out] path of typelib */
368 BSTR bstr=NULL;
369 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
371 if(SUCCEEDED(res))
373 res= LoadTypeLib(bstr, ppTLib);
374 SysFreeString(bstr);
377 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
379 return res;
383 /******************************************************************************
384 * RegisterTypeLib [OLEAUT32.163]
385 * Adds information about a type library to the System Registry
386 * NOTES
387 * Docs: ITypeLib FAR * ptlib
388 * Docs: OLECHAR FAR* szFullPath
389 * Docs: OLECHAR FAR* szHelpDir
391 * RETURNS
392 * Success: S_OK
393 * Failure: Status
395 HRESULT WINAPI RegisterTypeLib(
396 ITypeLib * ptlib, /* [in] Pointer to the library*/
397 OLECHAR * szFullPath, /* [in] full Path of the library*/
398 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
399 may be NULL*/
401 HRESULT res;
402 TLIBATTR *attr;
403 OLECHAR guid[80];
404 LPSTR guidA;
405 CHAR keyName[120];
406 HKEY key, subKey;
407 UINT types, tidx;
408 TYPEKIND kind;
409 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
411 if (ptlib == NULL || szFullPath == NULL)
412 return E_INVALIDARG;
414 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
415 return E_FAIL;
417 StringFromGUID2(&attr->guid, guid, 80);
418 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
419 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
420 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
421 HeapFree(GetProcessHeap(), 0, guidA);
423 res = S_OK;
424 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
425 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
427 LPOLESTR doc;
429 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
431 if (RegSetValueExW(key, NULL, 0, REG_SZ,
432 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
433 res = E_FAIL;
435 SysFreeString(doc);
437 else
438 res = E_FAIL;
440 /* FIXME: This *seems* to be 0 always, not sure though */
441 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
442 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
444 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
445 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
446 res = E_FAIL;
448 RegCloseKey(subKey);
450 else
451 res = E_FAIL;
453 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
454 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
456 CHAR buf[20];
457 /* FIXME: is %u correct? */
458 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
459 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
460 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
461 res = E_FAIL;
463 RegCloseKey(key);
465 else
466 res = E_FAIL;
468 /* register OLE Automation-compatible interfaces for this typelib */
469 types = ITypeLib_GetTypeInfoCount(ptlib);
470 for (tidx=0; tidx<types; tidx++) {
471 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
472 LPOLESTR name = NULL;
473 ITypeInfo *tinfo = NULL;
474 BOOL stop = FALSE;
475 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
476 switch (kind) {
477 case TKIND_INTERFACE:
478 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
479 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
480 break;
481 case TKIND_DISPATCH:
482 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
483 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
484 break;
485 case TKIND_COCLASS:
486 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
487 /* coclasses should probably not be registered? */
488 break;
489 default:
490 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
491 break;
493 if (tinfo) {
494 TYPEATTR *tattr = NULL;
495 ITypeInfo_GetTypeAttr(tinfo, &tattr);
496 if (tattr) {
497 TRACE_(typelib)("guid=%s, flags=%04x (",
498 debugstr_guid(&tattr->guid),
499 tattr->wTypeFlags);
500 if (TRACE_ON(typelib)) {
501 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
502 XX(FAPPOBJECT);
503 XX(FCANCREATE);
504 XX(FLICENSED);
505 XX(FPREDECLID);
506 XX(FHIDDEN);
507 XX(FCONTROL);
508 XX(FDUAL);
509 XX(FNONEXTENSIBLE);
510 XX(FOLEAUTOMATION);
511 XX(FRESTRICTED);
512 XX(FAGGREGATABLE);
513 XX(FREPLACEABLE);
514 XX(FDISPATCHABLE);
515 XX(FREVERSEBIND);
516 XX(FPROXY);
517 #undef XX
518 MESSAGE("\n");
521 * FIXME: The 1 is just here until we implement rpcrt4
522 * stub/proxy handling. Until then it helps IShield
523 * v6 to work.
525 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
527 /* register interface<->typelib coupling */
528 StringFromGUID2(&tattr->guid, guid, 80);
529 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
530 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
531 HeapFree(GetProcessHeap(), 0, guidA);
533 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
534 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
535 if (name)
536 RegSetValueExW(key, NULL, 0, REG_SZ,
537 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
539 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
540 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
541 RegSetValueExA(subKey, NULL, 0, REG_SZ,
542 PSOA, strlen(PSOA));
543 RegCloseKey(subKey);
545 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
546 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
547 RegSetValueExA(subKey, NULL, 0, REG_SZ,
548 PSOA, strlen(PSOA));
549 RegCloseKey(subKey);
552 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
553 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
554 CHAR ver[32];
555 StringFromGUID2(&attr->guid, guid, 80);
556 snprintf(ver, sizeof(ver), "%x.%x",
557 attr->wMajorVerNum, attr->wMinorVerNum);
558 RegSetValueExW(subKey, NULL, 0, REG_SZ,
559 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
560 RegSetValueExA(subKey, "Version", 0, REG_SZ,
561 ver, lstrlenA(ver));
562 RegCloseKey(subKey);
564 RegCloseKey(key);
567 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
569 ITypeInfo_Release(tinfo);
571 SysFreeString(name);
572 if (stop) break;
576 ITypeLib_ReleaseTLibAttr(ptlib, attr);
578 return res;
582 /******************************************************************************
583 * UnRegisterTypeLib [OLEAUT32.186]
584 * Removes information about a type library from the System Registry
585 * NOTES
587 * RETURNS
588 * Success: S_OK
589 * Failure: Status
591 HRESULT WINAPI UnRegisterTypeLib(
592 REFGUID libid, /* [in] Guid of the library */
593 WORD wVerMajor, /* [in] major version */
594 WORD wVerMinor, /* [in] minor version */
595 LCID lcid, /* [in] locale id */
596 SYSKIND syskind)
598 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
599 return S_OK; /* FIXME: pretend everything is OK */
602 /*======================= ITypeLib implementation =======================*/
604 typedef struct tagTLBCustData
606 GUID guid;
607 VARIANT data;
608 struct tagTLBCustData* next;
609 } TLBCustData;
611 /* data structure for import typelibs */
612 typedef struct tagTLBImpLib
614 int offset; /* offset in the file (MSFT)
615 offset in nametable (SLTG)
616 just used to identify library while reading
617 data from file */
618 GUID guid; /* libid */
619 BSTR name; /* name */
621 LCID lcid; /* lcid of imported typelib */
623 WORD wVersionMajor; /* major version number */
624 WORD wVersionMinor; /* minor version number */
626 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
627 NULL if not yet loaded */
628 struct tagTLBImpLib * next;
629 } TLBImpLib;
631 /* internal ITypeLib data */
632 typedef struct tagITypeLibImpl
634 ICOM_VFIELD(ITypeLib2);
635 UINT ref;
636 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
638 /* strings can be stored in tlb as multibyte strings BUT they are *always*
639 * exported to the application as a UNICODE string.
641 BSTR Name;
642 BSTR DocString;
643 BSTR HelpFile;
644 BSTR HelpStringDll;
645 unsigned long dwHelpContext;
646 int TypeInfoCount; /* nr of typeinfo's in librarry */
647 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
648 int ctCustData; /* number of items in cust data list */
649 TLBCustData * pCustData; /* linked list to cust data */
650 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
651 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
652 libary. Only used while read MSFT
653 typelibs */
654 } ITypeLibImpl;
656 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
658 /* ITypeLib methods */
659 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
660 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
662 /*======================= ITypeInfo implementation =======================*/
664 /* data for refernced types */
665 typedef struct tagTLBRefType
667 INT index; /* Type index for internal ref or for external ref
668 it the format is SLTG. -2 indicates to
669 use guid */
671 GUID guid; /* guid of the referenced type */
672 /* if index == TLB_REF_USE_GUID */
674 HREFTYPE reference; /* The href of this ref */
675 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
676 TLB_REF_INTERNAL for internal refs
677 TLB_REF_NOT_FOUND for broken refs */
679 struct tagTLBRefType * next;
680 } TLBRefType;
682 #define TLB_REF_USE_GUID -2
684 #define TLB_REF_INTERNAL (void*)-2
685 #define TLB_REF_NOT_FOUND (void*)-1
687 /* internal Parameter data */
688 typedef struct tagTLBParDesc
690 BSTR Name;
691 int ctCustData;
692 TLBCustData * pCustData; /* linked list to cust data */
693 } TLBParDesc;
695 /* internal Function data */
696 typedef struct tagTLBFuncDesc
698 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
699 BSTR Name; /* the name of this function */
700 TLBParDesc *pParamDesc; /* array with param names and custom data */
701 int helpcontext;
702 int HelpStringContext;
703 BSTR HelpString;
704 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
705 int ctCustData;
706 TLBCustData * pCustData; /* linked list to cust data; */
707 struct tagTLBFuncDesc * next;
708 } TLBFuncDesc;
710 /* internal Variable data */
711 typedef struct tagTLBVarDesc
713 VARDESC vardesc; /* lots of info on the variable and its attributes. */
714 BSTR Name; /* the name of this variable */
715 int HelpContext;
716 int HelpStringContext; /* FIXME: where? */
717 BSTR HelpString;
718 int ctCustData;
719 TLBCustData * pCustData;/* linked list to cust data; */
720 struct tagTLBVarDesc * next;
721 } TLBVarDesc;
723 /* internal implemented interface data */
724 typedef struct tagTLBImplType
726 HREFTYPE hRef; /* hRef of interface */
727 int implflags; /* IMPLFLAG_*s */
728 int ctCustData;
729 TLBCustData * pCustData;/* linked list to custom data; */
730 struct tagTLBImplType *next;
731 } TLBImplType;
733 /* internal TypeInfo data */
734 typedef struct tagITypeInfoImpl
736 ICOM_VFIELD(ITypeInfo2);
737 UINT ref;
738 TYPEATTR TypeAttr ; /* _lots_ of type information. */
739 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
740 int index; /* index in this typelib; */
741 /* type libs seem to store the doc strings in ascii
742 * so why should we do it in unicode?
744 BSTR Name;
745 BSTR DocString;
746 unsigned long dwHelpContext;
747 unsigned long dwHelpStringContext;
749 /* functions */
750 TLBFuncDesc * funclist; /* linked list with function descriptions */
752 /* variables */
753 TLBVarDesc * varlist; /* linked list with variable descriptions */
755 /* Implemented Interfaces */
756 TLBImplType * impltypelist;
758 TLBRefType * reflist;
759 int ctCustData;
760 TLBCustData * pCustData; /* linked list to cust data; */
761 struct tagITypeInfoImpl * next;
762 } ITypeInfoImpl;
764 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
766 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
768 typedef struct tagTLBContext
770 unsigned int oStart; /* start of TLB in file */
771 unsigned int pos; /* current pos */
772 unsigned int length; /* total length */
773 void *mapping; /* memory mapping */
774 MSFT_SegDir * pTblDir;
775 ITypeLibImpl* pLibInfo;
776 } TLBContext;
779 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
782 debug
784 static void dump_VarType(VARTYPE vt,char *szVarType) {
785 /* FIXME : we could have better trace here, depending on the VARTYPE
786 * of the variant
788 if (vt & VT_RESERVED)
789 szVarType += strlen(strcpy(szVarType, "reserved | "));
790 if (vt & VT_BYREF)
791 szVarType += strlen(strcpy(szVarType, "ref to "));
792 if (vt & VT_ARRAY)
793 szVarType += strlen(strcpy(szVarType, "array of "));
794 if (vt & VT_VECTOR)
795 szVarType += strlen(strcpy(szVarType, "vector of "));
796 switch(vt & VT_TYPEMASK) {
797 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
798 case VT_I2: sprintf(szVarType, "VT_I2"); break;
799 case VT_I4: sprintf(szVarType, "VT_I4"); break;
800 case VT_R4: sprintf(szVarType, "VT_R4"); break;
801 case VT_R8: sprintf(szVarType, "VT_R8"); break;
802 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
803 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
804 case VT_CY: sprintf(szVarType, "VT_CY"); break;
805 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
806 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
807 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
808 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
809 case VT_I1: sprintf(szVarType, "VT_I1"); break;
810 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
811 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
812 case VT_INT: sprintf(szVarType, "VT_INT"); break;
813 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
814 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
815 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
816 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
817 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
821 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
822 if (pTD->vt & VT_RESERVED)
823 szVarType += strlen(strcpy(szVarType, "reserved | "));
824 if (pTD->vt & VT_BYREF)
825 szVarType += strlen(strcpy(szVarType, "ref to "));
826 if (pTD->vt & VT_ARRAY)
827 szVarType += strlen(strcpy(szVarType, "array of "));
828 if (pTD->vt & VT_VECTOR)
829 szVarType += strlen(strcpy(szVarType, "vector of "));
830 switch(pTD->vt & VT_TYPEMASK) {
831 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
832 case VT_I2: sprintf(szVarType, "VT_I2"); break;
833 case VT_I4: sprintf(szVarType, "VT_I4"); break;
834 case VT_R4: sprintf(szVarType, "VT_R4"); break;
835 case VT_R8: sprintf(szVarType, "VT_R8"); break;
836 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
837 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
838 case VT_CY: sprintf(szVarType, "VT_CY"); break;
839 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
840 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
841 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
842 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
843 case VT_I1: sprintf(szVarType, "VT_I1"); break;
844 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
845 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
846 case VT_INT: sprintf(szVarType, "VT_INT"); break;
847 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
848 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
849 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
850 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
851 pTD->u.hreftype); break;
852 case VT_PTR: sprintf(szVarType, "ptr to ");
853 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
854 break;
855 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
856 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
857 break;
858 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
859 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
860 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
861 break;
863 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
867 void dump_ELEMDESC(ELEMDESC *edesc) {
868 char buf[200];
869 dump_TypeDesc(&edesc->tdesc,buf);
870 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
871 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
872 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
874 void dump_FUNCDESC(FUNCDESC *funcdesc) {
875 int i;
876 MESSAGE("memid is %08lx\n",funcdesc->memid);
877 for (i=0;i<funcdesc->cParams;i++) {
878 MESSAGE("Param %d:\n",i);
879 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
881 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
882 switch (funcdesc->funckind) {
883 case FUNC_VIRTUAL: MESSAGE("virtual");break;
884 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
885 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
886 case FUNC_STATIC: MESSAGE("static");break;
887 case FUNC_DISPATCH: MESSAGE("dispatch");break;
888 default: MESSAGE("unknown");break;
890 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
891 switch (funcdesc->invkind) {
892 case INVOKE_FUNC: MESSAGE("func");break;
893 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
894 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
895 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
897 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
898 switch (funcdesc->callconv) {
899 case CC_CDECL: MESSAGE("cdecl");break;
900 case CC_PASCAL: MESSAGE("pascal");break;
901 case CC_STDCALL: MESSAGE("stdcall");break;
902 case CC_SYSCALL: MESSAGE("syscall");break;
903 default:break;
905 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
906 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
907 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
910 void dump_IDLDESC(IDLDESC *idl) {
911 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
914 static char * typekind_desc[] =
916 "TKIND_ENUM",
917 "TKIND_RECORD",
918 "TKIND_MODULE",
919 "TKIND_INTERFACE",
920 "TKIND_DISPATCH",
921 "TKIND_COCLASS",
922 "TKIND_ALIAS",
923 "TKIND_UNION",
924 "TKIND_MAX"
927 void dump_TYPEATTR(TYPEATTR *tattr) {
928 char buf[200];
929 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
930 MESSAGE("\tlcid: %ld\n",tattr->lcid);
931 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
932 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
933 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
934 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
935 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
936 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
937 MESSAGE("\tcVars: %d\n", tattr->cVars);
938 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
939 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
940 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
941 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
942 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
943 dump_TypeDesc(&tattr->tdescAlias,buf);
944 MESSAGE("\ttypedesc: %s\n", buf);
945 dump_IDLDESC(&tattr->idldescType);
948 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
950 int i;
951 if (!TRACE_ON(typelib))
952 return;
953 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
954 for (i=0;i<pfd->funcdesc.cParams;i++)
955 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
958 dump_FUNCDESC(&(pfd->funcdesc));
960 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
961 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
963 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
965 while (pfd)
967 dump_TLBFuncDescOne(pfd);
968 pfd = pfd->next;
971 static void dump_TLBVarDesc(TLBVarDesc * pvd)
973 while (pvd)
975 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
976 pvd = pvd->next;
980 static void dump_TLBImpLib(TLBImpLib *import)
982 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
983 debugstr_w(import->name));
984 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
985 import->wVersionMinor, import->lcid, import->offset);
988 static void dump_TLBRefType(TLBRefType * prt)
990 while (prt)
992 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
993 if(prt->index == -1)
994 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
995 else
996 TRACE_(typelib)("type no: %d\n", prt->index);
998 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
999 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1000 TRACE_(typelib)("in lib\n");
1001 dump_TLBImpLib(prt->pImpTLInfo);
1003 prt = prt->next;
1007 static void dump_TLBImplType(TLBImplType * impl)
1009 while (impl) {
1010 TRACE_(typelib)(
1011 "implementing/inheriting interface hRef = %lx implflags %x\n",
1012 impl->hRef, impl->implflags);
1013 impl = impl->next;
1017 void dump_Variant(VARIANT * pvar)
1019 char szVarType[32];
1020 LPVOID ref;
1022 TRACE("(%p)\n", pvar);
1024 if (!pvar) return;
1026 ZeroMemory(szVarType, sizeof(szVarType));
1028 /* FIXME : we could have better trace here, depending on the VARTYPE
1029 * of the variant
1031 dump_VarType(V_VT(pvar),szVarType);
1033 TRACE("VARTYPE: %s\n", szVarType);
1035 if (V_VT(pvar) & VT_BYREF) {
1036 ref = V_UNION(pvar, byref);
1037 TRACE("%p\n", ref);
1039 else ref = &V_UNION(pvar, cVal);
1041 if (V_VT(pvar) & VT_ARRAY) {
1042 /* FIXME */
1043 return;
1045 if (V_VT(pvar) & VT_VECTOR) {
1046 /* FIXME */
1047 return;
1050 switch (V_VT(pvar) & VT_TYPEMASK)
1052 case VT_I2:
1053 TRACE("%d\n", *(short*)ref);
1054 break;
1056 case VT_UI4:
1057 case VT_UINT:
1058 TRACE("%u\n", *(UINT*)ref);
1059 break;
1061 case VT_I4:
1062 case VT_INT:
1063 TRACE("%d\n", *(INT*)ref);
1064 break;
1066 case VT_R4:
1067 TRACE("%3.3e\n", *(float*)ref);
1068 break;
1070 case VT_R8:
1071 TRACE("%3.3e\n", *(double*)ref);
1072 break;
1074 case VT_BOOL:
1075 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1076 break;
1078 case VT_BSTR:
1079 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1080 break;
1082 case VT_UNKNOWN:
1083 case VT_DISPATCH:
1084 TRACE("%p\n", *(LPVOID*)ref);
1085 break;
1087 case VT_VARIANT:
1088 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1089 break;
1091 case VT_DATE:
1093 struct tm TM;
1094 memset( &TM, 0, sizeof(TM) );
1096 if( DateToTm( *(DATE*)ref, 0, &TM ) == FALSE ) {
1097 TRACE("invalid date? (?)%ld %f\n", *(long*)ref, *(double *)ref);
1098 } else {
1099 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1100 TM.tm_year, TM.tm_mon+1, TM.tm_mday,
1101 TM.tm_hour, TM.tm_min, TM.tm_sec, *(double *)ref);
1103 break;
1106 case VT_CY:
1107 TRACE("%ld (hi), %lu (lo)\n", ((CY *)ref)->s.Hi, ((CY *)ref)->s.Lo);
1108 break;
1111 default:
1112 TRACE("(?)%ld\n", *(long*)ref);
1113 break;
1117 static void dump_DispParms(DISPPARAMS * pdp)
1119 int index = 0;
1121 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1123 while (index < pdp->cArgs)
1125 dump_Variant( &pdp->rgvarg[index] );
1126 ++index;
1130 static void dump_TypeInfo(ITypeInfoImpl * pty)
1132 TRACE("%p ref=%u\n", pty, pty->ref);
1133 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1134 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1135 TRACE("fct:%u var:%u impl:%u\n",
1136 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1137 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1138 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1139 dump_TLBFuncDesc(pty->funclist);
1140 dump_TLBVarDesc(pty->varlist);
1141 dump_TLBImplType(pty->impltypelist);
1144 void dump_VARDESC(VARDESC *v)
1146 MESSAGE("memid %ld\n",v->memid);
1147 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1148 MESSAGE("oInst %ld\n",v->u.oInst);
1149 dump_ELEMDESC(&(v->elemdescVar));
1150 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1151 MESSAGE("varkind %d\n",v->varkind);
1154 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1156 /* VT_LPWSTR is largest type that */
1157 /* may appear in type description*/
1158 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1159 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1160 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1161 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1162 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1163 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1164 {{0},30},{{0},31}
1167 static void TLB_abort()
1169 DebugBreak();
1171 static void * TLB_Alloc(unsigned size)
1173 void * ret;
1174 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1175 /* FIXME */
1176 ERR("cannot allocate memory\n");
1178 return ret;
1181 static void TLB_Free(void * ptr)
1183 HeapFree(GetProcessHeap(), 0, ptr);
1187 /**********************************************************************
1189 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1191 /* read function */
1192 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1194 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1195 pcx->pos, count, pcx->oStart, pcx->length, where);
1197 if (where != DO_NOT_SEEK)
1199 where += pcx->oStart;
1200 if (where > pcx->length)
1202 /* FIXME */
1203 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1204 TLB_abort();
1206 pcx->pos = where;
1208 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1209 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1210 pcx->pos += count;
1211 return count;
1214 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1215 long where )
1217 DWORD ret;
1219 ret = MSFT_Read(buffer, count, pcx, where);
1220 FromLEDWords(buffer, ret);
1222 return ret;
1225 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1226 long where )
1228 DWORD ret;
1230 ret = MSFT_Read(buffer, count, pcx, where);
1231 FromLEWords(buffer, ret);
1233 return ret;
1236 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1238 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1239 memset(pGuid,0, sizeof(GUID));
1240 return;
1242 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1243 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1244 pGuid->Data2 = FromLEWord(pGuid->Data2);
1245 pGuid->Data3 = FromLEWord(pGuid->Data3);
1246 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1249 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1251 char * name;
1252 MSFT_NameIntro niName;
1253 int lengthInChars;
1254 WCHAR* pwstring = NULL;
1255 BSTR bstrName = NULL;
1257 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1258 pcx->pTblDir->pNametab.offset+offset);
1259 niName.namelen &= 0xFF; /* FIXME: correct ? */
1260 name=TLB_Alloc((niName.namelen & 0xff) +1);
1261 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1262 name[niName.namelen & 0xff]='\0';
1264 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1265 name, -1, NULL, 0);
1267 /* no invalid characters in string */
1268 if (lengthInChars)
1270 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1272 /* don't check for invalid character since this has been done previously */
1273 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1275 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1276 lengthInChars = SysStringLen(bstrName);
1277 HeapFree(GetProcessHeap(), 0, pwstring);
1280 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1281 return bstrName;
1284 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1286 char * string;
1287 INT16 length;
1288 int lengthInChars;
1289 BSTR bstr = NULL;
1291 if(offset<0) return NULL;
1292 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1293 if(length <= 0) return 0;
1294 string=TLB_Alloc(length +1);
1295 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1296 string[length]='\0';
1298 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1299 string, -1, NULL, 0);
1301 /* no invalid characters in string */
1302 if (lengthInChars)
1304 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1306 /* don't check for invalid character since this has been done previously */
1307 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1309 bstr = SysAllocStringLen(pwstring, lengthInChars);
1310 lengthInChars = SysStringLen(bstr);
1311 HeapFree(GetProcessHeap(), 0, pwstring);
1314 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1315 return bstr;
1318 * read a value and fill a VARIANT structure
1320 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1322 int size;
1324 TRACE_(typelib)("\n");
1326 if(offset <0) { /* data are packed in here */
1327 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1328 V_UNION(pVar, iVal) = offset & 0xffff;
1329 return;
1331 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1332 pcx->pTblDir->pCustData.offset + offset );
1333 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1334 switch (V_VT(pVar)){
1335 case VT_EMPTY: /* FIXME: is this right? */
1336 case VT_NULL: /* FIXME: is this right? */
1337 case VT_I2 : /* this should not happen */
1338 case VT_I4 :
1339 case VT_R4 :
1340 case VT_ERROR :
1341 case VT_BOOL :
1342 case VT_I1 :
1343 case VT_UI1 :
1344 case VT_UI2 :
1345 case VT_UI4 :
1346 case VT_INT :
1347 case VT_UINT :
1348 case VT_VOID : /* FIXME: is this right? */
1349 case VT_HRESULT :
1350 size=4; break;
1351 case VT_R8 :
1352 case VT_CY :
1353 case VT_DATE :
1354 case VT_I8 :
1355 case VT_UI8 :
1356 case VT_DECIMAL : /* FIXME: is this right? */
1357 case VT_FILETIME :
1358 size=8;break;
1359 /* pointer types with known behaviour */
1360 case VT_BSTR :{
1361 char * ptr;
1362 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1363 if(size <= 0) {
1364 FIXME("BSTR length = %d?\n", size);
1365 } else {
1366 ptr=TLB_Alloc(size);/* allocate temp buffer */
1367 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1368 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1369 /* FIXME: do we need a AtoW conversion here? */
1370 V_UNION(pVar, bstrVal[size])=L'\0';
1371 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1372 TLB_Free(ptr);
1375 size=-4; break;
1376 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1377 case VT_DISPATCH :
1378 case VT_VARIANT :
1379 case VT_UNKNOWN :
1380 case VT_PTR :
1381 case VT_SAFEARRAY :
1382 case VT_CARRAY :
1383 case VT_USERDEFINED :
1384 case VT_LPSTR :
1385 case VT_LPWSTR :
1386 case VT_BLOB :
1387 case VT_STREAM :
1388 case VT_STORAGE :
1389 case VT_STREAMED_OBJECT :
1390 case VT_STORED_OBJECT :
1391 case VT_BLOB_OBJECT :
1392 case VT_CF :
1393 case VT_CLSID :
1394 default:
1395 size=0;
1396 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1397 V_VT(pVar));
1400 if(size>0) /* (big|small) endian correct? */
1401 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1402 return;
1405 * create a linked list with custom data
1407 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1409 MSFT_CDGuid entry;
1410 TLBCustData* pNew;
1411 int count=0;
1413 TRACE_(typelib)("\n");
1415 while(offset >=0){
1416 count++;
1417 pNew=TLB_Alloc(sizeof(TLBCustData));
1418 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1419 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1420 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1421 /* add new custom data at head of the list */
1422 pNew->next=*ppCustData;
1423 *ppCustData=pNew;
1424 offset = entry.next;
1426 return count;
1429 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1430 ITypeInfoImpl *pTI)
1432 if(type <0)
1433 pTd->vt=type & VT_TYPEMASK;
1434 else
1435 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1437 if(pTd->vt == VT_USERDEFINED)
1438 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1440 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1443 static void
1444 MSFT_DoFuncs(TLBContext* pcx,
1445 ITypeInfoImpl* pTI,
1446 int cFuncs,
1447 int cVars,
1448 int offset,
1449 TLBFuncDesc** pptfd)
1452 * member information is stored in a data structure at offset
1453 * indicated by the memoffset field of the typeinfo structure
1454 * There are several distinctive parts.
1455 * the first part starts with a field that holds the total length
1456 * of this (first) part excluding this field. Then follow the records,
1457 * for each member there is one record.
1459 * First entry is always the length of the record (excluding this
1460 * length word).
1461 * Rest of the record depends on the type of the member. If there is
1462 * a field indicating the member type (function variable intereface etc)
1463 * I have not found it yet. At this time we depend on the information
1464 * in the type info and the usual order how things are stored.
1466 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1467 * for each member;
1469 * Third is a equal sized array with file offsets to the name entry
1470 * of each member.
1472 * Forth and last (?) part is an array with offsets to the records in the
1473 * first part of this file segment.
1476 int infolen, nameoffset, reclength, nrattributes, i;
1477 int recoffset = offset + sizeof(INT);
1479 char recbuf[512];
1480 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1482 TRACE_(typelib)("\n");
1484 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1486 for ( i = 0; i < cFuncs ; i++ )
1488 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1490 /* name, eventually add to a hash table */
1491 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1492 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1494 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1496 /* read the function information record */
1497 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1499 reclength &= 0x1ff;
1501 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1503 /* do the attributes */
1504 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1505 / sizeof(int);
1507 if ( nrattributes > 0 )
1509 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1511 if ( nrattributes > 1 )
1513 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1514 pFuncRec->OptAttr[1]) ;
1516 if ( nrattributes > 2 )
1518 if ( pFuncRec->FKCCIC & 0x2000 )
1520 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1522 else
1524 (*pptfd)->Entry = MSFT_ReadString(pcx,
1525 pFuncRec->OptAttr[2]);
1527 if( nrattributes > 5 )
1529 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1531 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1533 MSFT_CustData(pcx,
1534 pFuncRec->OptAttr[6],
1535 &(*pptfd)->pCustData);
1542 /* fill the FuncDesc Structure */
1543 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1544 offset + infolen + ( i + 1) * sizeof(INT));
1546 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1547 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1548 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1549 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1550 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1551 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1552 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1554 MSFT_GetTdesc(pcx,
1555 pFuncRec->DataType,
1556 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1557 pTI);
1559 /* do the parameters/arguments */
1560 if(pFuncRec->nrargs)
1562 int j = 0;
1563 MSFT_ParameterInfo paraminfo;
1565 (*pptfd)->funcdesc.lprgelemdescParam =
1566 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1568 (*pptfd)->pParamDesc =
1569 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1571 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1572 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1574 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1576 TYPEDESC* lpArgTypeDesc = 0;
1578 MSFT_GetTdesc(pcx,
1579 paraminfo.DataType,
1580 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1581 pTI);
1583 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1585 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1587 /* SEEK value = jump to offset,
1588 * from there jump to the end of record,
1589 * go back by (j-1) arguments
1591 MSFT_ReadLEDWords( &paraminfo ,
1592 sizeof(MSFT_ParameterInfo), pcx,
1593 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1594 * sizeof(MSFT_ParameterInfo)));
1595 lpArgTypeDesc =
1596 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1598 while ( lpArgTypeDesc != NULL )
1600 switch ( lpArgTypeDesc->vt )
1602 case VT_PTR:
1603 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1604 break;
1606 case VT_CARRAY:
1607 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1608 break;
1610 case VT_USERDEFINED:
1611 MSFT_DoRefType(pcx, pTI,
1612 lpArgTypeDesc->u.hreftype);
1614 lpArgTypeDesc = NULL;
1615 break;
1617 default:
1618 lpArgTypeDesc = NULL;
1624 /* parameter is the return value! */
1625 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1627 TYPEDESC* lpArgTypeDesc;
1629 (*pptfd)->funcdesc.elemdescFunc =
1630 (*pptfd)->funcdesc.lprgelemdescParam[j];
1632 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1634 while ( lpArgTypeDesc != NULL )
1636 switch ( lpArgTypeDesc->vt )
1638 case VT_PTR:
1639 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1640 break;
1641 case VT_CARRAY:
1642 lpArgTypeDesc =
1643 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1645 break;
1647 case VT_USERDEFINED:
1648 MSFT_DoRefType(pcx,
1649 pTI,
1650 lpArgTypeDesc->u.hreftype);
1652 lpArgTypeDesc = NULL;
1653 break;
1655 default:
1656 lpArgTypeDesc = NULL;
1661 /* second time around */
1662 for(j=0;j<pFuncRec->nrargs;j++)
1664 /* name */
1665 (*pptfd)->pParamDesc[j].Name =
1666 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1668 /* default value */
1669 if ( (PARAMFLAG_FHASDEFAULT &
1670 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1671 ((pFuncRec->FKCCIC) & 0x1000) )
1673 INT* pInt = (INT *)((char *)pFuncRec +
1674 reclength -
1675 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1677 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1679 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1680 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1682 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1683 pInt[j], pcx);
1685 /* custom info */
1686 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1688 MSFT_CustData(pcx,
1689 pFuncRec->OptAttr[7+j],
1690 &(*pptfd)->pParamDesc[j].pCustData);
1695 /* scode is not used: archaic win16 stuff FIXME: right? */
1696 (*pptfd)->funcdesc.cScodes = 0 ;
1697 (*pptfd)->funcdesc.lprgscode = NULL ;
1699 pptfd = & ((*pptfd)->next);
1700 recoffset += reclength;
1703 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1704 int cVars, int offset, TLBVarDesc ** pptvd)
1706 int infolen, nameoffset, reclength;
1707 char recbuf[256];
1708 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1709 int i;
1710 int recoffset;
1712 TRACE_(typelib)("\n");
1714 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1715 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1716 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1717 recoffset += offset+sizeof(INT);
1718 for(i=0;i<cVars;i++){
1719 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1720 /* name, eventually add to a hash table */
1721 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1722 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1723 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1724 /* read the variable information record */
1725 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1726 reclength &=0xff;
1727 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1728 /* Optional data */
1729 if(reclength >(6*sizeof(INT)) )
1730 (*pptvd)->HelpContext=pVarRec->HelpContext;
1731 if(reclength >(7*sizeof(INT)) )
1732 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1733 if(reclength >(8*sizeof(INT)) )
1734 if(reclength >(9*sizeof(INT)) )
1735 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1736 /* fill the VarDesc Structure */
1737 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1738 offset + infolen + ( i + 1) * sizeof(INT));
1739 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1740 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1741 MSFT_GetTdesc(pcx, pVarRec->DataType,
1742 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1743 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1744 if(pVarRec->VarKind == VAR_CONST ){
1745 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1746 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1747 pVarRec->OffsValue, pcx);
1748 } else
1749 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1750 pptvd=&((*pptvd)->next);
1751 recoffset += reclength;
1754 /* fill in data for a hreftype (offset). When the refernced type is contained
1755 * in the typelib, it's just an (file) offset in the type info base dir.
1756 * If comes from import, it's an offset+1 in the ImpInfo table
1757 * */
1758 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1759 int offset)
1761 int j;
1762 TLBRefType **ppRefType = &pTI->reflist;
1764 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1766 while(*ppRefType) {
1767 if((*ppRefType)->reference == offset)
1768 return;
1769 ppRefType = &(*ppRefType)->next;
1772 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1773 sizeof(**ppRefType));
1775 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1776 /* external typelib */
1777 MSFT_ImpInfo impinfo;
1778 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1780 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1782 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1783 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1784 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1785 if(pImpLib->offset==impinfo.oImpFile) break;
1786 pImpLib=pImpLib->next;
1788 if(pImpLib){
1789 (*ppRefType)->reference=offset;
1790 (*ppRefType)->pImpTLInfo = pImpLib;
1791 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1792 (*ppRefType)->index = TLB_REF_USE_GUID;
1793 }else{
1794 ERR("Cannot find a reference\n");
1795 (*ppRefType)->reference=-1;
1796 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1798 }else{
1799 /* in this typelib */
1800 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1801 (*ppRefType)->reference=offset;
1802 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1806 /* process Implemented Interfaces of a com class */
1807 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1808 int offset)
1810 int i;
1811 MSFT_RefRecord refrec;
1812 TLBImplType **ppImpl = &pTI->impltypelist;
1814 TRACE_(typelib)("\n");
1816 for(i=0;i<count;i++){
1817 if(offset<0) break; /* paranoia */
1818 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1819 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1820 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1821 (*ppImpl)->hRef = refrec.reftype;
1822 (*ppImpl)->implflags=refrec.flags;
1823 (*ppImpl)->ctCustData=
1824 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1825 offset=refrec.onext;
1826 ppImpl=&((*ppImpl)->next);
1830 * process a typeinfo record
1832 ITypeInfoImpl * MSFT_DoTypeInfo(
1833 TLBContext *pcx,
1834 int count,
1835 ITypeLibImpl * pLibInfo)
1837 MSFT_TypeInfoBase tiBase;
1838 ITypeInfoImpl *ptiRet;
1840 TRACE_(typelib)("count=%u\n", count);
1842 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1843 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
1844 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1845 /* this is where we are coming from */
1846 ptiRet->pTypeLib = pLibInfo;
1847 ITypeLib2_AddRef((ITypeLib2 *)pLibInfo);
1848 ptiRet->index=count;
1849 /* fill in the typeattr fields */
1850 FIXME("Assign constructor/destructor memid\n");
1852 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1853 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1854 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1855 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1856 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1857 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1858 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1859 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1860 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1861 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1862 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1863 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1864 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1865 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1866 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1867 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1868 MSFT_GetTdesc(pcx, tiBase.datatype1,
1869 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1871 /* FIXME: */
1872 /* IDLDESC idldescType; *//* never saw this one != zero */
1874 /* name, eventually add to a hash table */
1875 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1876 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1877 /* help info */
1878 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1879 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1880 ptiRet->dwHelpContext=tiBase.helpcontext;
1881 /* note: InfoType's Help file and HelpStringDll come from the containing
1882 * library. Further HelpString and Docstring appear to be the same thing :(
1884 /* functions */
1885 if(ptiRet->TypeAttr.cFuncs >0 )
1886 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1887 ptiRet->TypeAttr.cVars,
1888 tiBase.memoffset, & ptiRet->funclist);
1889 /* variables */
1890 if(ptiRet->TypeAttr.cVars >0 )
1891 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1892 ptiRet->TypeAttr.cVars,
1893 tiBase.memoffset, & ptiRet->varlist);
1894 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1895 switch(ptiRet->TypeAttr.typekind)
1897 case TKIND_COCLASS:
1898 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1899 tiBase.datatype1);
1900 break;
1901 case TKIND_DISPATCH:
1902 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1904 if (tiBase.datatype1 != -1)
1906 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1907 ptiRet->impltypelist->hRef = tiBase.datatype1;
1909 else
1910 { /* FIXME: This is a really bad hack to add IDispatch */
1911 char* szStdOle = "stdole2.tlb\0";
1912 int nStdOleLen = strlen(szStdOle);
1913 TLBRefType **ppRef = &ptiRet->reflist;
1915 while(*ppRef) {
1916 if((*ppRef)->reference == -1)
1917 break;
1918 ppRef = &(*ppRef)->next;
1920 if(!*ppRef) {
1921 *ppRef = TLB_Alloc(sizeof(**ppRef));
1922 (*ppRef)->guid = IID_IDispatch;
1923 (*ppRef)->reference = -1;
1924 (*ppRef)->index = TLB_REF_USE_GUID;
1925 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1926 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1927 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1928 nStdOleLen + 1);
1930 MultiByteToWideChar(CP_ACP,
1931 MB_PRECOMPOSED,
1932 szStdOle,
1934 (*ppRef)->pImpTLInfo->name,
1935 SysStringLen((*ppRef)->pImpTLInfo->name));
1937 (*ppRef)->pImpTLInfo->lcid = 0;
1938 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1939 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1942 break;
1943 default:
1944 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1945 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1946 ptiRet->impltypelist->hRef = tiBase.datatype1;
1947 break;
1950 ptiRet->ctCustData=
1951 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1953 TRACE_(typelib)("%s guid: %s kind:%s\n",
1954 debugstr_w(ptiRet->Name),
1955 debugstr_guid(&ptiRet->TypeAttr.guid),
1956 typekind_desc[ptiRet->TypeAttr.typekind]);
1958 return ptiRet;
1961 /****************************************************************************
1962 * TLB_ReadTypeLib
1964 * find the type of the typelib file and map the typelib resource into
1965 * the memory
1967 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1968 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1969 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1971 int ret = TYPE_E_CANTLOADLIBRARY;
1972 DWORD dwSignature = 0;
1973 HANDLE hFile;
1975 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1977 *ppTypeLib = NULL;
1979 /* check the signature of the file */
1980 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1981 if (INVALID_HANDLE_VALUE != hFile)
1983 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1984 if (hMapping)
1986 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1987 if(pBase)
1989 /* retrieve file size */
1990 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1992 /* first try to load as *.tlb */
1993 dwSignature = FromLEDWord(*((DWORD*) pBase));
1994 if ( dwSignature == MSFT_SIGNATURE)
1996 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1998 else if ( dwSignature == SLTG_SIGNATURE)
2000 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2002 UnmapViewOfFile(pBase);
2004 CloseHandle(hMapping);
2006 CloseHandle(hFile);
2009 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2011 /* find the typelibrary resource*/
2012 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2013 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2014 if (hinstDLL)
2016 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2017 "TYPELIB");
2018 if (hrsrc)
2020 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2021 if (hGlobal)
2023 LPVOID pBase = LockResource(hGlobal);
2024 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2026 if (pBase)
2028 /* try to load as incore resource */
2029 dwSignature = FromLEDWord(*((DWORD*) pBase));
2030 if ( dwSignature == MSFT_SIGNATURE)
2032 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2034 else if ( dwSignature == SLTG_SIGNATURE)
2036 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2038 else
2040 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2043 FreeResource( hGlobal );
2046 FreeLibrary(hinstDLL);
2050 if(*ppTypeLib)
2051 ret = S_OK;
2052 else
2053 ERR("Loading of typelib %s failed with error %ld\n",
2054 debugstr_w(pszFileName), GetLastError());
2056 return ret;
2059 /*================== ITypeLib(2) Methods ===================================*/
2061 /****************************************************************************
2062 * ITypeLib2_Constructor_MSFT
2064 * loading an MSFT typelib from an in-memory image
2066 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2068 TLBContext cx;
2069 long lPSegDir;
2070 MSFT_Header tlbHeader;
2071 MSFT_SegDir tlbSegDir;
2072 ITypeLibImpl * pTypeLibImpl;
2074 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2076 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2077 if (!pTypeLibImpl) return NULL;
2079 pTypeLibImpl->lpVtbl = &tlbvt;
2080 pTypeLibImpl->ref = 1;
2082 /* get pointer to beginning of typelib data */
2083 cx.pos = 0;
2084 cx.oStart=0;
2085 cx.mapping = pLib;
2086 cx.pLibInfo = pTypeLibImpl;
2087 cx.length = dwTLBLength;
2089 /* read header */
2090 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2091 TRACE("header:\n");
2092 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2093 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2094 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2095 return NULL;
2097 /* there is a small amount of information here until the next important
2098 * part:
2099 * the segment directory . Try to calculate the amount of data */
2100 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2102 /* now read the segment directory */
2103 TRACE("read segment directory (at %ld)\n",lPSegDir);
2104 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2105 cx.pTblDir = &tlbSegDir;
2107 /* just check two entries */
2108 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2110 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2111 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2112 return NULL;
2115 /* now fill our internal data */
2116 /* TLIBATTR fields */
2117 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2119 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2120 /* Windows seems to have zero here, is this correct? */
2121 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2122 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2123 else
2124 pTypeLibImpl->LibAttr.lcid = 0;
2126 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2127 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2128 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2129 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2131 /* name, eventually add to a hash table */
2132 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2134 /* help info */
2135 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2136 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2138 if( tlbHeader.varflags & HELPDLLFLAG)
2140 int offset;
2141 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2142 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2145 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2147 /* custom data */
2148 if(tlbHeader.CustomDataOffset >= 0)
2150 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2153 /* fill in typedescriptions */
2154 if(tlbSegDir.pTypdescTab.length > 0)
2156 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2157 INT16 td[4];
2158 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2159 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2160 for(i=0; i<cTD; )
2162 /* FIXME: add several sanity checks here */
2163 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2164 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2166 /* FIXME: check safearray */
2167 if(td[3] < 0)
2168 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2169 else
2170 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2172 else if(td[0] == VT_CARRAY)
2174 /* array descr table here */
2175 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2177 else if(td[0] == VT_USERDEFINED)
2179 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2181 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2184 /* second time around to fill the array subscript info */
2185 for(i=0;i<cTD;i++)
2187 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2188 if(tlbSegDir.pArrayDescriptions.offset>0)
2190 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2191 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2193 if(td[1]<0)
2194 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2195 else
2196 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2198 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2200 for(j = 0; j<td[2]; j++)
2202 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2203 sizeof(INT), &cx, DO_NOT_SEEK);
2204 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2205 sizeof(INT), &cx, DO_NOT_SEEK);
2208 else
2210 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2211 ERR("didn't find array description data\n");
2216 /* imported type libs */
2217 if(tlbSegDir.pImpFiles.offset>0)
2219 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2220 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2221 UINT16 size;
2223 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2225 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2226 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2227 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2229 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2230 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2231 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2232 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2234 size >>= 2;
2235 (*ppImpLib)->name = TLB_Alloc(size+1);
2236 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2237 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2238 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2240 ppImpLib = &(*ppImpLib)->next;
2244 /* type info's */
2245 if(tlbHeader.nrtypeinfos >= 0 )
2247 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2248 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2249 int i;
2251 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2253 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2255 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2256 ppTI = &((*ppTI)->next);
2257 (pTypeLibImpl->TypeInfoCount)++;
2261 TRACE("(%p)\n", pTypeLibImpl);
2262 return (ITypeLib2*) pTypeLibImpl;
2266 static BSTR TLB_MultiByteToBSTR(char *ptr)
2268 DWORD len;
2269 WCHAR *nameW;
2270 BSTR ret;
2272 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2273 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2274 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2275 ret = SysAllocString(nameW);
2276 HeapFree(GetProcessHeap(), 0, nameW);
2277 return ret;
2280 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2282 char b[3];
2283 int i;
2284 short s;
2286 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2287 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2288 return FALSE;
2291 guid->Data4[0] = s >> 8;
2292 guid->Data4[1] = s & 0xff;
2294 b[2] = '\0';
2295 for(i = 0; i < 6; i++) {
2296 memcpy(b, str + 24 + 2 * i, 2);
2297 guid->Data4[i + 2] = strtol(b, NULL, 16);
2299 return TRUE;
2302 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2304 WORD bytelen;
2305 DWORD len;
2306 WCHAR *nameW;
2308 *pBstr = NULL;
2309 bytelen = *(WORD*)ptr;
2310 if(bytelen == 0xffff) return 2;
2311 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2312 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2313 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2314 *pBstr = SysAllocStringLen(nameW, len);
2315 HeapFree(GetProcessHeap(), 0, nameW);
2316 return bytelen + 2;
2319 static WORD SLTG_ReadStringA(char *ptr, char **str)
2321 WORD bytelen;
2323 *str = NULL;
2324 bytelen = *(WORD*)ptr;
2325 if(bytelen == 0xffff) return 2;
2326 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2327 memcpy(*str, ptr + 2, bytelen);
2328 (*str)[bytelen] = '\0';
2329 return bytelen + 2;
2332 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2334 char *ptr = pLibBlk;
2335 WORD w;
2337 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2338 FIXME("libblk magic = %04x\n", w);
2339 return 0;
2342 ptr += 6;
2343 if((w = *(WORD*)ptr) != 0xffff) {
2344 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2345 ptr += w;
2347 ptr += 2;
2349 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2351 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2353 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2354 ptr += 4;
2356 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2357 ptr += 2;
2359 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2360 ptr += 2;
2362 ptr += 4; /* skip res12 */
2364 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2365 ptr += 2;
2367 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2368 ptr += 2;
2370 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2371 ptr += 2;
2373 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2374 ptr += sizeof(GUID);
2376 return ptr - (char*)pLibBlk;
2379 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2381 BOOL done = FALSE;
2382 TYPEDESC *pTD = &pElem->tdesc;
2384 /* Handle [in/out] first */
2385 if((*pType & 0xc000) == 0xc000)
2386 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2387 else if(*pType & 0x8000)
2388 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2389 else if(*pType & 0x4000)
2390 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2391 else
2392 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2394 if(*pType & 0x2000)
2395 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2397 if(*pType & 0x80)
2398 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2400 while(!done) {
2401 if((*pType & 0xe00) == 0xe00) {
2402 pTD->vt = VT_PTR;
2403 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2404 sizeof(TYPEDESC));
2405 pTD = pTD->u.lptdesc;
2407 switch(*pType & 0x7f) {
2408 case VT_PTR:
2409 pTD->vt = VT_PTR;
2410 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2411 sizeof(TYPEDESC));
2412 pTD = pTD->u.lptdesc;
2413 break;
2415 case VT_USERDEFINED:
2416 pTD->vt = VT_USERDEFINED;
2417 pTD->u.hreftype = *(++pType) / 4;
2418 done = TRUE;
2419 break;
2421 case VT_CARRAY:
2423 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2424 array */
2426 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2428 pTD->vt = VT_CARRAY;
2429 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2430 sizeof(ARRAYDESC) +
2431 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2432 pTD->u.lpadesc->cDims = pSA->cDims;
2433 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2434 pSA->cDims * sizeof(SAFEARRAYBOUND));
2436 pTD = &pTD->u.lpadesc->tdescElem;
2437 break;
2440 case VT_SAFEARRAY:
2442 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2443 useful? */
2445 pType++;
2446 pTD->vt = VT_SAFEARRAY;
2447 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2448 sizeof(TYPEDESC));
2449 pTD = pTD->u.lptdesc;
2450 break;
2452 default:
2453 pTD->vt = *pType & 0x7f;
2454 done = TRUE;
2455 break;
2457 pType++;
2459 return pType;
2463 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2464 char *pNameTable)
2466 int ref;
2467 char *name;
2468 TLBRefType **ppRefType;
2470 if(pRef->magic != SLTG_REF_MAGIC) {
2471 FIXME("Ref magic = %x\n", pRef->magic);
2472 return;
2474 name = ( (char*)(&pRef->names) + pRef->number);
2476 ppRefType = &pTI->reflist;
2477 for(ref = 0; ref < pRef->number >> 3; ref++) {
2478 char *refname;
2479 unsigned int lib_offs, type_num;
2481 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2482 sizeof(**ppRefType));
2484 name += SLTG_ReadStringA(name, &refname);
2485 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2486 FIXME("Can't sscanf ref\n");
2487 if(lib_offs != 0xffff) {
2488 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2490 while(*import) {
2491 if((*import)->offset == lib_offs)
2492 break;
2493 import = &(*import)->next;
2495 if(!*import) {
2496 char fname[MAX_PATH+1];
2497 int len;
2499 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2500 sizeof(**import));
2501 (*import)->offset = lib_offs;
2502 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2503 &(*import)->guid);
2504 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2505 &(*import)->wVersionMajor,
2506 &(*import)->wVersionMinor,
2507 &(*import)->lcid, fname) != 4) {
2508 FIXME("can't sscanf ref %s\n",
2509 pNameTable + lib_offs + 40);
2511 len = strlen(fname);
2512 if(fname[len-1] != '#')
2513 FIXME("fname = %s\n", fname);
2514 fname[len-1] = '\0';
2515 (*import)->name = TLB_MultiByteToBSTR(fname);
2517 (*ppRefType)->pImpTLInfo = *import;
2518 } else { /* internal ref */
2519 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2521 (*ppRefType)->reference = ref;
2522 (*ppRefType)->index = type_num;
2524 HeapFree(GetProcessHeap(), 0, refname);
2525 ppRefType = &(*ppRefType)->next;
2527 if((BYTE)*name != SLTG_REF_MAGIC)
2528 FIXME("End of ref block magic = %x\n", *name);
2529 dump_TLBRefType(pTI->reflist);
2532 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2533 BOOL OneOnly)
2535 SLTG_ImplInfo *info;
2536 TLBImplType **ppImplType = &pTI->impltypelist;
2537 /* I don't really get this structure, usually it's 0x16 bytes
2538 long, but iuser.tlb contains some that are 0x18 bytes long.
2539 That's ok because we can use the next ptr to jump to the next
2540 one. But how do we know the length of the last one? The WORD
2541 at offs 0x8 might be the clue. For now I'm just assuming that
2542 the last one is the regular 0x16 bytes. */
2544 info = (SLTG_ImplInfo*)pBlk;
2545 while(1) {
2546 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2547 sizeof(**ppImplType));
2548 (*ppImplType)->hRef = info->ref;
2549 (*ppImplType)->implflags = info->impltypeflags;
2550 pTI->TypeAttr.cImplTypes++;
2551 ppImplType = &(*ppImplType)->next;
2553 if(info->next == 0xffff)
2554 break;
2555 if(OneOnly)
2556 FIXME("Interface inheriting more than one interface\n");
2557 info = (SLTG_ImplInfo*)(pBlk + info->next);
2559 info++; /* see comment at top of function */
2560 return (char*)info;
2563 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2564 char *pNameTable)
2566 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2567 SLTG_MemberHeader *pMemHeader;
2568 char *pFirstItem, *pNextItem;
2570 if(pTIHeader->href_table != 0xffffffff) {
2571 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2572 pNameTable);
2576 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2578 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2580 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2581 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2584 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2588 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2589 char *pNameTable)
2591 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2592 SLTG_MemberHeader *pMemHeader;
2593 SLTG_Function *pFunc;
2594 char *pFirstItem, *pNextItem;
2595 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2596 int num = 0;
2598 if(pTIHeader->href_table != 0xffffffff) {
2599 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2600 pNameTable);
2603 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2605 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2607 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2608 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2611 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2612 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2614 int param;
2615 WORD *pType, *pArg;
2617 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2618 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2619 FIXME("func magic = %02x\n", pFunc->magic);
2620 return NULL;
2622 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2623 sizeof(**ppFuncDesc));
2624 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2626 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2627 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2628 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2629 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2630 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2631 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2633 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2634 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2636 if(pFunc->retnextopt & 0x80)
2637 pType = &pFunc->rettype;
2638 else
2639 pType = (WORD*)(pFirstItem + pFunc->rettype);
2642 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2644 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2645 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2646 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2647 (*ppFuncDesc)->pParamDesc =
2648 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2649 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2651 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2653 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2654 char *paramName = pNameTable + *pArg;
2655 BOOL HaveOffs;
2656 /* If arg type follows then paramName points to the 2nd
2657 letter of the name, else the next WORD is an offset to
2658 the arg type and paramName points to the first letter.
2659 So let's take one char off paramName and see if we're
2660 pointing at an alpha-numeric char. However if *pArg is
2661 0xffff or 0xfffe then the param has no name, the former
2662 meaning that the next WORD is the type, the latter
2663 meaning the the next WORD is an offset to the type. */
2665 HaveOffs = FALSE;
2666 if(*pArg == 0xffff)
2667 paramName = NULL;
2668 else if(*pArg == 0xfffe) {
2669 paramName = NULL;
2670 HaveOffs = TRUE;
2672 else if(!isalnum(*(paramName-1)))
2673 HaveOffs = TRUE;
2675 pArg++;
2677 if(HaveOffs) { /* the next word is an offset to type */
2678 pType = (WORD*)(pFirstItem + *pArg);
2679 SLTG_DoType(pType, pFirstItem,
2680 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2681 pArg++;
2682 } else {
2683 if(paramName)
2684 paramName--;
2685 pArg = SLTG_DoType(pArg, pFirstItem,
2686 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2689 /* Are we an optional param ? */
2690 if((*ppFuncDesc)->funcdesc.cParams - param <=
2691 (*ppFuncDesc)->funcdesc.cParamsOpt)
2692 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2694 if(paramName) {
2695 (*ppFuncDesc)->pParamDesc[param].Name =
2696 TLB_MultiByteToBSTR(paramName);
2700 ppFuncDesc = &((*ppFuncDesc)->next);
2701 if(pFunc->next == 0xffff) break;
2703 pTI->TypeAttr.cFuncs = num;
2704 dump_TLBFuncDesc(pTI->funclist);
2705 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2708 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2709 char *pNameTable)
2711 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2712 SLTG_MemberHeader *pMemHeader;
2713 SLTG_RecordItem *pItem;
2714 char *pFirstItem;
2715 TLBVarDesc **ppVarDesc = &pTI->varlist;
2716 int num = 0;
2717 WORD *pType;
2718 char buf[300];
2720 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2722 pFirstItem = (char*)(pMemHeader + 1);
2723 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2724 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2725 if(pItem->magic != SLTG_RECORD_MAGIC) {
2726 FIXME("record magic = %02x\n", pItem->magic);
2727 return NULL;
2729 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2730 sizeof(**ppVarDesc));
2731 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2732 (*ppVarDesc)->vardesc.memid = pItem->memid;
2733 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2734 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2736 if(pItem->typepos == 0x02)
2737 pType = &pItem->type;
2738 else if(pItem->typepos == 0x00)
2739 pType = (WORD*)(pFirstItem + pItem->type);
2740 else {
2741 FIXME("typepos = %02x\n", pItem->typepos);
2742 break;
2745 SLTG_DoType(pType, pFirstItem,
2746 &(*ppVarDesc)->vardesc.elemdescVar);
2748 /* FIXME("helpcontext, helpstring\n"); */
2750 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2752 ppVarDesc = &((*ppVarDesc)->next);
2753 if(pItem->next == 0xffff) break;
2755 pTI->TypeAttr.cVars = num;
2756 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2759 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2760 char *pNameTable)
2762 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2763 SLTG_MemberHeader *pMemHeader;
2764 SLTG_AliasItem *pItem;
2765 int i, mustbelast;
2767 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2768 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2770 mustbelast = 0;
2771 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2772 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2773 if (pItem->vt == 0xffff) {
2774 if (i<(pMemHeader->cbExtra/4-1))
2775 FIXME("Endmarker too early in process alias data!\n");
2776 break;
2778 if (mustbelast) {
2779 FIXME("Chain extends over last entry?\n");
2780 break;
2782 if (pItem->vt == VT_USERDEFINED) {
2783 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2784 /* guessing here ... */
2785 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2786 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2787 mustbelast = 1;
2788 } else {
2789 FIXME("alias %d: 0x%x\n",i,pItem->vt);
2790 FIXME("alias %d: 0x%x\n",i,pItem->res02);
2792 pItem++;
2794 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2797 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
2798 char *pNameTable)
2800 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2801 SLTG_MemberHeader *pMemHeader;
2802 SLTG_AliasItem *pItem;
2804 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2805 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2806 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
2807 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
2808 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2811 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2812 char *pNameTable)
2814 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2815 SLTG_MemberHeader *pMemHeader;
2816 SLTG_EnumItem *pItem;
2817 char *pFirstItem;
2818 TLBVarDesc **ppVarDesc = &pTI->varlist;
2819 int num = 0;
2821 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2823 pFirstItem = (char*)(pMemHeader + 1);
2824 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2825 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2826 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2827 FIXME("enumitem magic = %04x\n", pItem->magic);
2828 return NULL;
2830 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2831 sizeof(**ppVarDesc));
2832 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2833 (*ppVarDesc)->vardesc.memid = pItem->memid;
2834 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2835 sizeof(VARIANT));
2836 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2837 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2838 *(INT*)(pItem->value + pFirstItem);
2839 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2840 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2841 /* FIXME("helpcontext, helpstring\n"); */
2843 ppVarDesc = &((*ppVarDesc)->next);
2844 if(pItem->next == 0xffff) break;
2846 pTI->TypeAttr.cVars = num;
2847 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2850 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2851 managable copy of it into this */
2852 typedef struct {
2853 WORD small_no;
2854 char *index_name;
2855 char *other_name;
2856 WORD res1a;
2857 WORD name_offs;
2858 WORD more_bytes;
2859 char *extra;
2860 WORD res20;
2861 DWORD helpcontext;
2862 WORD res26;
2863 GUID uuid;
2864 } SLTG_InternalOtherTypeInfo;
2866 /****************************************************************************
2867 * ITypeLib2_Constructor_SLTG
2869 * loading a SLTG typelib from an in-memory image
2871 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2873 ITypeLibImpl *pTypeLibImpl;
2874 SLTG_Header *pHeader;
2875 SLTG_BlkEntry *pBlkEntry;
2876 SLTG_Magic *pMagic;
2877 SLTG_Index *pIndex;
2878 SLTG_Pad9 *pPad9;
2879 LPVOID pBlk, pFirstBlk;
2880 SLTG_LibBlk *pLibBlk;
2881 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2882 char *pAfterOTIBlks = NULL;
2883 char *pNameTable, *ptr;
2884 int i;
2885 DWORD len, order;
2886 ITypeInfoImpl **ppTypeInfoImpl;
2888 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2890 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2891 if (!pTypeLibImpl) return NULL;
2893 pTypeLibImpl->lpVtbl = &tlbvt;
2894 pTypeLibImpl->ref = 1;
2896 pHeader = pLib;
2898 TRACE("header:\n");
2899 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2900 pHeader->nrOfFileBlks );
2901 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
2902 FIXME("Header type magic 0x%08lx not supported.\n",
2903 pHeader->SLTG_magic);
2904 return NULL;
2907 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2908 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2910 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2911 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2913 /* Next we have a magic block */
2914 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2916 /* Let's see if we're still in sync */
2917 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2918 sizeof(SLTG_COMPOBJ_MAGIC))) {
2919 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2920 return NULL;
2922 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2923 sizeof(SLTG_DIR_MAGIC))) {
2924 FIXME("dir magic = %s\n", pMagic->dir_magic);
2925 return NULL;
2928 pIndex = (SLTG_Index*)(pMagic+1);
2930 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2932 pFirstBlk = (LPVOID)(pPad9 + 1);
2934 /* We'll set up a ptr to the main library block, which is the last one. */
2936 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2937 pBlkEntry[order].next != 0;
2938 order = pBlkEntry[order].next - 1, i++) {
2939 pBlk = (char*)pBlk + pBlkEntry[order].len;
2941 pLibBlk = pBlk;
2943 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2945 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2946 interspersed */
2948 len += 0x40;
2950 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2952 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2953 sizeof(*pOtherTypeInfoBlks) *
2954 pTypeLibImpl->TypeInfoCount);
2957 ptr = (char*)pLibBlk + len;
2959 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2960 WORD w, extra;
2961 len = 0;
2963 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2965 w = *(WORD*)(ptr + 2);
2966 if(w != 0xffff) {
2967 len += w;
2968 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2969 w+1);
2970 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2971 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2973 w = *(WORD*)(ptr + 4 + len);
2974 if(w != 0xffff) {
2975 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2976 len += w;
2977 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2978 w+1);
2979 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2980 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2982 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2983 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2984 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2985 if(extra) {
2986 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2987 extra);
2988 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2989 len += extra;
2991 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2992 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2993 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2994 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2995 len += sizeof(SLTG_OtherTypeInfo);
2996 ptr += len;
2999 pAfterOTIBlks = ptr;
3001 /* Skip this WORD and get the next DWORD */
3002 len = *(DWORD*)(pAfterOTIBlks + 2);
3004 /* Now add this to pLibBLk look at what we're pointing at and
3005 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3006 dust and we should be pointing at the beginning of the name
3007 table */
3009 pNameTable = (char*)pLibBlk + len;
3011 switch(*(WORD*)pNameTable) {
3012 case 0xffff:
3013 break;
3014 case 0x0200:
3015 pNameTable += 0x20;
3016 break;
3017 default:
3018 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3019 break;
3022 pNameTable += 0x216;
3024 pNameTable += 2;
3026 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3028 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3031 /* Hopefully we now have enough ptrs set up to actually read in
3032 some TypeInfos. It's not clear which order to do them in, so
3033 I'll just follow the links along the BlkEntry chain and read
3034 them in in the order in which they're in the file */
3036 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3038 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3039 pBlkEntry[order].next != 0;
3040 order = pBlkEntry[order].next - 1, i++) {
3042 SLTG_TypeInfoHeader *pTIHeader;
3043 SLTG_TypeInfoTail *pTITail;
3045 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3046 pOtherTypeInfoBlks[i].index_name)) {
3047 FIXME("Index strings don't match\n");
3048 return NULL;
3051 pTIHeader = pBlk;
3052 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3053 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3054 return NULL;
3056 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3057 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3058 ITypeLib2_AddRef((ITypeLib2 *)pTypeLibImpl);
3059 (*ppTypeInfoImpl)->index = i;
3060 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3061 pOtherTypeInfoBlks[i].name_offs +
3062 pNameTable);
3063 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3064 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3065 sizeof(GUID));
3066 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3067 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3068 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3069 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3070 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3072 if((pTIHeader->typeflags1 & 7) != 2)
3073 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3074 if(pTIHeader->typeflags3 != 2)
3075 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3077 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3078 debugstr_w((*ppTypeInfoImpl)->Name),
3079 typekind_desc[pTIHeader->typekind],
3080 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3081 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3083 switch(pTIHeader->typekind) {
3084 case TKIND_ENUM:
3085 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3086 break;
3088 case TKIND_RECORD:
3089 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3090 break;
3092 case TKIND_INTERFACE:
3093 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3094 break;
3096 case TKIND_COCLASS:
3097 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3098 break;
3100 case TKIND_ALIAS:
3101 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3102 if (pTITail->tdescalias_vt)
3103 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3104 break;
3106 case TKIND_DISPATCH:
3107 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3108 break;
3110 default:
3111 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3112 pTITail = NULL;
3113 break;
3117 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3118 but we've already set those */
3119 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3120 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3121 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3123 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3124 X(06);
3125 X(08);
3126 X(0a);
3127 X(0c);
3128 X(0e);
3129 X(10);
3130 X(12);
3131 X(16);
3132 X(18);
3133 X(1a);
3134 X(1c);
3135 X(1e);
3136 X(24);
3137 X(26);
3138 X(2a);
3139 X(2c);
3140 X(2e);
3141 X(30);
3142 X(32);
3143 X(34);
3145 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3146 pBlk = (char*)pBlk + pBlkEntry[order].len;
3149 if(i != pTypeLibImpl->TypeInfoCount) {
3150 FIXME("Somehow processed %d TypeInfos\n", i);
3151 return NULL;
3154 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3155 return (ITypeLib2*)pTypeLibImpl;
3158 /* ITypeLib::QueryInterface
3160 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3161 ITypeLib2 * iface,
3162 REFIID riid,
3163 VOID **ppvObject)
3165 ICOM_THIS( ITypeLibImpl, iface);
3167 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3169 *ppvObject=NULL;
3170 if(IsEqualIID(riid, &IID_IUnknown) ||
3171 IsEqualIID(riid,&IID_ITypeLib)||
3172 IsEqualIID(riid,&IID_ITypeLib2))
3174 *ppvObject = This;
3177 if(*ppvObject)
3179 ITypeLib2_AddRef(iface);
3180 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3181 return S_OK;
3183 TRACE("-- Interface: E_NOINTERFACE\n");
3184 return E_NOINTERFACE;
3187 /* ITypeLib::AddRef
3189 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3191 ICOM_THIS( ITypeLibImpl, iface);
3193 TRACE("(%p)->ref is %u\n",This, This->ref);
3195 return ++(This->ref);
3198 /* ITypeLib::Release
3200 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3202 ICOM_THIS( ITypeLibImpl, iface);
3204 --(This->ref);
3206 TRACE("(%p)->(%u)\n",This, This->ref);
3208 if (!This->ref)
3210 /* FIXME destroy child objects */
3212 TRACE(" destroying ITypeLib(%p)\n",This);
3214 if (This->Name)
3216 SysFreeString(This->Name);
3217 This->Name = NULL;
3220 if (This->DocString)
3222 SysFreeString(This->DocString);
3223 This->DocString = NULL;
3226 if (This->HelpFile)
3228 SysFreeString(This->HelpFile);
3229 This->HelpFile = NULL;
3232 if (This->HelpStringDll)
3234 SysFreeString(This->HelpStringDll);
3235 This->HelpStringDll = NULL;
3238 if (This->pTypeInfo) /* can be NULL */
3239 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3240 HeapFree(GetProcessHeap(),0,This);
3241 return 0;
3244 return This->ref;
3247 /* ITypeLib::GetTypeInfoCount
3249 * Returns the number of type descriptions in the type library
3251 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3253 ICOM_THIS( ITypeLibImpl, iface);
3254 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3255 return This->TypeInfoCount;
3258 /* ITypeLib::GetTypeInfo
3260 * retrieves the specified type description in the library.
3262 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3263 ITypeLib2 *iface,
3264 UINT index,
3265 ITypeInfo **ppTInfo)
3267 int i;
3269 ICOM_THIS( ITypeLibImpl, iface);
3270 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3272 TRACE("(%p)->(index=%d) \n", This, index);
3274 if (!ppTInfo) return E_INVALIDARG;
3276 /* search element n in list */
3277 for(i=0; i < index; i++)
3279 pTypeInfo = pTypeInfo->next;
3280 if (!pTypeInfo)
3282 TRACE("-- element not found\n");
3283 return TYPE_E_ELEMENTNOTFOUND;
3287 *ppTInfo = (ITypeInfo *) pTypeInfo;
3289 ITypeInfo_AddRef(*ppTInfo);
3290 TRACE("-- found (%p)\n",*ppTInfo);
3291 return S_OK;
3295 /* ITypeLibs::GetTypeInfoType
3297 * Retrieves the type of a type description.
3299 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3300 ITypeLib2 *iface,
3301 UINT index,
3302 TYPEKIND *pTKind)
3304 ICOM_THIS( ITypeLibImpl, iface);
3305 int i;
3306 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3308 TRACE("(%p) index %d \n",This, index);
3310 if(!pTKind) return E_INVALIDARG;
3312 /* search element n in list */
3313 for(i=0; i < index; i++)
3315 if(!pTInfo)
3317 TRACE("-- element not found\n");
3318 return TYPE_E_ELEMENTNOTFOUND;
3320 pTInfo = pTInfo->next;
3323 *pTKind = pTInfo->TypeAttr.typekind;
3324 TRACE("-- found Type (%d)\n", *pTKind);
3325 return S_OK;
3328 /* ITypeLib::GetTypeInfoOfGuid
3330 * Retrieves the type description that corresponds to the specified GUID.
3333 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3334 ITypeLib2 *iface,
3335 REFGUID guid,
3336 ITypeInfo **ppTInfo)
3338 ICOM_THIS( ITypeLibImpl, iface);
3339 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3341 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3343 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3345 /* search linked list for guid */
3346 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3348 pTypeInfo = pTypeInfo->next;
3350 if (!pTypeInfo)
3352 /* end of list reached */
3353 TRACE("-- element not found\n");
3354 return TYPE_E_ELEMENTNOTFOUND;
3358 TRACE("-- found (%p, %s)\n",
3359 pTypeInfo,
3360 debugstr_w(pTypeInfo->Name));
3362 *ppTInfo = (ITypeInfo*)pTypeInfo;
3363 ITypeInfo_AddRef(*ppTInfo);
3364 return S_OK;
3367 /* ITypeLib::GetLibAttr
3369 * Retrieves the structure that contains the library's attributes.
3372 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3373 ITypeLib2 *iface,
3374 LPTLIBATTR *ppTLibAttr)
3376 ICOM_THIS( ITypeLibImpl, iface);
3377 TRACE("(%p)\n",This);
3378 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3379 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3380 return S_OK;
3383 /* ITypeLib::GetTypeComp
3385 * Enables a client compiler to bind to a library's types, variables,
3386 * constants, and global functions.
3389 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3390 ITypeLib2 *iface,
3391 ITypeComp **ppTComp)
3393 ICOM_THIS( ITypeLibImpl, iface);
3394 FIXME("(%p): stub!\n",This);
3395 return E_NOTIMPL;
3398 /* ITypeLib::GetDocumentation
3400 * Retrieves the library's documentation string, the complete Help file name
3401 * and path, and the context identifier for the library Help topic in the Help
3402 * file.
3404 * On a successful return all non-null BSTR pointers will have been set,
3405 * possibly to NULL.
3407 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3408 ITypeLib2 *iface,
3409 INT index,
3410 BSTR *pBstrName,
3411 BSTR *pBstrDocString,
3412 DWORD *pdwHelpContext,
3413 BSTR *pBstrHelpFile)
3415 ICOM_THIS( ITypeLibImpl, iface);
3417 HRESULT result = E_INVALIDARG;
3419 ITypeInfo *pTInfo;
3422 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3423 This, index,
3424 pBstrName, pBstrDocString,
3425 pdwHelpContext, pBstrHelpFile);
3427 if(index<0)
3429 /* documentation for the typelib */
3430 if(pBstrName)
3432 if (This->Name)
3433 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3434 else
3435 *pBstrName = NULL;
3437 if(pBstrDocString)
3439 if (This->DocString)
3440 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3441 else if (This->Name)
3442 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3443 else
3444 *pBstrDocString = NULL;
3446 if(pdwHelpContext)
3448 *pdwHelpContext = This->dwHelpContext;
3450 if(pBstrHelpFile)
3452 if (This->HelpFile)
3453 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3454 else
3455 *pBstrHelpFile = NULL;
3458 result = S_OK;
3460 else
3462 /* for a typeinfo */
3463 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3465 if(SUCCEEDED(result))
3467 result = ITypeInfo_GetDocumentation(pTInfo,
3468 MEMBERID_NIL,
3469 pBstrName,
3470 pBstrDocString,
3471 pdwHelpContext, pBstrHelpFile);
3473 ITypeInfo_Release(pTInfo);
3476 return result;
3477 memerr3:
3478 if (pBstrDocString) SysFreeString (*pBstrDocString);
3479 memerr2:
3480 if (pBstrName) SysFreeString (*pBstrName);
3481 memerr1:
3482 return STG_E_INSUFFICIENTMEMORY;
3485 /* ITypeLib::IsName
3487 * Indicates whether a passed-in string contains the name of a type or member
3488 * described in the library.
3491 static HRESULT WINAPI ITypeLib2_fnIsName(
3492 ITypeLib2 *iface,
3493 LPOLESTR szNameBuf,
3494 ULONG lHashVal,
3495 BOOL *pfName)
3497 ICOM_THIS( ITypeLibImpl, iface);
3498 ITypeInfoImpl *pTInfo;
3499 TLBFuncDesc *pFInfo;
3500 TLBVarDesc *pVInfo;
3501 int i;
3502 UINT nNameBufLen = SysStringLen(szNameBuf);
3504 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3505 pfName);
3507 *pfName=TRUE;
3508 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3509 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3510 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3511 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3512 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3513 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3514 goto ITypeLib2_fnIsName_exit;
3516 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3517 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3520 *pfName=FALSE;
3522 ITypeLib2_fnIsName_exit:
3523 TRACE("(%p)slow! search for %s: %s found!\n", This,
3524 debugstr_w(szNameBuf), *pfName?"NOT":"");
3526 return S_OK;
3529 /* ITypeLib::FindName
3531 * Finds occurrences of a type description in a type library. This may be used
3532 * to quickly verify that a name exists in a type library.
3535 static HRESULT WINAPI ITypeLib2_fnFindName(
3536 ITypeLib2 *iface,
3537 LPOLESTR szNameBuf,
3538 ULONG lHashVal,
3539 ITypeInfo **ppTInfo,
3540 MEMBERID *rgMemId,
3541 UINT16 *pcFound)
3543 ICOM_THIS( ITypeLibImpl, iface);
3544 ITypeInfoImpl *pTInfo;
3545 TLBFuncDesc *pFInfo;
3546 TLBVarDesc *pVInfo;
3547 int i,j = 0;
3549 UINT nNameBufLen = SysStringLen(szNameBuf);
3551 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3552 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3553 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3554 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3555 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3556 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3557 goto ITypeLib2_fnFindName_exit;
3559 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3560 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3561 continue;
3562 ITypeLib2_fnFindName_exit:
3563 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3564 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3565 j++;
3567 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3568 This, *pcFound, debugstr_w(szNameBuf), j);
3570 *pcFound=j;
3572 return S_OK;
3575 /* ITypeLib::ReleaseTLibAttr
3577 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3580 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3581 ITypeLib2 *iface,
3582 TLIBATTR *pTLibAttr)
3584 ICOM_THIS( ITypeLibImpl, iface);
3585 TRACE("freeing (%p)\n",This);
3586 HeapFree(GetProcessHeap(),0,pTLibAttr);
3590 /* ITypeLib2::GetCustData
3592 * gets the custom data
3594 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3595 ITypeLib2 * iface,
3596 REFGUID guid,
3597 VARIANT *pVarVal)
3599 ICOM_THIS( ITypeLibImpl, iface);
3600 TLBCustData *pCData;
3602 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3604 if( IsEqualIID(guid, &pCData->guid)) break;
3607 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3609 if(pCData)
3611 VariantInit( pVarVal);
3612 VariantCopy( pVarVal, &pCData->data);
3613 return S_OK;
3615 return E_INVALIDARG; /* FIXME: correct? */
3618 /* ITypeLib2::GetLibStatistics
3620 * Returns statistics about a type library that are required for efficient
3621 * sizing of hash tables.
3624 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3625 ITypeLib2 * iface,
3626 ULONG *pcUniqueNames,
3627 ULONG *pcchUniqueNames)
3629 ICOM_THIS( ITypeLibImpl, iface);
3631 FIXME("(%p): stub!\n", This);
3633 if(pcUniqueNames) *pcUniqueNames=1;
3634 if(pcchUniqueNames) *pcchUniqueNames=1;
3635 return S_OK;
3638 /* ITypeLib2::GetDocumentation2
3640 * Retrieves the library's documentation string, the complete Help file name
3641 * and path, the localization context to use, and the context ID for the
3642 * library Help topic in the Help file.
3645 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3646 ITypeLib2 * iface,
3647 INT index,
3648 LCID lcid,
3649 BSTR *pbstrHelpString,
3650 DWORD *pdwHelpStringContext,
3651 BSTR *pbstrHelpStringDll)
3653 ICOM_THIS( ITypeLibImpl, iface);
3654 HRESULT result;
3655 ITypeInfo *pTInfo;
3657 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3659 /* the help string should be obtained from the helpstringdll,
3660 * using the _DLLGetDocumentation function, based on the supplied
3661 * lcid. Nice to do sometime...
3663 if(index<0)
3665 /* documentation for the typelib */
3666 if(pbstrHelpString)
3667 *pbstrHelpString=SysAllocString(This->DocString);
3668 if(pdwHelpStringContext)
3669 *pdwHelpStringContext=This->dwHelpContext;
3670 if(pbstrHelpStringDll)
3671 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3673 result = S_OK;
3675 else
3677 /* for a typeinfo */
3678 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3680 if(SUCCEEDED(result))
3682 ITypeInfo2 * pTInfo2;
3683 result = ITypeInfo_QueryInterface(pTInfo,
3684 &IID_ITypeInfo2,
3685 (LPVOID*) &pTInfo2);
3687 if(SUCCEEDED(result))
3689 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3690 MEMBERID_NIL,
3691 lcid,
3692 pbstrHelpString,
3693 pdwHelpStringContext,
3694 pbstrHelpStringDll);
3696 ITypeInfo2_Release(pTInfo2);
3699 ITypeInfo_Release(pTInfo);
3702 return result;
3705 /* ITypeLib2::GetAllCustData
3707 * Gets all custom data items for the library.
3710 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3711 ITypeLib2 * iface,
3712 CUSTDATA *pCustData)
3714 ICOM_THIS( ITypeLibImpl, iface);
3715 TLBCustData *pCData;
3716 int i;
3717 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3718 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3719 if(pCustData->prgCustData ){
3720 pCustData->cCustData=This->ctCustData;
3721 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3722 pCustData->prgCustData[i].guid=pCData->guid;
3723 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3725 }else{
3726 ERR(" OUT OF MEMORY! \n");
3727 return E_OUTOFMEMORY;
3729 return S_OK;
3732 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3733 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3734 ITypeLib2_fnQueryInterface,
3735 ITypeLib2_fnAddRef,
3736 ITypeLib2_fnRelease,
3737 ITypeLib2_fnGetTypeInfoCount,
3738 ITypeLib2_fnGetTypeInfo,
3739 ITypeLib2_fnGetTypeInfoType,
3740 ITypeLib2_fnGetTypeInfoOfGuid,
3741 ITypeLib2_fnGetLibAttr,
3742 ITypeLib2_fnGetTypeComp,
3743 ITypeLib2_fnGetDocumentation,
3744 ITypeLib2_fnIsName,
3745 ITypeLib2_fnFindName,
3746 ITypeLib2_fnReleaseTLibAttr,
3748 ITypeLib2_fnGetCustData,
3749 ITypeLib2_fnGetLibStatistics,
3750 ITypeLib2_fnGetDocumentation2,
3751 ITypeLib2_fnGetAllCustData
3754 /*================== ITypeInfo(2) Methods ===================================*/
3755 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3757 ITypeInfoImpl * pTypeInfoImpl;
3759 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3760 if (pTypeInfoImpl)
3762 pTypeInfoImpl->lpVtbl = &tinfvt;
3763 pTypeInfoImpl->ref=1;
3765 TRACE("(%p)\n", pTypeInfoImpl);
3766 return (ITypeInfo2*) pTypeInfoImpl;
3769 /* ITypeInfo::QueryInterface
3771 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3772 ITypeInfo2 *iface,
3773 REFIID riid,
3774 VOID **ppvObject)
3776 ICOM_THIS( ITypeLibImpl, iface);
3778 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3780 *ppvObject=NULL;
3781 if(IsEqualIID(riid, &IID_IUnknown) ||
3782 IsEqualIID(riid,&IID_ITypeInfo)||
3783 IsEqualIID(riid,&IID_ITypeInfo2))
3784 *ppvObject = This;
3786 if(*ppvObject){
3787 ITypeInfo_AddRef(iface);
3788 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3789 return S_OK;
3791 TRACE("-- Interface: E_NOINTERFACE\n");
3792 return E_NOINTERFACE;
3795 /* ITypeInfo::AddRef
3797 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3799 ICOM_THIS( ITypeInfoImpl, iface);
3801 ++(This->ref);
3803 TRACE("(%p)->ref is %u\n",This, This->ref);
3804 return This->ref;
3807 /* ITypeInfo::Release
3809 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3811 ICOM_THIS( ITypeInfoImpl, iface);
3813 --(This->ref);
3815 TRACE("(%p)->(%u)\n",This, This->ref);
3817 if (!This->ref)
3819 FIXME("destroy child objects\n");
3821 TRACE("destroying ITypeInfo(%p)\n",This);
3822 if (This->Name)
3824 SysFreeString(This->Name);
3825 This->Name = 0;
3828 if (This->DocString)
3830 SysFreeString(This->DocString);
3831 This->DocString = 0;
3834 if (This->next)
3836 ITypeInfo_Release((ITypeInfo*)This->next);
3839 HeapFree(GetProcessHeap(),0,This);
3840 return 0;
3842 return This->ref;
3845 /* ITypeInfo::GetTypeAttr
3847 * Retrieves a TYPEATTR structure that contains the attributes of the type
3848 * description.
3851 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3852 LPTYPEATTR *ppTypeAttr)
3854 ICOM_THIS( ITypeInfoImpl, iface);
3855 TRACE("(%p)\n",This);
3856 /* FIXME: must do a copy here */
3857 *ppTypeAttr=&This->TypeAttr;
3858 return S_OK;
3861 /* ITypeInfo::GetTypeComp
3863 * Retrieves the ITypeComp interface for the type description, which enables a
3864 * client compiler to bind to the type description's members.
3867 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3868 ITypeComp * *ppTComp)
3870 ICOM_THIS( ITypeInfoImpl, iface);
3871 FIXME("(%p) stub!\n", This);
3872 return S_OK;
3875 /* ITypeInfo::GetFuncDesc
3877 * Retrieves the FUNCDESC structure that contains information about a
3878 * specified function.
3881 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3882 LPFUNCDESC *ppFuncDesc)
3884 ICOM_THIS( ITypeInfoImpl, iface);
3885 int i;
3886 TLBFuncDesc * pFDesc;
3887 TRACE("(%p) index %d\n", This, index);
3888 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3890 if(pFDesc){
3891 /* FIXME: must do a copy here */
3892 *ppFuncDesc=&pFDesc->funcdesc;
3893 return S_OK;
3895 return E_INVALIDARG;
3898 /* ITypeInfo::GetVarDesc
3900 * Retrieves a VARDESC structure that describes the specified variable.
3903 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3904 LPVARDESC *ppVarDesc)
3906 ICOM_THIS( ITypeInfoImpl, iface);
3907 int i;
3908 TLBVarDesc * pVDesc;
3909 TRACE("(%p) index %d\n", This, index);
3910 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3912 if(pVDesc){
3913 /* FIXME: must do a copy here */
3914 *ppVarDesc=&pVDesc->vardesc;
3915 return S_OK;
3917 return E_INVALIDARG;
3920 /* ITypeInfo_GetNames
3922 * Retrieves the variable with the specified member ID (or the name of the
3923 * property or method and its parameters) that correspond to the specified
3924 * function ID.
3926 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3927 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3929 ICOM_THIS( ITypeInfoImpl, iface);
3930 TLBFuncDesc * pFDesc;
3931 TLBVarDesc * pVDesc;
3932 int i;
3933 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3934 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3935 if(pFDesc)
3937 /* function found, now return function and parameter names */
3938 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3940 if(!i)
3941 *rgBstrNames=SysAllocString(pFDesc->Name);
3942 else
3943 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3945 *pcNames=i;
3947 else
3949 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3950 if(pVDesc)
3952 *rgBstrNames=SysAllocString(pVDesc->Name);
3953 *pcNames=1;
3955 else
3957 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3959 /* recursive search */
3960 ITypeInfo *pTInfo;
3961 HRESULT result;
3962 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3963 &pTInfo);
3964 if(SUCCEEDED(result))
3966 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3967 ITypeInfo_Release(pTInfo);
3968 return result;
3970 WARN("Could not search inherited interface!\n");
3972 else
3974 WARN("no names found\n");
3976 *pcNames=0;
3977 return TYPE_E_ELEMENTNOTFOUND;
3980 return S_OK;
3984 /* ITypeInfo::GetRefTypeOfImplType
3986 * If a type description describes a COM class, it retrieves the type
3987 * description of the implemented interface types. For an interface,
3988 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3989 * if any exist.
3992 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3993 ITypeInfo2 *iface,
3994 UINT index,
3995 HREFTYPE *pRefType)
3997 ICOM_THIS( ITypeInfoImpl, iface);
3998 int(i);
3999 TLBImplType *pImpl = This->impltypelist;
4001 TRACE("(%p) index %d\n", This, index);
4002 if (TRACE_ON(ole)) dump_TypeInfo(This);
4004 if(index==(UINT)-1)
4006 /* only valid on dual interfaces;
4007 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4009 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4011 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4012 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4014 *pRefType = -1;
4016 else
4018 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4019 *pRefType = pImpl->hRef;
4022 else
4024 /* get element n from linked list */
4025 for(i=0; pImpl && i<index; i++)
4027 pImpl = pImpl->next;
4030 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4032 *pRefType = pImpl->hRef;
4034 TRACE("-- 0x%08lx\n", pImpl->hRef );
4037 return S_OK;
4041 /* ITypeInfo::GetImplTypeFlags
4043 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4044 * or base interface in a type description.
4046 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4047 UINT index, INT *pImplTypeFlags)
4049 ICOM_THIS( ITypeInfoImpl, iface);
4050 int i;
4051 TLBImplType *pImpl;
4053 TRACE("(%p) index %d\n", This, index);
4054 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4055 i++, pImpl=pImpl->next)
4057 if(i==index && pImpl){
4058 *pImplTypeFlags=pImpl->implflags;
4059 return S_OK;
4061 *pImplTypeFlags=0;
4062 return TYPE_E_ELEMENTNOTFOUND;
4065 /* GetIDsOfNames
4066 * Maps between member names and member IDs, and parameter names and
4067 * parameter IDs.
4069 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4070 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4072 ICOM_THIS( ITypeInfoImpl, iface);
4073 TLBFuncDesc * pFDesc;
4074 TLBVarDesc * pVDesc;
4075 HRESULT ret=S_OK;
4077 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4078 cNames);
4079 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4080 int i, j;
4081 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4082 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4083 for(i=1; i < cNames; i++){
4084 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4085 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4086 break;
4087 if( j<pFDesc->funcdesc.cParams)
4088 pMemId[i]=j;
4089 else
4090 ret=DISP_E_UNKNOWNNAME;
4092 return ret;
4095 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4096 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4097 if(cNames) *pMemId=pVDesc->vardesc.memid;
4098 return ret;
4101 /* not found, see if this is and interface with an inheritance */
4102 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
4103 This->TypeAttr.cImplTypes ){
4104 /* recursive search */
4105 ITypeInfo *pTInfo;
4106 ret=ITypeInfo_GetRefTypeInfo(iface,
4107 This->impltypelist->hRef, &pTInfo);
4108 if(SUCCEEDED(ret)){
4109 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4110 ITypeInfo_Release(pTInfo);
4111 return ret;
4113 WARN("Could not search inherited interface!\n");
4114 } else
4115 WARN("no names found\n");
4116 return DISP_E_UNKNOWNNAME;
4119 /* ITypeInfo::Invoke
4121 * Invokes a method, or accesses a property of an object, that implements the
4122 * interface described by the type description.
4124 DWORD
4125 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4126 DWORD res;
4128 if (TRACE_ON(ole)) {
4129 int i;
4130 TRACE("Calling %p(",func);
4131 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4132 TRACE(")\n");
4135 switch (callconv) {
4136 case CC_STDCALL:
4138 switch (nrargs) {
4139 case 0:
4140 res = func();
4141 break;
4142 case 1:
4143 res = func(args[0]);
4144 break;
4145 case 2:
4146 res = func(args[0],args[1]);
4147 break;
4148 case 3:
4149 res = func(args[0],args[1],args[2]);
4150 break;
4151 case 4:
4152 res = func(args[0],args[1],args[2],args[3]);
4153 break;
4154 case 5:
4155 res = func(args[0],args[1],args[2],args[3],args[4]);
4156 break;
4157 case 6:
4158 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4159 break;
4160 case 7:
4161 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4162 break;
4163 case 8:
4164 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4165 break;
4166 case 9:
4167 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4168 break;
4169 default:
4170 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4171 res = -1;
4172 break;
4174 break;
4175 default:
4176 FIXME("unsupported calling convention %d\n",callconv);
4177 res = -1;
4178 break;
4180 TRACE("returns %08lx\n",res);
4181 return res;
4184 extern int const _argsize(DWORD vt);
4186 /****************************************************************************
4187 * Helper functions for Dispcall / Invoke, which copies one variant
4188 * with target type onto the argument stack.
4190 static HRESULT
4191 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4192 DWORD *argpos, VARIANT *arg, VARTYPE vt
4194 UINT arglen = _argsize(vt)*sizeof(DWORD);
4195 VARTYPE oldvt;
4197 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4198 memcpy(argpos,&arg,sizeof(void*));
4199 return S_OK;
4202 if (V_VT(arg) == vt) {
4203 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4204 return S_OK;
4207 if (vt == VT_VARIANT) {
4208 memcpy(argpos, arg, arglen);
4209 return S_OK;
4211 /* Deref BYREF vars if there is need */
4212 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4213 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4214 return S_OK;
4216 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4217 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4218 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4219 return S_OK;
4221 if ((vt == VT_PTR) && tdesc)
4222 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4223 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4224 ITypeInfo *tinfo2;
4225 TYPEATTR *tattr;
4226 HRESULT hres;
4228 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4229 if (hres) {
4230 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));
4231 memcpy(argpos, &V_UNION(arg,lVal), 4);
4232 return S_OK;
4234 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4235 switch (tattr->typekind) {
4236 case TKIND_ENUM:
4237 if (V_VT(arg) == VT_I4) {
4238 memcpy(argpos, &V_UNION(arg,iVal), 4);
4239 return S_OK;
4241 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4242 break;
4243 case TKIND_ALIAS:
4244 tdesc = &(tattr->tdescAlias);
4245 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4246 ITypeInfo_Release(tinfo2);
4247 return hres;
4249 case TKIND_INTERFACE:
4250 if (V_VT(arg) == VT_DISPATCH) {
4251 IDispatch *disp;
4252 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4253 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4254 return S_OK;
4256 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),&IID_IDispatch,(LPVOID*)&disp);
4257 if (SUCCEEDED(hres)) {
4258 memcpy(argpos,&disp,4);
4259 IUnknown_Release(V_UNION(arg,pdispVal));
4260 return S_OK;
4262 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4263 return E_FAIL;
4265 if (V_VT(arg) == VT_UNKNOWN) {
4266 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4267 return S_OK;
4269 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg),debugstr_guid(&(tattr->guid)));
4270 break;
4271 case TKIND_DISPATCH:
4272 if (V_VT(arg) == VT_DISPATCH) {
4273 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4274 return S_OK;
4276 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4277 break;
4278 case TKIND_RECORD:
4279 FIXME("TKIND_RECORD unhandled.\n");
4280 break;
4281 default:
4282 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4283 break;
4285 return E_FAIL;
4287 oldvt = V_VT(arg);
4288 if (VariantChangeType(arg,arg,0,vt)==S_OK) {
4289 FIXME("argument was coerced in-place (0x%x -> 0x%x); source data has been modified!!!\n", oldvt, vt);
4290 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4291 return S_OK;
4293 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4294 return E_FAIL;
4297 /***********************************************************************
4298 * DispCallFunc (OLEAUT32.@)
4300 HRESULT WINAPI
4301 DispCallFunc(
4302 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4303 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4305 int i, argsize, argspos;
4306 DWORD *args;
4307 HRESULT hres;
4309 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4310 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4312 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4313 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4314 argsize = 1;
4315 for (i=0;i<cActuals;i++) {
4316 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4317 dump_Variant(prgpvarg[i]);
4318 argsize += _argsize(prgvt[i]);
4320 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4321 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4322 argspos = 1;
4323 for (i=0;i<cActuals;i++) {
4324 VARIANT *arg = prgpvarg[i];
4325 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4326 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4327 argspos += _argsize(prgvt[i]);
4330 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4332 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4333 hres=S_OK;
4335 else
4337 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4338 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4339 FIXME("Method returned %lx\n",hres);
4341 HeapFree(GetProcessHeap(),0,args);
4342 return hres;
4345 static HRESULT WINAPI ITypeInfo_fnInvoke(
4346 ITypeInfo2 *iface,
4347 VOID *pIUnk,
4348 MEMBERID memid,
4349 UINT16 dwFlags,
4350 DISPPARAMS *pDispParams,
4351 VARIANT *pVarResult,
4352 EXCEPINFO *pExcepInfo,
4353 UINT *pArgErr)
4355 ICOM_THIS( ITypeInfoImpl, iface);
4356 TLBFuncDesc * pFDesc;
4357 TLBVarDesc * pVDesc;
4358 int i;
4359 HRESULT hres;
4361 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4362 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4364 dump_DispParms(pDispParams);
4366 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4367 if (pFDesc->funcdesc.memid == memid) {
4368 if (pFDesc->funcdesc.invkind & dwFlags)
4369 break;
4371 if (pFDesc) {
4372 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4373 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4374 switch (pFDesc->funcdesc.funckind) {
4375 case FUNC_PUREVIRTUAL:
4376 case FUNC_VIRTUAL: {
4377 DWORD res;
4378 int numargs, numargs2, argspos, args2pos;
4379 DWORD *args , *args2;
4382 numargs = 1; numargs2 = 0;
4383 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4384 if (i<pDispParams->cArgs)
4385 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4386 else {
4387 numargs += 1; /* sizeof(lpvoid) */
4388 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4392 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4393 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4395 args[0] = (DWORD)pIUnk;
4396 argspos = 1; args2pos = 0;
4397 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4398 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4399 if (i<pDispParams->cArgs) {
4400 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4401 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4402 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4403 if (FAILED(hres)) return hres;
4404 argspos += arglen;
4405 } else {
4406 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4407 if (tdesc->vt != VT_PTR)
4408 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4409 /*FIXME: give pointers for the rest, so propertyget works*/
4410 args[argspos] = (DWORD)&args2[args2pos];
4412 /* If pointer to variant, pass reference it. */
4413 if ((tdesc->vt == VT_PTR) &&
4414 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4415 pVarResult
4417 args[argspos]= (DWORD)pVarResult;
4418 argspos += 1;
4419 args2pos += arglen;
4422 if (pFDesc->funcdesc.cParamsOpt)
4423 FIXME("Does not support optional parameters (%d)\n",
4424 pFDesc->funcdesc.cParamsOpt
4427 res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4],
4428 pFDesc->funcdesc.callconv,
4429 numargs,
4430 args
4432 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4433 args2pos = 0;
4434 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4435 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4436 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4437 /* If we are a pointer to a variant, we are done already */
4438 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4439 continue;
4441 VariantInit(pVarResult);
4442 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4444 if (tdesc->vt == VT_PTR)
4445 tdesc = tdesc->u.lptdesc;
4446 if (tdesc->vt == VT_USERDEFINED) {
4447 ITypeInfo *tinfo2;
4448 TYPEATTR *tattr;
4450 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4451 if (hres) {
4452 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4453 return E_FAIL;
4455 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4456 switch (tattr->typekind) {
4457 case TKIND_ENUM:
4458 FIXME("TKIND_ENUM unhandled.\n");
4459 break;
4460 case TKIND_ALIAS:
4461 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4462 tdesc = &(tattr->tdescAlias);
4463 break;
4465 case TKIND_INTERFACE:
4466 FIXME("TKIND_INTERFACE unhandled.\n");
4467 break;
4468 case TKIND_DISPATCH:
4469 FIXME("TKIND_DISPATCH unhandled.\n");
4470 break;
4471 case TKIND_RECORD:
4472 FIXME("TKIND_RECORD unhandled.\n");
4473 break;
4474 default:
4475 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4476 break;
4478 ITypeInfo_Release(tinfo2);
4480 V_VT(pVarResult) = tdesc->vt;
4482 /* HACK: VB5 likes this.
4483 * I do not know why. There is 1 example in MSDN which uses
4484 * this which appears broken (mixes int vals and
4485 * IDispatch*.).
4487 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4488 V_VT(pVarResult) = VT_DISPATCH;
4489 TRACE("storing into variant:\n");
4490 dump_Variant(pVarResult);
4491 args2pos += arglen;
4494 HeapFree(GetProcessHeap(),0,args2);
4495 HeapFree(GetProcessHeap(),0,args);
4496 return S_OK;
4498 case FUNC_DISPATCH: {
4499 IDispatch *disp;
4500 HRESULT hr;
4502 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4503 if (hr) {
4504 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4505 return hr;
4507 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4508 hr = IDispatch_Invoke(
4509 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4510 pVarResult,pExcepInfo,pArgErr
4512 if (hr)
4513 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4514 IDispatch_Release(disp);
4515 return hr;
4517 default:
4518 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4519 return E_FAIL;
4521 } else {
4522 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4523 if (pVDesc->vardesc.memid == memid) {
4524 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4525 dump_TLBVarDesc(pVDesc);
4526 break;
4530 /* not found, look for it in inherited interfaces */
4531 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4532 /* recursive search */
4533 ITypeInfo *pTInfo;
4534 HRESULT hr;
4535 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4536 if(SUCCEEDED(hr)){
4537 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4538 ITypeInfo_Release(pTInfo);
4539 return hr;
4541 WARN("Could not search inherited interface!\n");
4543 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4544 return DISP_E_MEMBERNOTFOUND;
4547 /* ITypeInfo::GetDocumentation
4549 * Retrieves the documentation string, the complete Help file name and path,
4550 * and the context ID for the Help topic for a specified type description.
4552 * (Can be tested by the Visual Basic Editor in Word for instance.)
4554 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4555 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4556 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4558 ICOM_THIS( ITypeInfoImpl, iface);
4559 TLBFuncDesc * pFDesc;
4560 TLBVarDesc * pVDesc;
4561 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4562 " HelpContext(%p) HelpFile(%p)\n",
4563 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4564 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4565 if(pBstrName)
4566 *pBstrName=SysAllocString(This->Name);
4567 if(pBstrDocString)
4568 *pBstrDocString=SysAllocString(This->DocString);
4569 if(pdwHelpContext)
4570 *pdwHelpContext=This->dwHelpContext;
4571 if(pBstrHelpFile)
4572 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4573 return S_OK;
4574 }else {/* for a member */
4575 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4576 if(pFDesc->funcdesc.memid==memid){
4577 if(pBstrName)
4578 *pBstrName = SysAllocString(pFDesc->Name);
4579 if(pBstrDocString)
4580 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4581 if(pdwHelpContext)
4582 *pdwHelpContext=pFDesc->helpcontext;
4583 return S_OK;
4585 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4586 if(pVDesc->vardesc.memid==memid){
4587 if(pBstrName)
4588 *pBstrName = SysAllocString(pVDesc->Name);
4589 if(pBstrDocString)
4590 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4591 if(pdwHelpContext)
4592 *pdwHelpContext=pVDesc->HelpContext;
4593 return S_OK;
4596 return TYPE_E_ELEMENTNOTFOUND;
4599 /* ITypeInfo::GetDllEntry
4601 * Retrieves a description or specification of an entry point for a function
4602 * in a DLL.
4604 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4605 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4606 WORD *pwOrdinal)
4608 ICOM_THIS( ITypeInfoImpl, iface);
4609 TLBFuncDesc *pFDesc;
4611 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4613 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4614 if(pFDesc->funcdesc.memid==memid){
4615 dump_TypeInfo(This);
4616 dump_TLBFuncDescOne(pFDesc);
4618 /* FIXME: This is wrong, but how do you find that out? */
4619 if (pBstrDllName) {
4620 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4621 *pBstrDllName = SysAllocString(oleaut32W);
4624 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4625 if (pBstrName)
4626 *pBstrName = SysAllocString(pFDesc->Entry);
4627 if (pwOrdinal)
4628 *pwOrdinal = -1;
4629 return S_OK;
4631 if (pBstrName)
4632 *pBstrName = NULL;
4633 if (pwOrdinal)
4634 *pwOrdinal = (DWORD)pFDesc->Entry;
4635 return S_OK;
4637 return E_FAIL;
4640 /* ITypeInfo::GetRefTypeInfo
4642 * If a type description references other type descriptions, it retrieves
4643 * the referenced type descriptions.
4645 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4646 ITypeInfo2 *iface,
4647 HREFTYPE hRefType,
4648 ITypeInfo **ppTInfo)
4650 ICOM_THIS( ITypeInfoImpl, iface);
4651 HRESULT result = E_FAIL;
4654 if (hRefType == -1 &&
4655 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4656 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4658 /* when we meet a DUAL dispinterface, we must create the interface
4659 * version of it.
4661 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4664 /* the interface version contains the same information as the dispinterface
4665 * copy the contents of the structs.
4667 *pTypeInfoImpl = *This;
4668 pTypeInfoImpl->ref = 1;
4670 /* change the type to interface */
4671 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4673 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4675 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4677 result = S_OK;
4679 } else {
4680 TLBRefType *pRefType;
4681 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4682 if(pRefType->reference == hRefType)
4683 break;
4685 if(!pRefType)
4686 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4687 if(pRefType && hRefType != -1) {
4688 ITypeLib *pTLib = NULL;
4690 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4691 int Index;
4692 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4693 } else {
4694 if(pRefType->pImpTLInfo->pImpTypeLib) {
4695 TRACE("typeinfo in imported typelib that is already loaded\n");
4696 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4697 ITypeLib2_AddRef((ITypeLib*) pTLib);
4698 result = S_OK;
4699 } else {
4700 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4701 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4702 pRefType->pImpTLInfo->wVersionMajor,
4703 pRefType->pImpTLInfo->wVersionMinor,
4704 pRefType->pImpTLInfo->lcid,
4705 &pTLib);
4707 if(!SUCCEEDED(result)) {
4708 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4709 result=LoadTypeLib(libnam, &pTLib);
4710 SysFreeString(libnam);
4712 if(SUCCEEDED(result)) {
4713 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4714 ITypeLib2_AddRef(pTLib);
4718 if(SUCCEEDED(result)) {
4719 if(pRefType->index == TLB_REF_USE_GUID)
4720 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4721 &pRefType->guid,
4722 ppTInfo);
4723 else
4724 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4725 ppTInfo);
4727 if (pTLib != NULL)
4728 ITypeLib2_Release(pTLib);
4732 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4733 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4734 return result;
4737 /* ITypeInfo::AddressOfMember
4739 * Retrieves the addresses of static functions or variables, such as those
4740 * defined in a DLL.
4742 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4743 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4745 ICOM_THIS( ITypeInfoImpl, iface);
4746 FIXME("(%p) stub!\n", This);
4747 return S_OK;
4750 /* ITypeInfo::CreateInstance
4752 * Creates a new instance of a type that describes a component object class
4753 * (coclass).
4755 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4756 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4758 ICOM_THIS( ITypeInfoImpl, iface);
4759 FIXME("(%p) stub!\n", This);
4760 return S_OK;
4763 /* ITypeInfo::GetMops
4765 * Retrieves marshaling information.
4767 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4768 BSTR *pBstrMops)
4770 ICOM_THIS( ITypeInfoImpl, iface);
4771 FIXME("(%p) stub!\n", This);
4772 return S_OK;
4775 /* ITypeInfo::GetContainingTypeLib
4777 * Retrieves the containing type library and the index of the type description
4778 * within that type library.
4780 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4781 ITypeLib * *ppTLib, UINT *pIndex)
4783 ICOM_THIS( ITypeInfoImpl, iface);
4785 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
4786 if (pIndex) {
4787 *pIndex=This->index;
4788 TRACE("returning pIndex=%d", *pIndex);
4791 if (ppTLib) {
4792 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4793 ITypeLib2_AddRef(*ppTLib);
4794 TRACE("returning ppTLib=%p", *ppTLib);
4797 return S_OK;
4800 /* ITypeInfo::ReleaseTypeAttr
4802 * Releases a TYPEATTR previously returned by GetTypeAttr.
4805 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4806 TYPEATTR* pTypeAttr)
4808 ICOM_THIS( ITypeInfoImpl, iface);
4809 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4812 /* ITypeInfo::ReleaseFuncDesc
4814 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4816 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
4817 ITypeInfo2 *iface,
4818 FUNCDESC *pFuncDesc)
4820 ICOM_THIS( ITypeInfoImpl, iface);
4821 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4824 /* ITypeInfo::ReleaseVarDesc
4826 * Releases a VARDESC previously returned by GetVarDesc.
4828 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4829 VARDESC *pVarDesc)
4831 ICOM_THIS( ITypeInfoImpl, iface);
4832 TRACE("(%p)->(%p)\n", This, pVarDesc);
4835 /* ITypeInfo2::GetTypeKind
4837 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4840 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4841 TYPEKIND *pTypeKind)
4843 ICOM_THIS( ITypeInfoImpl, iface);
4844 *pTypeKind=This->TypeAttr.typekind;
4845 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4846 return S_OK;
4849 /* ITypeInfo2::GetTypeFlags
4851 * Returns the type flags without any allocations. This returns a DWORD type
4852 * flag, which expands the type flags without growing the TYPEATTR (type
4853 * attribute).
4856 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
4858 ICOM_THIS( ITypeInfoImpl, iface);
4859 *pTypeFlags=This->TypeAttr.wTypeFlags;
4860 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
4861 return S_OK;
4864 /* ITypeInfo2::GetFuncIndexOfMemId
4865 * Binds to a specific member based on a known DISPID, where the member name
4866 * is not known (for example, when binding to a default member).
4869 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4870 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4872 ICOM_THIS( ITypeInfoImpl, iface);
4873 TLBFuncDesc *pFuncInfo;
4874 int i;
4875 HRESULT result;
4876 /* FIXME: should check for invKind??? */
4877 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4878 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4879 if(pFuncInfo){
4880 *pFuncIndex=i;
4881 result= S_OK;
4882 }else{
4883 *pFuncIndex=0;
4884 result=E_INVALIDARG;
4886 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4887 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4888 return result;
4891 /* TypeInfo2::GetVarIndexOfMemId
4893 * Binds to a specific member based on a known DISPID, where the member name
4894 * is not known (for example, when binding to a default member).
4897 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4898 MEMBERID memid, UINT *pVarIndex)
4900 ICOM_THIS( ITypeInfoImpl, iface);
4901 TLBVarDesc *pVarInfo;
4902 int i;
4903 HRESULT result;
4904 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4905 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4907 if(pVarInfo){
4908 *pVarIndex=i;
4909 result= S_OK;
4910 }else{
4911 *pVarIndex=0;
4912 result=E_INVALIDARG;
4914 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4915 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4916 return result;
4919 /* ITypeInfo2::GetCustData
4921 * Gets the custom data
4923 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4924 ITypeInfo2 * iface,
4925 REFGUID guid,
4926 VARIANT *pVarVal)
4928 ICOM_THIS( ITypeInfoImpl, iface);
4929 TLBCustData *pCData;
4931 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4932 if( IsEqualIID(guid, &pCData->guid)) break;
4934 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4936 if(pCData)
4938 VariantInit( pVarVal);
4939 VariantCopy( pVarVal, &pCData->data);
4940 return S_OK;
4942 return E_INVALIDARG; /* FIXME: correct? */
4945 /* ITypeInfo2::GetFuncCustData
4947 * Gets the custom data
4949 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4950 ITypeInfo2 * iface,
4951 UINT index,
4952 REFGUID guid,
4953 VARIANT *pVarVal)
4955 ICOM_THIS( ITypeInfoImpl, iface);
4956 TLBCustData *pCData=NULL;
4957 TLBFuncDesc * pFDesc;
4958 int i;
4959 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4960 pFDesc=pFDesc->next);
4962 if(pFDesc)
4963 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4964 if( IsEqualIID(guid, &pCData->guid)) break;
4966 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4968 if(pCData){
4969 VariantInit( pVarVal);
4970 VariantCopy( pVarVal, &pCData->data);
4971 return S_OK;
4973 return E_INVALIDARG; /* FIXME: correct? */
4976 /* ITypeInfo2::GetParamCustData
4978 * Gets the custom data
4980 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4981 ITypeInfo2 * iface,
4982 UINT indexFunc,
4983 UINT indexParam,
4984 REFGUID guid,
4985 VARIANT *pVarVal)
4987 ICOM_THIS( ITypeInfoImpl, iface);
4988 TLBCustData *pCData=NULL;
4989 TLBFuncDesc * pFDesc;
4990 int i;
4992 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4994 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4995 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4996 pCData = pCData->next)
4997 if( IsEqualIID(guid, &pCData->guid)) break;
4999 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5001 if(pCData)
5003 VariantInit( pVarVal);
5004 VariantCopy( pVarVal, &pCData->data);
5005 return S_OK;
5007 return E_INVALIDARG; /* FIXME: correct? */
5010 /* ITypeInfo2::GetVarCustData
5012 * Gets the custom data
5014 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5015 ITypeInfo2 * iface,
5016 UINT index,
5017 REFGUID guid,
5018 VARIANT *pVarVal)
5020 ICOM_THIS( ITypeInfoImpl, iface);
5021 TLBCustData *pCData=NULL;
5022 TLBVarDesc * pVDesc;
5023 int i;
5025 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5027 if(pVDesc)
5029 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5031 if( IsEqualIID(guid, &pCData->guid)) break;
5035 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5037 if(pCData)
5039 VariantInit( pVarVal);
5040 VariantCopy( pVarVal, &pCData->data);
5041 return S_OK;
5043 return E_INVALIDARG; /* FIXME: correct? */
5046 /* ITypeInfo2::GetImplCustData
5048 * Gets the custom data
5050 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5051 ITypeInfo2 * iface,
5052 UINT index,
5053 REFGUID guid,
5054 VARIANT *pVarVal)
5056 ICOM_THIS( ITypeInfoImpl, iface);
5057 TLBCustData *pCData=NULL;
5058 TLBImplType * pRDesc;
5059 int i;
5061 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5063 if(pRDesc)
5065 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5067 if( IsEqualIID(guid, &pCData->guid)) break;
5071 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5073 if(pCData)
5075 VariantInit( pVarVal);
5076 VariantCopy( pVarVal, &pCData->data);
5077 return S_OK;
5079 return E_INVALIDARG; /* FIXME: correct? */
5082 /* ITypeInfo2::GetDocumentation2
5084 * Retrieves the documentation string, the complete Help file name and path,
5085 * the localization context to use, and the context ID for the library Help
5086 * topic in the Help file.
5089 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5090 ITypeInfo2 * iface,
5091 MEMBERID memid,
5092 LCID lcid,
5093 BSTR *pbstrHelpString,
5094 DWORD *pdwHelpStringContext,
5095 BSTR *pbstrHelpStringDll)
5097 ICOM_THIS( ITypeInfoImpl, iface);
5098 TLBFuncDesc * pFDesc;
5099 TLBVarDesc * pVDesc;
5100 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5101 "HelpStringContext(%p) HelpStringDll(%p)\n",
5102 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5103 pbstrHelpStringDll );
5104 /* the help string should be obtained from the helpstringdll,
5105 * using the _DLLGetDocumentation function, based on the supplied
5106 * lcid. Nice to do sometime...
5108 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5109 if(pbstrHelpString)
5110 *pbstrHelpString=SysAllocString(This->Name);
5111 if(pdwHelpStringContext)
5112 *pdwHelpStringContext=This->dwHelpStringContext;
5113 if(pbstrHelpStringDll)
5114 *pbstrHelpStringDll=
5115 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5116 return S_OK;
5117 }else {/* for a member */
5118 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5119 if(pFDesc->funcdesc.memid==memid){
5120 if(pbstrHelpString)
5121 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5122 if(pdwHelpStringContext)
5123 *pdwHelpStringContext=pFDesc->HelpStringContext;
5124 if(pbstrHelpStringDll)
5125 *pbstrHelpStringDll=
5126 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5127 return S_OK;
5129 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5130 if(pVDesc->vardesc.memid==memid){
5131 if(pbstrHelpString)
5132 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5133 if(pdwHelpStringContext)
5134 *pdwHelpStringContext=pVDesc->HelpStringContext;
5135 if(pbstrHelpStringDll)
5136 *pbstrHelpStringDll=
5137 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5138 return S_OK;
5141 return TYPE_E_ELEMENTNOTFOUND;
5144 /* ITypeInfo2::GetAllCustData
5146 * Gets all custom data items for the Type info.
5149 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5150 ITypeInfo2 * iface,
5151 CUSTDATA *pCustData)
5153 ICOM_THIS( ITypeInfoImpl, iface);
5154 TLBCustData *pCData;
5155 int i;
5157 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5159 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5160 if(pCustData->prgCustData ){
5161 pCustData->cCustData=This->ctCustData;
5162 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5163 pCustData->prgCustData[i].guid=pCData->guid;
5164 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5166 }else{
5167 ERR(" OUT OF MEMORY! \n");
5168 return E_OUTOFMEMORY;
5170 return S_OK;
5173 /* ITypeInfo2::GetAllFuncCustData
5175 * Gets all custom data items for the specified Function
5178 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5179 ITypeInfo2 * iface,
5180 UINT index,
5181 CUSTDATA *pCustData)
5183 ICOM_THIS( ITypeInfoImpl, iface);
5184 TLBCustData *pCData;
5185 TLBFuncDesc * pFDesc;
5186 int i;
5187 TRACE("(%p) index %d\n", This, index);
5188 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5189 pFDesc=pFDesc->next)
5191 if(pFDesc){
5192 pCustData->prgCustData =
5193 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5194 if(pCustData->prgCustData ){
5195 pCustData->cCustData=pFDesc->ctCustData;
5196 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5197 pCData = pCData->next){
5198 pCustData->prgCustData[i].guid=pCData->guid;
5199 VariantCopy(& pCustData->prgCustData[i].varValue,
5200 & pCData->data);
5202 }else{
5203 ERR(" OUT OF MEMORY! \n");
5204 return E_OUTOFMEMORY;
5206 return S_OK;
5208 return TYPE_E_ELEMENTNOTFOUND;
5211 /* ITypeInfo2::GetAllParamCustData
5213 * Gets all custom data items for the Functions
5216 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5217 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5219 ICOM_THIS( ITypeInfoImpl, iface);
5220 TLBCustData *pCData=NULL;
5221 TLBFuncDesc * pFDesc;
5222 int i;
5223 TRACE("(%p) index %d\n", This, indexFunc);
5224 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5225 pFDesc=pFDesc->next)
5227 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5228 pCustData->prgCustData =
5229 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5230 sizeof(CUSTDATAITEM));
5231 if(pCustData->prgCustData ){
5232 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5233 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5234 pCData; i++, pCData = pCData->next){
5235 pCustData->prgCustData[i].guid=pCData->guid;
5236 VariantCopy(& pCustData->prgCustData[i].varValue,
5237 & pCData->data);
5239 }else{
5240 ERR(" OUT OF MEMORY! \n");
5241 return E_OUTOFMEMORY;
5243 return S_OK;
5245 return TYPE_E_ELEMENTNOTFOUND;
5248 /* ITypeInfo2::GetAllVarCustData
5250 * Gets all custom data items for the specified Variable
5253 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5254 UINT index, CUSTDATA *pCustData)
5256 ICOM_THIS( ITypeInfoImpl, iface);
5257 TLBCustData *pCData;
5258 TLBVarDesc * pVDesc;
5259 int i;
5260 TRACE("(%p) index %d\n", This, index);
5261 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5262 pVDesc=pVDesc->next)
5264 if(pVDesc){
5265 pCustData->prgCustData =
5266 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5267 if(pCustData->prgCustData ){
5268 pCustData->cCustData=pVDesc->ctCustData;
5269 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5270 pCData = pCData->next){
5271 pCustData->prgCustData[i].guid=pCData->guid;
5272 VariantCopy(& pCustData->prgCustData[i].varValue,
5273 & pCData->data);
5275 }else{
5276 ERR(" OUT OF MEMORY! \n");
5277 return E_OUTOFMEMORY;
5279 return S_OK;
5281 return TYPE_E_ELEMENTNOTFOUND;
5284 /* ITypeInfo2::GetAllImplCustData
5286 * Gets all custom data items for the specified implementation type
5289 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5290 ITypeInfo2 * iface,
5291 UINT index,
5292 CUSTDATA *pCustData)
5294 ICOM_THIS( ITypeInfoImpl, iface);
5295 TLBCustData *pCData;
5296 TLBImplType * pRDesc;
5297 int i;
5298 TRACE("(%p) index %d\n", This, index);
5299 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5300 pRDesc=pRDesc->next)
5302 if(pRDesc){
5303 pCustData->prgCustData =
5304 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5305 if(pCustData->prgCustData ){
5306 pCustData->cCustData=pRDesc->ctCustData;
5307 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5308 pCData = pCData->next){
5309 pCustData->prgCustData[i].guid=pCData->guid;
5310 VariantCopy(& pCustData->prgCustData[i].varValue,
5311 & pCData->data);
5313 }else{
5314 ERR(" OUT OF MEMORY! \n");
5315 return E_OUTOFMEMORY;
5317 return S_OK;
5319 return TYPE_E_ELEMENTNOTFOUND;
5322 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5324 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5326 ITypeInfo_fnQueryInterface,
5327 ITypeInfo_fnAddRef,
5328 ITypeInfo_fnRelease,
5330 ITypeInfo_fnGetTypeAttr,
5331 ITypeInfo_fnGetTypeComp,
5332 ITypeInfo_fnGetFuncDesc,
5333 ITypeInfo_fnGetVarDesc,
5334 ITypeInfo_fnGetNames,
5335 ITypeInfo_fnGetRefTypeOfImplType,
5336 ITypeInfo_fnGetImplTypeFlags,
5337 ITypeInfo_fnGetIDsOfNames,
5338 ITypeInfo_fnInvoke,
5339 ITypeInfo_fnGetDocumentation,
5340 ITypeInfo_fnGetDllEntry,
5341 ITypeInfo_fnGetRefTypeInfo,
5342 ITypeInfo_fnAddressOfMember,
5343 ITypeInfo_fnCreateInstance,
5344 ITypeInfo_fnGetMops,
5345 ITypeInfo_fnGetContainingTypeLib,
5346 ITypeInfo_fnReleaseTypeAttr,
5347 ITypeInfo_fnReleaseFuncDesc,
5348 ITypeInfo_fnReleaseVarDesc,
5350 ITypeInfo2_fnGetTypeKind,
5351 ITypeInfo2_fnGetTypeFlags,
5352 ITypeInfo2_fnGetFuncIndexOfMemId,
5353 ITypeInfo2_fnGetVarIndexOfMemId,
5354 ITypeInfo2_fnGetCustData,
5355 ITypeInfo2_fnGetFuncCustData,
5356 ITypeInfo2_fnGetParamCustData,
5357 ITypeInfo2_fnGetVarCustData,
5358 ITypeInfo2_fnGetImplTypeCustData,
5359 ITypeInfo2_fnGetDocumentation2,
5360 ITypeInfo2_fnGetAllCustData,
5361 ITypeInfo2_fnGetAllFuncCustData,
5362 ITypeInfo2_fnGetAllParamCustData,
5363 ITypeInfo2_fnGetAllVarCustData,
5364 ITypeInfo2_fnGetAllImplTypeCustData,