Print a large failure message if we try to load stdole32.tlb and
[wine.git] / dlls / oleaut32 / typelib.c
blob0d30b16b13b86e768f5c0f09aad8180a566676ba
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 ICOM_VTBL(pTypeLibImpl) = &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 ICOM_VTBL(pTypeLibImpl) = &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 ICOM_VTBL(pTypeInfoImpl) = &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(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
4126 DWORD res;
4128 if (TRACE_ON(ole)) {
4129 int i;
4130 MESSAGE("Calling %p(",func);
4131 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
4132 MESSAGE(")\n");
4135 switch (callconv) {
4136 case CC_STDCALL:
4138 switch (nrargs) {
4139 case 0: {
4140 DWORD (WINAPI *xfunc)() = func;
4141 res = xfunc();
4142 break;
4144 case 1: {
4145 DWORD (WINAPI *xfunc)(DWORD) = func;
4146 res = xfunc(args[0]);
4147 break;
4149 case 2: {
4150 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
4151 res = xfunc(args[0],args[1]);
4152 break;
4154 case 3: {
4155 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
4156 res = xfunc(args[0],args[1],args[2]);
4157 break;
4159 case 4: {
4160 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD) = func;
4161 res = xfunc(args[0],args[1],args[2],args[3]);
4162 break;
4164 case 5: {
4165 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4166 res = xfunc(args[0],args[1],args[2],args[3],args[4]);
4167 break;
4169 case 6: {
4170 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4171 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5]);
4172 break;
4174 case 7: {
4175 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4176 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4177 break;
4179 case 8: {
4180 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4181 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4182 break;
4184 case 9: {
4185 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4186 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4187 break;
4189 default:
4190 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4191 res = -1;
4192 break;
4194 break;
4195 default:
4196 FIXME("unsupported calling convention %d\n",callconv);
4197 res = -1;
4198 break;
4200 TRACE("returns %08lx\n",res);
4201 return res;
4204 extern int const _argsize(DWORD vt);
4206 /****************************************************************************
4207 * Helper functions for Dispcall / Invoke, which copies one variant
4208 * with target type onto the argument stack.
4210 static HRESULT
4211 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4212 DWORD *argpos, VARIANT *arg, VARTYPE vt
4214 UINT arglen = _argsize(vt)*sizeof(DWORD);
4215 VARTYPE oldvt;
4217 if (V_VT(arg) == vt) {
4218 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4219 return S_OK;
4222 if (vt == VT_VARIANT) {
4223 memcpy(argpos, arg, arglen);
4224 return S_OK;
4226 /* Deref BYREF vars if there is need */
4227 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4228 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4229 return S_OK;
4231 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4232 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4233 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4234 return S_OK;
4236 if ((vt == VT_PTR) && tdesc)
4237 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4238 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4239 ITypeInfo *tinfo2;
4240 TYPEATTR *tattr;
4241 HRESULT hres;
4243 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4244 if (hres) {
4245 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));
4246 memcpy(argpos, &V_UNION(arg,lVal), 4);
4247 return S_OK;
4249 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4250 switch (tattr->typekind) {
4251 case TKIND_ENUM:
4252 if (V_VT(arg) == VT_I4) {
4253 memcpy(argpos, &V_UNION(arg,iVal), 4);
4254 return S_OK;
4256 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4257 break;
4258 case TKIND_ALIAS:
4259 tdesc = &(tattr->tdescAlias);
4260 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4261 ITypeInfo_Release(tinfo2);
4262 return hres;
4264 case TKIND_INTERFACE:
4265 if (V_VT(arg) == VT_DISPATCH) {
4266 IDispatch *disp;
4267 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4268 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4269 return S_OK;
4271 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),&IID_IDispatch,(LPVOID*)&disp);
4272 if (SUCCEEDED(hres)) {
4273 memcpy(argpos,&disp,4);
4274 IUnknown_Release(V_UNION(arg,pdispVal));
4275 return S_OK;
4277 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4278 return E_FAIL;
4280 if (V_VT(arg) == VT_UNKNOWN) {
4281 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4282 return S_OK;
4284 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg),debugstr_guid(&(tattr->guid)));
4285 break;
4286 case TKIND_DISPATCH:
4287 if (V_VT(arg) == VT_DISPATCH) {
4288 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4289 return S_OK;
4291 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4292 break;
4293 case TKIND_RECORD:
4294 FIXME("TKIND_RECORD unhandled.\n");
4295 break;
4296 default:
4297 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4298 break;
4300 return E_FAIL;
4302 oldvt = V_VT(arg);
4303 if (VariantChangeType(arg,arg,0,vt)==S_OK) {
4304 FIXME("argument was coerced in-place (0x%x -> 0x%x); source data has been modified!!!\n", oldvt, vt);
4305 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4306 return S_OK;
4308 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4309 return E_FAIL;
4312 /***********************************************************************
4313 * DispCallFunc (OLEAUT32.@)
4315 HRESULT WINAPI
4316 DispCallFunc(
4317 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4318 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4320 int i, argsize, argspos;
4321 DWORD *args;
4322 HRESULT hres;
4324 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4325 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4327 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4328 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4329 argsize = 1;
4330 for (i=0;i<cActuals;i++) {
4331 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4332 dump_Variant(prgpvarg[i]);
4333 argsize += _argsize(prgvt[i]);
4335 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4336 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4337 argspos = 1;
4338 for (i=0;i<cActuals;i++) {
4339 VARIANT *arg = prgpvarg[i];
4340 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4341 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4342 argspos += _argsize(prgvt[i]);
4345 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4347 _invoke((*(DWORD***)pvInstance)[oVft/4],cc,argsize,args);
4348 hres=S_OK;
4350 else
4352 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4353 hres = _invoke((*(DWORD***)pvInstance)[oVft/4],cc,argsize,args);
4354 FIXME("Method returned %lx\n",hres);
4356 HeapFree(GetProcessHeap(),0,args);
4357 return hres;
4360 static HRESULT WINAPI ITypeInfo_fnInvoke(
4361 ITypeInfo2 *iface,
4362 VOID *pIUnk,
4363 MEMBERID memid,
4364 UINT16 dwFlags,
4365 DISPPARAMS *pDispParams,
4366 VARIANT *pVarResult,
4367 EXCEPINFO *pExcepInfo,
4368 UINT *pArgErr)
4370 ICOM_THIS( ITypeInfoImpl, iface);
4371 TLBFuncDesc * pFDesc;
4372 TLBVarDesc * pVDesc;
4373 int i;
4374 HRESULT hres;
4376 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4377 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4379 dump_DispParms(pDispParams);
4381 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4382 if (pFDesc->funcdesc.memid == memid) {
4383 if (pFDesc->funcdesc.invkind & dwFlags)
4384 break;
4386 if (pFDesc) {
4387 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4388 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4389 switch (pFDesc->funcdesc.funckind) {
4390 case FUNC_PUREVIRTUAL:
4391 case FUNC_VIRTUAL: {
4392 DWORD res;
4393 int numargs, numargs2, argspos, args2pos;
4394 DWORD *args , *args2;
4397 numargs = 1; numargs2 = 0;
4398 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4399 if (i<pDispParams->cArgs)
4400 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4401 else {
4402 numargs += 1; /* sizeof(lpvoid) */
4403 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4407 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4408 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4410 args[0] = (DWORD)pIUnk;
4411 argspos = 1; args2pos = 0;
4412 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4413 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4414 if (i<pDispParams->cArgs) {
4415 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4416 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4417 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4418 if (FAILED(hres)) return hres;
4419 argspos += arglen;
4420 } else {
4421 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4422 if (tdesc->vt != VT_PTR)
4423 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4424 /*FIXME: give pointers for the rest, so propertyget works*/
4425 args[argspos] = (DWORD)&args2[args2pos];
4427 /* If pointer to variant, pass reference it. */
4428 if ((tdesc->vt == VT_PTR) &&
4429 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4430 pVarResult
4432 args[argspos]= (DWORD)pVarResult;
4433 argspos += 1;
4434 args2pos += arglen;
4437 if (pFDesc->funcdesc.cParamsOpt)
4438 FIXME("Does not support optional parameters (%d)\n",
4439 pFDesc->funcdesc.cParamsOpt
4442 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4443 pFDesc->funcdesc.callconv,
4444 numargs,
4445 args
4447 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4448 args2pos = 0;
4449 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4450 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4451 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4452 /* If we are a pointer to a variant, we are done already */
4453 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4454 continue;
4456 VariantInit(pVarResult);
4457 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4459 if (tdesc->vt == VT_PTR)
4460 tdesc = tdesc->u.lptdesc;
4461 if (tdesc->vt == VT_USERDEFINED) {
4462 ITypeInfo *tinfo2;
4463 TYPEATTR *tattr;
4465 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4466 if (hres) {
4467 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4468 return E_FAIL;
4470 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4471 switch (tattr->typekind) {
4472 case TKIND_ENUM:
4473 FIXME("TKIND_ENUM unhandled.\n");
4474 break;
4475 case TKIND_ALIAS:
4476 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4477 tdesc = &(tattr->tdescAlias);
4478 break;
4480 case TKIND_INTERFACE:
4481 FIXME("TKIND_INTERFACE unhandled.\n");
4482 break;
4483 case TKIND_DISPATCH:
4484 FIXME("TKIND_DISPATCH unhandled.\n");
4485 break;
4486 case TKIND_RECORD:
4487 FIXME("TKIND_RECORD unhandled.\n");
4488 break;
4489 default:
4490 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4491 break;
4493 ITypeInfo_Release(tinfo2);
4495 V_VT(pVarResult) = tdesc->vt;
4497 /* HACK: VB5 likes this.
4498 * I do not know why. There is 1 example in MSDN which uses
4499 * this which appears broken (mixes int vals and
4500 * IDispatch*.).
4502 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4503 V_VT(pVarResult) = VT_DISPATCH;
4504 TRACE("storing into variant:\n");
4505 dump_Variant(pVarResult);
4506 args2pos += arglen;
4509 HeapFree(GetProcessHeap(),0,args2);
4510 HeapFree(GetProcessHeap(),0,args);
4511 return S_OK;
4513 case FUNC_DISPATCH: {
4514 IDispatch *disp;
4515 HRESULT hr;
4517 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4518 if (hr) {
4519 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4520 return hr;
4522 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4523 hr = IDispatch_Invoke(
4524 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4525 pVarResult,pExcepInfo,pArgErr
4527 if (hr)
4528 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4529 IDispatch_Release(disp);
4530 return hr;
4532 default:
4533 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4534 return E_FAIL;
4536 } else {
4537 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4538 if (pVDesc->vardesc.memid == memid) {
4539 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4540 dump_TLBVarDesc(pVDesc);
4541 break;
4545 /* not found, look for it in inherited interfaces */
4546 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4547 /* recursive search */
4548 ITypeInfo *pTInfo;
4549 HRESULT hr;
4550 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4551 if(SUCCEEDED(hr)){
4552 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4553 ITypeInfo_Release(pTInfo);
4554 return hr;
4556 WARN("Could not search inherited interface!\n");
4558 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4559 return DISP_E_MEMBERNOTFOUND;
4562 /* ITypeInfo::GetDocumentation
4564 * Retrieves the documentation string, the complete Help file name and path,
4565 * and the context ID for the Help topic for a specified type description.
4567 * (Can be tested by the Visual Basic Editor in Word for instance.)
4569 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4570 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4571 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4573 ICOM_THIS( ITypeInfoImpl, iface);
4574 TLBFuncDesc * pFDesc;
4575 TLBVarDesc * pVDesc;
4576 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4577 " HelpContext(%p) HelpFile(%p)\n",
4578 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4579 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4580 if(pBstrName)
4581 *pBstrName=SysAllocString(This->Name);
4582 if(pBstrDocString)
4583 *pBstrDocString=SysAllocString(This->DocString);
4584 if(pdwHelpContext)
4585 *pdwHelpContext=This->dwHelpContext;
4586 if(pBstrHelpFile)
4587 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4588 return S_OK;
4589 }else {/* for a member */
4590 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4591 if(pFDesc->funcdesc.memid==memid){
4592 if(pBstrName)
4593 *pBstrName = SysAllocString(pFDesc->Name);
4594 if(pBstrDocString)
4595 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4596 if(pdwHelpContext)
4597 *pdwHelpContext=pFDesc->helpcontext;
4598 return S_OK;
4600 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4601 if(pVDesc->vardesc.memid==memid){
4602 if(pBstrName)
4603 *pBstrName = SysAllocString(pVDesc->Name);
4604 if(pBstrDocString)
4605 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4606 if(pdwHelpContext)
4607 *pdwHelpContext=pVDesc->HelpContext;
4608 return S_OK;
4611 return TYPE_E_ELEMENTNOTFOUND;
4614 /* ITypeInfo::GetDllEntry
4616 * Retrieves a description or specification of an entry point for a function
4617 * in a DLL.
4619 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4620 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4621 WORD *pwOrdinal)
4623 ICOM_THIS( ITypeInfoImpl, iface);
4624 TLBFuncDesc *pFDesc;
4626 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4628 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4629 if(pFDesc->funcdesc.memid==memid){
4630 dump_TypeInfo(This);
4631 dump_TLBFuncDescOne(pFDesc);
4633 /* FIXME: This is wrong, but how do you find that out? */
4634 if (pBstrDllName) {
4635 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4636 *pBstrDllName = SysAllocString(oleaut32W);
4639 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4640 if (pBstrName)
4641 *pBstrName = SysAllocString(pFDesc->Entry);
4642 if (pwOrdinal)
4643 *pwOrdinal = -1;
4644 return S_OK;
4646 if (pBstrName)
4647 *pBstrName = NULL;
4648 if (pwOrdinal)
4649 *pwOrdinal = (DWORD)pFDesc->Entry;
4650 return S_OK;
4652 return E_FAIL;
4655 /* ITypeInfo::GetRefTypeInfo
4657 * If a type description references other type descriptions, it retrieves
4658 * the referenced type descriptions.
4660 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4661 ITypeInfo2 *iface,
4662 HREFTYPE hRefType,
4663 ITypeInfo **ppTInfo)
4665 ICOM_THIS( ITypeInfoImpl, iface);
4666 HRESULT result = E_FAIL;
4669 if (hRefType == -1 &&
4670 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4671 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4673 /* when we meet a DUAL dispinterface, we must create the interface
4674 * version of it.
4676 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4679 /* the interface version contains the same information as the dispinterface
4680 * copy the contents of the structs.
4682 *pTypeInfoImpl = *This;
4683 pTypeInfoImpl->ref = 1;
4685 /* change the type to interface */
4686 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4688 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4690 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4692 result = S_OK;
4694 } else {
4695 TLBRefType *pRefType;
4696 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4697 if(pRefType->reference == hRefType)
4698 break;
4700 if(!pRefType)
4701 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4702 if(pRefType && hRefType != -1) {
4703 ITypeLib *pTLib = NULL;
4705 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4706 int Index;
4707 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4708 } else {
4709 if(pRefType->pImpTLInfo->pImpTypeLib) {
4710 TRACE("typeinfo in imported typelib that is already loaded\n");
4711 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4712 ITypeLib2_AddRef((ITypeLib*) pTLib);
4713 result = S_OK;
4714 } else {
4715 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4716 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4717 pRefType->pImpTLInfo->wVersionMajor,
4718 pRefType->pImpTLInfo->wVersionMinor,
4719 pRefType->pImpTLInfo->lcid,
4720 &pTLib);
4722 if(!SUCCEEDED(result)) {
4723 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4724 result=LoadTypeLib(libnam, &pTLib);
4725 SysFreeString(libnam);
4727 if(SUCCEEDED(result)) {
4728 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4729 ITypeLib2_AddRef(pTLib);
4733 if(SUCCEEDED(result)) {
4734 if(pRefType->index == TLB_REF_USE_GUID)
4735 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4736 &pRefType->guid,
4737 ppTInfo);
4738 else
4739 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4740 ppTInfo);
4742 if (pTLib != NULL)
4743 ITypeLib2_Release(pTLib);
4747 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4748 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4749 return result;
4752 /* ITypeInfo::AddressOfMember
4754 * Retrieves the addresses of static functions or variables, such as those
4755 * defined in a DLL.
4757 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4758 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4760 ICOM_THIS( ITypeInfoImpl, iface);
4761 FIXME("(%p) stub!\n", This);
4762 return S_OK;
4765 /* ITypeInfo::CreateInstance
4767 * Creates a new instance of a type that describes a component object class
4768 * (coclass).
4770 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4771 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4773 ICOM_THIS( ITypeInfoImpl, iface);
4774 FIXME("(%p) stub!\n", This);
4775 return S_OK;
4778 /* ITypeInfo::GetMops
4780 * Retrieves marshaling information.
4782 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4783 BSTR *pBstrMops)
4785 ICOM_THIS( ITypeInfoImpl, iface);
4786 FIXME("(%p) stub!\n", This);
4787 return S_OK;
4790 /* ITypeInfo::GetContainingTypeLib
4792 * Retrieves the containing type library and the index of the type description
4793 * within that type library.
4795 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4796 ITypeLib * *ppTLib, UINT *pIndex)
4798 ICOM_THIS( ITypeInfoImpl, iface);
4799 if (!pIndex)
4800 return E_INVALIDARG;
4801 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4802 *pIndex=This->index;
4803 ITypeLib2_AddRef(*ppTLib);
4804 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4805 return S_OK;
4808 /* ITypeInfo::ReleaseTypeAttr
4810 * Releases a TYPEATTR previously returned by GetTypeAttr.
4813 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4814 TYPEATTR* pTypeAttr)
4816 ICOM_THIS( ITypeInfoImpl, iface);
4817 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4820 /* ITypeInfo::ReleaseFuncDesc
4822 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4824 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
4825 ITypeInfo2 *iface,
4826 FUNCDESC *pFuncDesc)
4828 ICOM_THIS( ITypeInfoImpl, iface);
4829 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4832 /* ITypeInfo::ReleaseVarDesc
4834 * Releases a VARDESC previously returned by GetVarDesc.
4836 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4837 VARDESC *pVarDesc)
4839 ICOM_THIS( ITypeInfoImpl, iface);
4840 TRACE("(%p)->(%p)\n", This, pVarDesc);
4843 /* ITypeInfo2::GetTypeKind
4845 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4848 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4849 TYPEKIND *pTypeKind)
4851 ICOM_THIS( ITypeInfoImpl, iface);
4852 *pTypeKind=This->TypeAttr.typekind;
4853 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4854 return S_OK;
4857 /* ITypeInfo2::GetTypeFlags
4859 * Returns the type flags without any allocations. This returns a DWORD type
4860 * flag, which expands the type flags without growing the TYPEATTR (type
4861 * attribute).
4864 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
4866 ICOM_THIS( ITypeInfoImpl, iface);
4867 *pTypeFlags=This->TypeAttr.wTypeFlags;
4868 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
4869 return S_OK;
4872 /* ITypeInfo2::GetFuncIndexOfMemId
4873 * Binds to a specific member based on a known DISPID, where the member name
4874 * is not known (for example, when binding to a default member).
4877 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4878 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4880 ICOM_THIS( ITypeInfoImpl, iface);
4881 TLBFuncDesc *pFuncInfo;
4882 int i;
4883 HRESULT result;
4884 /* FIXME: should check for invKind??? */
4885 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4886 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4887 if(pFuncInfo){
4888 *pFuncIndex=i;
4889 result= S_OK;
4890 }else{
4891 *pFuncIndex=0;
4892 result=E_INVALIDARG;
4894 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4895 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4896 return result;
4899 /* TypeInfo2::GetVarIndexOfMemId
4901 * Binds to a specific member based on a known DISPID, where the member name
4902 * is not known (for example, when binding to a default member).
4905 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4906 MEMBERID memid, UINT *pVarIndex)
4908 ICOM_THIS( ITypeInfoImpl, iface);
4909 TLBVarDesc *pVarInfo;
4910 int i;
4911 HRESULT result;
4912 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4913 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4915 if(pVarInfo){
4916 *pVarIndex=i;
4917 result= S_OK;
4918 }else{
4919 *pVarIndex=0;
4920 result=E_INVALIDARG;
4922 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4923 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4924 return result;
4927 /* ITypeInfo2::GetCustData
4929 * Gets the custom data
4931 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4932 ITypeInfo2 * iface,
4933 REFGUID guid,
4934 VARIANT *pVarVal)
4936 ICOM_THIS( ITypeInfoImpl, iface);
4937 TLBCustData *pCData;
4939 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4940 if( IsEqualIID(guid, &pCData->guid)) break;
4942 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4944 if(pCData)
4946 VariantInit( pVarVal);
4947 VariantCopy( pVarVal, &pCData->data);
4948 return S_OK;
4950 return E_INVALIDARG; /* FIXME: correct? */
4953 /* ITypeInfo2::GetFuncCustData
4955 * Gets the custom data
4957 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4958 ITypeInfo2 * iface,
4959 UINT index,
4960 REFGUID guid,
4961 VARIANT *pVarVal)
4963 ICOM_THIS( ITypeInfoImpl, iface);
4964 TLBCustData *pCData=NULL;
4965 TLBFuncDesc * pFDesc;
4966 int i;
4967 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4968 pFDesc=pFDesc->next);
4970 if(pFDesc)
4971 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4972 if( IsEqualIID(guid, &pCData->guid)) break;
4974 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4976 if(pCData){
4977 VariantInit( pVarVal);
4978 VariantCopy( pVarVal, &pCData->data);
4979 return S_OK;
4981 return E_INVALIDARG; /* FIXME: correct? */
4984 /* ITypeInfo2::GetParamCustData
4986 * Gets the custom data
4988 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4989 ITypeInfo2 * iface,
4990 UINT indexFunc,
4991 UINT indexParam,
4992 REFGUID guid,
4993 VARIANT *pVarVal)
4995 ICOM_THIS( ITypeInfoImpl, iface);
4996 TLBCustData *pCData=NULL;
4997 TLBFuncDesc * pFDesc;
4998 int i;
5000 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5002 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5003 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5004 pCData = pCData->next)
5005 if( IsEqualIID(guid, &pCData->guid)) break;
5007 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5009 if(pCData)
5011 VariantInit( pVarVal);
5012 VariantCopy( pVarVal, &pCData->data);
5013 return S_OK;
5015 return E_INVALIDARG; /* FIXME: correct? */
5018 /* ITypeInfo2::GetVarCustData
5020 * Gets the custom data
5022 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5023 ITypeInfo2 * iface,
5024 UINT index,
5025 REFGUID guid,
5026 VARIANT *pVarVal)
5028 ICOM_THIS( ITypeInfoImpl, iface);
5029 TLBCustData *pCData=NULL;
5030 TLBVarDesc * pVDesc;
5031 int i;
5033 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5035 if(pVDesc)
5037 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5039 if( IsEqualIID(guid, &pCData->guid)) break;
5043 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5045 if(pCData)
5047 VariantInit( pVarVal);
5048 VariantCopy( pVarVal, &pCData->data);
5049 return S_OK;
5051 return E_INVALIDARG; /* FIXME: correct? */
5054 /* ITypeInfo2::GetImplCustData
5056 * Gets the custom data
5058 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5059 ITypeInfo2 * iface,
5060 UINT index,
5061 REFGUID guid,
5062 VARIANT *pVarVal)
5064 ICOM_THIS( ITypeInfoImpl, iface);
5065 TLBCustData *pCData=NULL;
5066 TLBImplType * pRDesc;
5067 int i;
5069 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5071 if(pRDesc)
5073 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5075 if( IsEqualIID(guid, &pCData->guid)) break;
5079 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5081 if(pCData)
5083 VariantInit( pVarVal);
5084 VariantCopy( pVarVal, &pCData->data);
5085 return S_OK;
5087 return E_INVALIDARG; /* FIXME: correct? */
5090 /* ITypeInfo2::GetDocumentation2
5092 * Retrieves the documentation string, the complete Help file name and path,
5093 * the localization context to use, and the context ID for the library Help
5094 * topic in the Help file.
5097 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5098 ITypeInfo2 * iface,
5099 MEMBERID memid,
5100 LCID lcid,
5101 BSTR *pbstrHelpString,
5102 DWORD *pdwHelpStringContext,
5103 BSTR *pbstrHelpStringDll)
5105 ICOM_THIS( ITypeInfoImpl, iface);
5106 TLBFuncDesc * pFDesc;
5107 TLBVarDesc * pVDesc;
5108 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5109 "HelpStringContext(%p) HelpStringDll(%p)\n",
5110 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5111 pbstrHelpStringDll );
5112 /* the help string should be obtained from the helpstringdll,
5113 * using the _DLLGetDocumentation function, based on the supplied
5114 * lcid. Nice to do sometime...
5116 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5117 if(pbstrHelpString)
5118 *pbstrHelpString=SysAllocString(This->Name);
5119 if(pdwHelpStringContext)
5120 *pdwHelpStringContext=This->dwHelpStringContext;
5121 if(pbstrHelpStringDll)
5122 *pbstrHelpStringDll=
5123 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5124 return S_OK;
5125 }else {/* for a member */
5126 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5127 if(pFDesc->funcdesc.memid==memid){
5128 if(pbstrHelpString)
5129 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5130 if(pdwHelpStringContext)
5131 *pdwHelpStringContext=pFDesc->HelpStringContext;
5132 if(pbstrHelpStringDll)
5133 *pbstrHelpStringDll=
5134 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5135 return S_OK;
5137 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5138 if(pVDesc->vardesc.memid==memid){
5139 if(pbstrHelpString)
5140 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5141 if(pdwHelpStringContext)
5142 *pdwHelpStringContext=pVDesc->HelpStringContext;
5143 if(pbstrHelpStringDll)
5144 *pbstrHelpStringDll=
5145 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5146 return S_OK;
5149 return TYPE_E_ELEMENTNOTFOUND;
5152 /* ITypeInfo2::GetAllCustData
5154 * Gets all custom data items for the Type info.
5157 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5158 ITypeInfo2 * iface,
5159 CUSTDATA *pCustData)
5161 ICOM_THIS( ITypeInfoImpl, iface);
5162 TLBCustData *pCData;
5163 int i;
5165 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5167 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5168 if(pCustData->prgCustData ){
5169 pCustData->cCustData=This->ctCustData;
5170 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5171 pCustData->prgCustData[i].guid=pCData->guid;
5172 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5174 }else{
5175 ERR(" OUT OF MEMORY! \n");
5176 return E_OUTOFMEMORY;
5178 return S_OK;
5181 /* ITypeInfo2::GetAllFuncCustData
5183 * Gets all custom data items for the specified Function
5186 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5187 ITypeInfo2 * iface,
5188 UINT index,
5189 CUSTDATA *pCustData)
5191 ICOM_THIS( ITypeInfoImpl, iface);
5192 TLBCustData *pCData;
5193 TLBFuncDesc * pFDesc;
5194 int i;
5195 TRACE("(%p) index %d\n", This, index);
5196 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5197 pFDesc=pFDesc->next)
5199 if(pFDesc){
5200 pCustData->prgCustData =
5201 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5202 if(pCustData->prgCustData ){
5203 pCustData->cCustData=pFDesc->ctCustData;
5204 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5205 pCData = pCData->next){
5206 pCustData->prgCustData[i].guid=pCData->guid;
5207 VariantCopy(& pCustData->prgCustData[i].varValue,
5208 & pCData->data);
5210 }else{
5211 ERR(" OUT OF MEMORY! \n");
5212 return E_OUTOFMEMORY;
5214 return S_OK;
5216 return TYPE_E_ELEMENTNOTFOUND;
5219 /* ITypeInfo2::GetAllParamCustData
5221 * Gets all custom data items for the Functions
5224 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5225 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5227 ICOM_THIS( ITypeInfoImpl, iface);
5228 TLBCustData *pCData=NULL;
5229 TLBFuncDesc * pFDesc;
5230 int i;
5231 TRACE("(%p) index %d\n", This, indexFunc);
5232 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5233 pFDesc=pFDesc->next)
5235 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5236 pCustData->prgCustData =
5237 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5238 sizeof(CUSTDATAITEM));
5239 if(pCustData->prgCustData ){
5240 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5241 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5242 pCData; i++, pCData = pCData->next){
5243 pCustData->prgCustData[i].guid=pCData->guid;
5244 VariantCopy(& pCustData->prgCustData[i].varValue,
5245 & pCData->data);
5247 }else{
5248 ERR(" OUT OF MEMORY! \n");
5249 return E_OUTOFMEMORY;
5251 return S_OK;
5253 return TYPE_E_ELEMENTNOTFOUND;
5256 /* ITypeInfo2::GetAllVarCustData
5258 * Gets all custom data items for the specified Variable
5261 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5262 UINT index, CUSTDATA *pCustData)
5264 ICOM_THIS( ITypeInfoImpl, iface);
5265 TLBCustData *pCData;
5266 TLBVarDesc * pVDesc;
5267 int i;
5268 TRACE("(%p) index %d\n", This, index);
5269 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5270 pVDesc=pVDesc->next)
5272 if(pVDesc){
5273 pCustData->prgCustData =
5274 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5275 if(pCustData->prgCustData ){
5276 pCustData->cCustData=pVDesc->ctCustData;
5277 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5278 pCData = pCData->next){
5279 pCustData->prgCustData[i].guid=pCData->guid;
5280 VariantCopy(& pCustData->prgCustData[i].varValue,
5281 & pCData->data);
5283 }else{
5284 ERR(" OUT OF MEMORY! \n");
5285 return E_OUTOFMEMORY;
5287 return S_OK;
5289 return TYPE_E_ELEMENTNOTFOUND;
5292 /* ITypeInfo2::GetAllImplCustData
5294 * Gets all custom data items for the specified implementation type
5297 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5298 ITypeInfo2 * iface,
5299 UINT index,
5300 CUSTDATA *pCustData)
5302 ICOM_THIS( ITypeInfoImpl, iface);
5303 TLBCustData *pCData;
5304 TLBImplType * pRDesc;
5305 int i;
5306 TRACE("(%p) index %d\n", This, index);
5307 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5308 pRDesc=pRDesc->next)
5310 if(pRDesc){
5311 pCustData->prgCustData =
5312 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5313 if(pCustData->prgCustData ){
5314 pCustData->cCustData=pRDesc->ctCustData;
5315 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5316 pCData = pCData->next){
5317 pCustData->prgCustData[i].guid=pCData->guid;
5318 VariantCopy(& pCustData->prgCustData[i].varValue,
5319 & pCData->data);
5321 }else{
5322 ERR(" OUT OF MEMORY! \n");
5323 return E_OUTOFMEMORY;
5325 return S_OK;
5327 return TYPE_E_ELEMENTNOTFOUND;
5330 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5332 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5334 ITypeInfo_fnQueryInterface,
5335 ITypeInfo_fnAddRef,
5336 ITypeInfo_fnRelease,
5338 ITypeInfo_fnGetTypeAttr,
5339 ITypeInfo_fnGetTypeComp,
5340 ITypeInfo_fnGetFuncDesc,
5341 ITypeInfo_fnGetVarDesc,
5342 ITypeInfo_fnGetNames,
5343 ITypeInfo_fnGetRefTypeOfImplType,
5344 ITypeInfo_fnGetImplTypeFlags,
5345 ITypeInfo_fnGetIDsOfNames,
5346 ITypeInfo_fnInvoke,
5347 ITypeInfo_fnGetDocumentation,
5348 ITypeInfo_fnGetDllEntry,
5349 ITypeInfo_fnGetRefTypeInfo,
5350 ITypeInfo_fnAddressOfMember,
5351 ITypeInfo_fnCreateInstance,
5352 ITypeInfo_fnGetMops,
5353 ITypeInfo_fnGetContainingTypeLib,
5354 ITypeInfo_fnReleaseTypeAttr,
5355 ITypeInfo_fnReleaseFuncDesc,
5356 ITypeInfo_fnReleaseVarDesc,
5358 ITypeInfo2_fnGetTypeKind,
5359 ITypeInfo2_fnGetTypeFlags,
5360 ITypeInfo2_fnGetFuncIndexOfMemId,
5361 ITypeInfo2_fnGetVarIndexOfMemId,
5362 ITypeInfo2_fnGetCustData,
5363 ITypeInfo2_fnGetFuncCustData,
5364 ITypeInfo2_fnGetParamCustData,
5365 ITypeInfo2_fnGetVarCustData,
5366 ITypeInfo2_fnGetImplTypeCustData,
5367 ITypeInfo2_fnGetDocumentation2,
5368 ITypeInfo2_fnGetAllCustData,
5369 ITypeInfo2_fnGetAllFuncCustData,
5370 ITypeInfo2_fnGetAllParamCustData,
5371 ITypeInfo2_fnGetAllVarCustData,
5372 ITypeInfo2_fnGetAllImplTypeCustData,