Implemented localeconv() with libc function.
[wine.git] / dlls / oleaut32 / typelib.c
blob3c995ea6e8a2f95dcb5d8691d5e991743127d2e6
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 ptiRet->index=count;
1848 /* fill in the typeattr fields */
1849 FIXME("Assign constructor/destructor memid\n");
1851 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1852 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1853 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1854 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1855 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1856 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1857 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1858 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1859 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1860 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1861 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1862 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1863 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1864 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1865 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1866 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1867 MSFT_GetTdesc(pcx, tiBase.datatype1,
1868 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1870 /* FIXME: */
1871 /* IDLDESC idldescType; *//* never saw this one != zero */
1873 /* name, eventually add to a hash table */
1874 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1875 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1876 /* help info */
1877 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1878 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1879 ptiRet->dwHelpContext=tiBase.helpcontext;
1880 /* note: InfoType's Help file and HelpStringDll come from the containing
1881 * library. Further HelpString and Docstring appear to be the same thing :(
1883 /* functions */
1884 if(ptiRet->TypeAttr.cFuncs >0 )
1885 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1886 ptiRet->TypeAttr.cVars,
1887 tiBase.memoffset, & ptiRet->funclist);
1888 /* variables */
1889 if(ptiRet->TypeAttr.cVars >0 )
1890 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1891 ptiRet->TypeAttr.cVars,
1892 tiBase.memoffset, & ptiRet->varlist);
1893 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1894 switch(ptiRet->TypeAttr.typekind)
1896 case TKIND_COCLASS:
1897 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1898 tiBase.datatype1);
1899 break;
1900 case TKIND_DISPATCH:
1901 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1903 if (tiBase.datatype1 != -1)
1905 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1906 ptiRet->impltypelist->hRef = tiBase.datatype1;
1908 else
1909 { /* FIXME: This is a really bad hack to add IDispatch */
1910 char* szStdOle = "stdole2.tlb\0";
1911 int nStdOleLen = strlen(szStdOle);
1912 TLBRefType **ppRef = &ptiRet->reflist;
1914 while(*ppRef) {
1915 if((*ppRef)->reference == -1)
1916 break;
1917 ppRef = &(*ppRef)->next;
1919 if(!*ppRef) {
1920 *ppRef = TLB_Alloc(sizeof(**ppRef));
1921 (*ppRef)->guid = IID_IDispatch;
1922 (*ppRef)->reference = -1;
1923 (*ppRef)->index = TLB_REF_USE_GUID;
1924 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1925 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1926 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1927 nStdOleLen + 1);
1929 MultiByteToWideChar(CP_ACP,
1930 MB_PRECOMPOSED,
1931 szStdOle,
1933 (*ppRef)->pImpTLInfo->name,
1934 SysStringLen((*ppRef)->pImpTLInfo->name));
1936 (*ppRef)->pImpTLInfo->lcid = 0;
1937 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1938 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1941 break;
1942 default:
1943 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1944 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1945 ptiRet->impltypelist->hRef = tiBase.datatype1;
1946 break;
1949 ptiRet->ctCustData=
1950 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1952 TRACE_(typelib)("%s guid: %s kind:%s\n",
1953 debugstr_w(ptiRet->Name),
1954 debugstr_guid(&ptiRet->TypeAttr.guid),
1955 typekind_desc[ptiRet->TypeAttr.typekind]);
1957 return ptiRet;
1960 /****************************************************************************
1961 * TLB_ReadTypeLib
1963 * find the type of the typelib file and map the typelib resource into
1964 * the memory
1966 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1967 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1968 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1970 int ret = TYPE_E_CANTLOADLIBRARY;
1971 DWORD dwSignature = 0;
1972 HANDLE hFile;
1974 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1976 *ppTypeLib = NULL;
1978 /* check the signature of the file */
1979 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1980 if (INVALID_HANDLE_VALUE != hFile)
1982 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1983 if (hMapping)
1985 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1986 if(pBase)
1988 /* retrieve file size */
1989 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1991 /* first try to load as *.tlb */
1992 dwSignature = FromLEDWord(*((DWORD*) pBase));
1993 if ( dwSignature == MSFT_SIGNATURE)
1995 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1997 else if ( dwSignature == SLTG_SIGNATURE)
1999 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2001 UnmapViewOfFile(pBase);
2003 CloseHandle(hMapping);
2005 CloseHandle(hFile);
2008 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2010 /* find the typelibrary resource*/
2011 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2012 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2013 if (hinstDLL)
2015 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2016 "TYPELIB");
2017 if (hrsrc)
2019 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2020 if (hGlobal)
2022 LPVOID pBase = LockResource(hGlobal);
2023 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2025 if (pBase)
2027 /* try to load as incore resource */
2028 dwSignature = FromLEDWord(*((DWORD*) pBase));
2029 if ( dwSignature == MSFT_SIGNATURE)
2031 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2033 else if ( dwSignature == SLTG_SIGNATURE)
2035 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2037 else
2039 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2042 FreeResource( hGlobal );
2045 FreeLibrary(hinstDLL);
2049 if(*ppTypeLib)
2050 ret = S_OK;
2051 else
2052 ERR("Loading of typelib %s failed with error %ld\n",
2053 debugstr_w(pszFileName), GetLastError());
2055 return ret;
2058 /*================== ITypeLib(2) Methods ===================================*/
2060 /****************************************************************************
2061 * ITypeLib2_Constructor_MSFT
2063 * loading an MSFT typelib from an in-memory image
2065 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2067 TLBContext cx;
2068 long lPSegDir;
2069 MSFT_Header tlbHeader;
2070 MSFT_SegDir tlbSegDir;
2071 ITypeLibImpl * pTypeLibImpl;
2073 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2075 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2076 if (!pTypeLibImpl) return NULL;
2078 pTypeLibImpl->lpVtbl = &tlbvt;
2079 pTypeLibImpl->ref = 1;
2081 /* get pointer to beginning of typelib data */
2082 cx.pos = 0;
2083 cx.oStart=0;
2084 cx.mapping = pLib;
2085 cx.pLibInfo = pTypeLibImpl;
2086 cx.length = dwTLBLength;
2088 /* read header */
2089 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2090 TRACE("header:\n");
2091 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2092 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2093 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2094 return NULL;
2096 /* there is a small amount of information here until the next important
2097 * part:
2098 * the segment directory . Try to calculate the amount of data */
2099 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2101 /* now read the segment directory */
2102 TRACE("read segment directory (at %ld)\n",lPSegDir);
2103 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2104 cx.pTblDir = &tlbSegDir;
2106 /* just check two entries */
2107 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2109 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2110 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2111 return NULL;
2114 /* now fill our internal data */
2115 /* TLIBATTR fields */
2116 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2118 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2119 /* Windows seems to have zero here, is this correct? */
2120 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2121 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2122 else
2123 pTypeLibImpl->LibAttr.lcid = 0;
2125 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2126 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2127 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2128 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2130 /* name, eventually add to a hash table */
2131 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2133 /* help info */
2134 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2135 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2137 if( tlbHeader.varflags & HELPDLLFLAG)
2139 int offset;
2140 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2141 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2144 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2146 /* custom data */
2147 if(tlbHeader.CustomDataOffset >= 0)
2149 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2152 /* fill in typedescriptions */
2153 if(tlbSegDir.pTypdescTab.length > 0)
2155 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2156 INT16 td[4];
2157 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2158 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2159 for(i=0; i<cTD; )
2161 /* FIXME: add several sanity checks here */
2162 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2163 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2165 /* FIXME: check safearray */
2166 if(td[3] < 0)
2167 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2168 else
2169 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2171 else if(td[0] == VT_CARRAY)
2173 /* array descr table here */
2174 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2176 else if(td[0] == VT_USERDEFINED)
2178 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2180 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2183 /* second time around to fill the array subscript info */
2184 for(i=0;i<cTD;i++)
2186 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2187 if(tlbSegDir.pArrayDescriptions.offset>0)
2189 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2190 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2192 if(td[1]<0)
2193 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2194 else
2195 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2197 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2199 for(j = 0; j<td[2]; j++)
2201 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2202 sizeof(INT), &cx, DO_NOT_SEEK);
2203 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2204 sizeof(INT), &cx, DO_NOT_SEEK);
2207 else
2209 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2210 ERR("didn't find array description data\n");
2215 /* imported type libs */
2216 if(tlbSegDir.pImpFiles.offset>0)
2218 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2219 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2220 UINT16 size;
2222 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2224 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2225 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2226 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2228 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2229 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2230 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2231 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2233 size >>= 2;
2234 (*ppImpLib)->name = TLB_Alloc(size+1);
2235 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2236 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2237 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2239 ppImpLib = &(*ppImpLib)->next;
2243 /* type info's */
2244 if(tlbHeader.nrtypeinfos >= 0 )
2246 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2247 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2248 int i;
2250 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2252 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2254 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2255 ppTI = &((*ppTI)->next);
2256 (pTypeLibImpl->TypeInfoCount)++;
2260 TRACE("(%p)\n", pTypeLibImpl);
2261 return (ITypeLib2*) pTypeLibImpl;
2265 static BSTR TLB_MultiByteToBSTR(char *ptr)
2267 DWORD len;
2268 WCHAR *nameW;
2269 BSTR ret;
2271 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2272 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2273 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2274 ret = SysAllocString(nameW);
2275 HeapFree(GetProcessHeap(), 0, nameW);
2276 return ret;
2279 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2281 char b[3];
2282 int i;
2283 short s;
2285 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2286 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2287 return FALSE;
2290 guid->Data4[0] = s >> 8;
2291 guid->Data4[1] = s & 0xff;
2293 b[2] = '\0';
2294 for(i = 0; i < 6; i++) {
2295 memcpy(b, str + 24 + 2 * i, 2);
2296 guid->Data4[i + 2] = strtol(b, NULL, 16);
2298 return TRUE;
2301 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2303 WORD bytelen;
2304 DWORD len;
2305 WCHAR *nameW;
2307 *pBstr = NULL;
2308 bytelen = *(WORD*)ptr;
2309 if(bytelen == 0xffff) return 2;
2310 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2311 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2312 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2313 *pBstr = SysAllocStringLen(nameW, len);
2314 HeapFree(GetProcessHeap(), 0, nameW);
2315 return bytelen + 2;
2318 static WORD SLTG_ReadStringA(char *ptr, char **str)
2320 WORD bytelen;
2322 *str = NULL;
2323 bytelen = *(WORD*)ptr;
2324 if(bytelen == 0xffff) return 2;
2325 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2326 memcpy(*str, ptr + 2, bytelen);
2327 (*str)[bytelen] = '\0';
2328 return bytelen + 2;
2331 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2333 char *ptr = pLibBlk;
2334 WORD w;
2336 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2337 FIXME("libblk magic = %04x\n", w);
2338 return 0;
2341 ptr += 6;
2342 if((w = *(WORD*)ptr) != 0xffff) {
2343 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2344 ptr += w;
2346 ptr += 2;
2348 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2350 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2352 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2353 ptr += 4;
2355 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2356 ptr += 2;
2358 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2359 ptr += 2;
2361 ptr += 4; /* skip res12 */
2363 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2364 ptr += 2;
2366 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2367 ptr += 2;
2369 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2370 ptr += 2;
2372 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2373 ptr += sizeof(GUID);
2375 return ptr - (char*)pLibBlk;
2378 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2380 BOOL done = FALSE;
2381 TYPEDESC *pTD = &pElem->tdesc;
2383 /* Handle [in/out] first */
2384 if((*pType & 0xc000) == 0xc000)
2385 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2386 else if(*pType & 0x8000)
2387 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2388 else if(*pType & 0x4000)
2389 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2390 else
2391 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2393 if(*pType & 0x2000)
2394 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2396 if(*pType & 0x80)
2397 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2399 while(!done) {
2400 if((*pType & 0xe00) == 0xe00) {
2401 pTD->vt = VT_PTR;
2402 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2403 sizeof(TYPEDESC));
2404 pTD = pTD->u.lptdesc;
2406 switch(*pType & 0x7f) {
2407 case VT_PTR:
2408 pTD->vt = VT_PTR;
2409 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2410 sizeof(TYPEDESC));
2411 pTD = pTD->u.lptdesc;
2412 break;
2414 case VT_USERDEFINED:
2415 pTD->vt = VT_USERDEFINED;
2416 pTD->u.hreftype = *(++pType) / 4;
2417 done = TRUE;
2418 break;
2420 case VT_CARRAY:
2422 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2423 array */
2425 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2427 pTD->vt = VT_CARRAY;
2428 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2429 sizeof(ARRAYDESC) +
2430 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2431 pTD->u.lpadesc->cDims = pSA->cDims;
2432 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2433 pSA->cDims * sizeof(SAFEARRAYBOUND));
2435 pTD = &pTD->u.lpadesc->tdescElem;
2436 break;
2439 case VT_SAFEARRAY:
2441 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2442 useful? */
2444 pType++;
2445 pTD->vt = VT_SAFEARRAY;
2446 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2447 sizeof(TYPEDESC));
2448 pTD = pTD->u.lptdesc;
2449 break;
2451 default:
2452 pTD->vt = *pType & 0x7f;
2453 done = TRUE;
2454 break;
2456 pType++;
2458 return pType;
2462 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2463 char *pNameTable)
2465 int ref;
2466 char *name;
2467 TLBRefType **ppRefType;
2469 if(pRef->magic != SLTG_REF_MAGIC) {
2470 FIXME("Ref magic = %x\n", pRef->magic);
2471 return;
2473 name = ( (char*)(&pRef->names) + pRef->number);
2475 ppRefType = &pTI->reflist;
2476 for(ref = 0; ref < pRef->number >> 3; ref++) {
2477 char *refname;
2478 unsigned int lib_offs, type_num;
2480 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2481 sizeof(**ppRefType));
2483 name += SLTG_ReadStringA(name, &refname);
2484 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2485 FIXME("Can't sscanf ref\n");
2486 if(lib_offs != 0xffff) {
2487 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2489 while(*import) {
2490 if((*import)->offset == lib_offs)
2491 break;
2492 import = &(*import)->next;
2494 if(!*import) {
2495 char fname[MAX_PATH+1];
2496 int len;
2498 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2499 sizeof(**import));
2500 (*import)->offset = lib_offs;
2501 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2502 &(*import)->guid);
2503 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2504 &(*import)->wVersionMajor,
2505 &(*import)->wVersionMinor,
2506 &(*import)->lcid, fname) != 4) {
2507 FIXME("can't sscanf ref %s\n",
2508 pNameTable + lib_offs + 40);
2510 len = strlen(fname);
2511 if(fname[len-1] != '#')
2512 FIXME("fname = %s\n", fname);
2513 fname[len-1] = '\0';
2514 (*import)->name = TLB_MultiByteToBSTR(fname);
2516 (*ppRefType)->pImpTLInfo = *import;
2517 } else { /* internal ref */
2518 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2520 (*ppRefType)->reference = ref;
2521 (*ppRefType)->index = type_num;
2523 HeapFree(GetProcessHeap(), 0, refname);
2524 ppRefType = &(*ppRefType)->next;
2526 if((BYTE)*name != SLTG_REF_MAGIC)
2527 FIXME("End of ref block magic = %x\n", *name);
2528 dump_TLBRefType(pTI->reflist);
2531 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2532 BOOL OneOnly)
2534 SLTG_ImplInfo *info;
2535 TLBImplType **ppImplType = &pTI->impltypelist;
2536 /* I don't really get this structure, usually it's 0x16 bytes
2537 long, but iuser.tlb contains some that are 0x18 bytes long.
2538 That's ok because we can use the next ptr to jump to the next
2539 one. But how do we know the length of the last one? The WORD
2540 at offs 0x8 might be the clue. For now I'm just assuming that
2541 the last one is the regular 0x16 bytes. */
2543 info = (SLTG_ImplInfo*)pBlk;
2544 while(1) {
2545 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2546 sizeof(**ppImplType));
2547 (*ppImplType)->hRef = info->ref;
2548 (*ppImplType)->implflags = info->impltypeflags;
2549 pTI->TypeAttr.cImplTypes++;
2550 ppImplType = &(*ppImplType)->next;
2552 if(info->next == 0xffff)
2553 break;
2554 if(OneOnly)
2555 FIXME("Interface inheriting more than one interface\n");
2556 info = (SLTG_ImplInfo*)(pBlk + info->next);
2558 info++; /* see comment at top of function */
2559 return (char*)info;
2562 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2563 char *pNameTable)
2565 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2566 SLTG_MemberHeader *pMemHeader;
2567 char *pFirstItem, *pNextItem;
2569 if(pTIHeader->href_table != 0xffffffff) {
2570 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2571 pNameTable);
2575 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2577 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2579 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2580 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2583 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2587 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2588 char *pNameTable)
2590 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2591 SLTG_MemberHeader *pMemHeader;
2592 SLTG_Function *pFunc;
2593 char *pFirstItem, *pNextItem;
2594 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2595 int num = 0;
2597 if(pTIHeader->href_table != 0xffffffff) {
2598 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2599 pNameTable);
2602 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2604 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2606 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2607 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2610 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2611 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2613 int param;
2614 WORD *pType, *pArg;
2616 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2617 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2618 FIXME("func magic = %02x\n", pFunc->magic);
2619 return NULL;
2621 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2622 sizeof(**ppFuncDesc));
2623 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2625 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2626 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2627 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2628 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2629 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2630 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2632 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2633 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2635 if(pFunc->retnextopt & 0x80)
2636 pType = &pFunc->rettype;
2637 else
2638 pType = (WORD*)(pFirstItem + pFunc->rettype);
2641 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2643 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2644 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2645 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2646 (*ppFuncDesc)->pParamDesc =
2647 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2648 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2650 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2652 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2653 char *paramName = pNameTable + *pArg;
2654 BOOL HaveOffs;
2655 /* If arg type follows then paramName points to the 2nd
2656 letter of the name, else the next WORD is an offset to
2657 the arg type and paramName points to the first letter.
2658 So let's take one char off paramName and see if we're
2659 pointing at an alpha-numeric char. However if *pArg is
2660 0xffff or 0xfffe then the param has no name, the former
2661 meaning that the next WORD is the type, the latter
2662 meaning the the next WORD is an offset to the type. */
2664 HaveOffs = FALSE;
2665 if(*pArg == 0xffff)
2666 paramName = NULL;
2667 else if(*pArg == 0xfffe) {
2668 paramName = NULL;
2669 HaveOffs = TRUE;
2671 else if(!isalnum(*(paramName-1)))
2672 HaveOffs = TRUE;
2674 pArg++;
2676 if(HaveOffs) { /* the next word is an offset to type */
2677 pType = (WORD*)(pFirstItem + *pArg);
2678 SLTG_DoType(pType, pFirstItem,
2679 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2680 pArg++;
2681 } else {
2682 if(paramName)
2683 paramName--;
2684 pArg = SLTG_DoType(pArg, pFirstItem,
2685 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2688 /* Are we an optional param ? */
2689 if((*ppFuncDesc)->funcdesc.cParams - param <=
2690 (*ppFuncDesc)->funcdesc.cParamsOpt)
2691 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2693 if(paramName) {
2694 (*ppFuncDesc)->pParamDesc[param].Name =
2695 TLB_MultiByteToBSTR(paramName);
2699 ppFuncDesc = &((*ppFuncDesc)->next);
2700 if(pFunc->next == 0xffff) break;
2702 pTI->TypeAttr.cFuncs = num;
2703 dump_TLBFuncDesc(pTI->funclist);
2704 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2707 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2708 char *pNameTable)
2710 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2711 SLTG_MemberHeader *pMemHeader;
2712 SLTG_RecordItem *pItem;
2713 char *pFirstItem;
2714 TLBVarDesc **ppVarDesc = &pTI->varlist;
2715 int num = 0;
2716 WORD *pType;
2717 char buf[300];
2719 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2721 pFirstItem = (char*)(pMemHeader + 1);
2722 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2723 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2724 if(pItem->magic != SLTG_RECORD_MAGIC) {
2725 FIXME("record magic = %02x\n", pItem->magic);
2726 return NULL;
2728 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2729 sizeof(**ppVarDesc));
2730 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2731 (*ppVarDesc)->vardesc.memid = pItem->memid;
2732 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2733 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2735 if(pItem->typepos == 0x02)
2736 pType = &pItem->type;
2737 else if(pItem->typepos == 0x00)
2738 pType = (WORD*)(pFirstItem + pItem->type);
2739 else {
2740 FIXME("typepos = %02x\n", pItem->typepos);
2741 break;
2744 SLTG_DoType(pType, pFirstItem,
2745 &(*ppVarDesc)->vardesc.elemdescVar);
2747 /* FIXME("helpcontext, helpstring\n"); */
2749 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2751 ppVarDesc = &((*ppVarDesc)->next);
2752 if(pItem->next == 0xffff) break;
2754 pTI->TypeAttr.cVars = num;
2755 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2758 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2759 char *pNameTable)
2761 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2762 SLTG_MemberHeader *pMemHeader;
2763 SLTG_AliasItem *pItem;
2764 int i, mustbelast;
2766 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2767 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2769 mustbelast = 0;
2770 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2771 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2772 if (pItem->vt == 0xffff) {
2773 if (i<(pMemHeader->cbExtra/4-1))
2774 FIXME("Endmarker too early in process alias data!\n");
2775 break;
2777 if (mustbelast) {
2778 FIXME("Chain extends over last entry?\n");
2779 break;
2781 if (pItem->vt == VT_USERDEFINED) {
2782 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2783 /* guessing here ... */
2784 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2785 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2786 mustbelast = 1;
2787 } else {
2788 FIXME("alias %d: 0x%x\n",i,pItem->vt);
2789 FIXME("alias %d: 0x%x\n",i,pItem->res02);
2791 pItem++;
2793 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2796 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
2797 char *pNameTable)
2799 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2800 SLTG_MemberHeader *pMemHeader;
2801 SLTG_AliasItem *pItem;
2803 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2804 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2805 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
2806 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
2807 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2810 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2811 char *pNameTable)
2813 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2814 SLTG_MemberHeader *pMemHeader;
2815 SLTG_EnumItem *pItem;
2816 char *pFirstItem;
2817 TLBVarDesc **ppVarDesc = &pTI->varlist;
2818 int num = 0;
2820 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2822 pFirstItem = (char*)(pMemHeader + 1);
2823 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2824 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2825 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2826 FIXME("enumitem magic = %04x\n", pItem->magic);
2827 return NULL;
2829 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2830 sizeof(**ppVarDesc));
2831 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2832 (*ppVarDesc)->vardesc.memid = pItem->memid;
2833 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2834 sizeof(VARIANT));
2835 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2836 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2837 *(INT*)(pItem->value + pFirstItem);
2838 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2839 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2840 /* FIXME("helpcontext, helpstring\n"); */
2842 ppVarDesc = &((*ppVarDesc)->next);
2843 if(pItem->next == 0xffff) break;
2845 pTI->TypeAttr.cVars = num;
2846 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2849 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2850 managable copy of it into this */
2851 typedef struct {
2852 WORD small_no;
2853 char *index_name;
2854 char *other_name;
2855 WORD res1a;
2856 WORD name_offs;
2857 WORD more_bytes;
2858 char *extra;
2859 WORD res20;
2860 DWORD helpcontext;
2861 WORD res26;
2862 GUID uuid;
2863 } SLTG_InternalOtherTypeInfo;
2865 /****************************************************************************
2866 * ITypeLib2_Constructor_SLTG
2868 * loading a SLTG typelib from an in-memory image
2870 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2872 ITypeLibImpl *pTypeLibImpl;
2873 SLTG_Header *pHeader;
2874 SLTG_BlkEntry *pBlkEntry;
2875 SLTG_Magic *pMagic;
2876 SLTG_Index *pIndex;
2877 SLTG_Pad9 *pPad9;
2878 LPVOID pBlk, pFirstBlk;
2879 SLTG_LibBlk *pLibBlk;
2880 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2881 char *pAfterOTIBlks = NULL;
2882 char *pNameTable, *ptr;
2883 int i;
2884 DWORD len, order;
2885 ITypeInfoImpl **ppTypeInfoImpl;
2887 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2889 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2890 if (!pTypeLibImpl) return NULL;
2892 pTypeLibImpl->lpVtbl = &tlbvt;
2893 pTypeLibImpl->ref = 1;
2895 pHeader = pLib;
2897 TRACE("header:\n");
2898 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2899 pHeader->nrOfFileBlks );
2900 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
2901 FIXME("Header type magic 0x%08lx not supported.\n",
2902 pHeader->SLTG_magic);
2903 return NULL;
2906 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2907 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2909 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2910 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2912 /* Next we have a magic block */
2913 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2915 /* Let's see if we're still in sync */
2916 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2917 sizeof(SLTG_COMPOBJ_MAGIC))) {
2918 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2919 return NULL;
2921 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2922 sizeof(SLTG_DIR_MAGIC))) {
2923 FIXME("dir magic = %s\n", pMagic->dir_magic);
2924 return NULL;
2927 pIndex = (SLTG_Index*)(pMagic+1);
2929 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2931 pFirstBlk = (LPVOID)(pPad9 + 1);
2933 /* We'll set up a ptr to the main library block, which is the last one. */
2935 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2936 pBlkEntry[order].next != 0;
2937 order = pBlkEntry[order].next - 1, i++) {
2938 pBlk = (char*)pBlk + pBlkEntry[order].len;
2940 pLibBlk = pBlk;
2942 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2944 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2945 interspersed */
2947 len += 0x40;
2949 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2951 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2952 sizeof(*pOtherTypeInfoBlks) *
2953 pTypeLibImpl->TypeInfoCount);
2956 ptr = (char*)pLibBlk + len;
2958 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2959 WORD w, extra;
2960 len = 0;
2962 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2964 w = *(WORD*)(ptr + 2);
2965 if(w != 0xffff) {
2966 len += w;
2967 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2968 w+1);
2969 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2970 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2972 w = *(WORD*)(ptr + 4 + len);
2973 if(w != 0xffff) {
2974 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2975 len += w;
2976 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2977 w+1);
2978 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2979 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2981 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2982 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2983 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2984 if(extra) {
2985 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2986 extra);
2987 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2988 len += extra;
2990 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2991 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2992 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2993 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2994 len += sizeof(SLTG_OtherTypeInfo);
2995 ptr += len;
2998 pAfterOTIBlks = ptr;
3000 /* Skip this WORD and get the next DWORD */
3001 len = *(DWORD*)(pAfterOTIBlks + 2);
3003 /* Now add this to pLibBLk look at what we're pointing at and
3004 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3005 dust and we should be pointing at the beginning of the name
3006 table */
3008 pNameTable = (char*)pLibBlk + len;
3010 switch(*(WORD*)pNameTable) {
3011 case 0xffff:
3012 break;
3013 case 0x0200:
3014 pNameTable += 0x20;
3015 break;
3016 default:
3017 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3018 break;
3021 pNameTable += 0x216;
3023 pNameTable += 2;
3025 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3027 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3030 /* Hopefully we now have enough ptrs set up to actually read in
3031 some TypeInfos. It's not clear which order to do them in, so
3032 I'll just follow the links along the BlkEntry chain and read
3033 them in in the order in which they're in the file */
3035 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3037 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3038 pBlkEntry[order].next != 0;
3039 order = pBlkEntry[order].next - 1, i++) {
3041 SLTG_TypeInfoHeader *pTIHeader;
3042 SLTG_TypeInfoTail *pTITail;
3044 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3045 pOtherTypeInfoBlks[i].index_name)) {
3046 FIXME("Index strings don't match\n");
3047 return NULL;
3050 pTIHeader = pBlk;
3051 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3052 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3053 return NULL;
3055 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3056 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3057 (*ppTypeInfoImpl)->index = i;
3058 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3059 pOtherTypeInfoBlks[i].name_offs +
3060 pNameTable);
3061 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3062 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3063 sizeof(GUID));
3064 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3065 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3066 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3067 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3068 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3070 if((pTIHeader->typeflags1 & 7) != 2)
3071 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3072 if(pTIHeader->typeflags3 != 2)
3073 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3075 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3076 debugstr_w((*ppTypeInfoImpl)->Name),
3077 typekind_desc[pTIHeader->typekind],
3078 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3079 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3081 switch(pTIHeader->typekind) {
3082 case TKIND_ENUM:
3083 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3084 break;
3086 case TKIND_RECORD:
3087 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3088 break;
3090 case TKIND_INTERFACE:
3091 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3092 break;
3094 case TKIND_COCLASS:
3095 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3096 break;
3098 case TKIND_ALIAS:
3099 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3100 if (pTITail->tdescalias_vt)
3101 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3102 break;
3104 case TKIND_DISPATCH:
3105 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3106 break;
3108 default:
3109 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3110 pTITail = NULL;
3111 break;
3115 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3116 but we've already set those */
3117 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3118 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3119 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3121 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3122 X(06);
3123 X(08);
3124 X(0a);
3125 X(0c);
3126 X(0e);
3127 X(10);
3128 X(12);
3129 X(16);
3130 X(18);
3131 X(1a);
3132 X(1c);
3133 X(1e);
3134 X(24);
3135 X(26);
3136 X(2a);
3137 X(2c);
3138 X(2e);
3139 X(30);
3140 X(32);
3141 X(34);
3143 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3144 pBlk = (char*)pBlk + pBlkEntry[order].len;
3147 if(i != pTypeLibImpl->TypeInfoCount) {
3148 FIXME("Somehow processed %d TypeInfos\n", i);
3149 return NULL;
3152 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3153 return (ITypeLib2*)pTypeLibImpl;
3156 /* ITypeLib::QueryInterface
3158 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3159 ITypeLib2 * iface,
3160 REFIID riid,
3161 VOID **ppvObject)
3163 ICOM_THIS( ITypeLibImpl, iface);
3165 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3167 *ppvObject=NULL;
3168 if(IsEqualIID(riid, &IID_IUnknown) ||
3169 IsEqualIID(riid,&IID_ITypeLib)||
3170 IsEqualIID(riid,&IID_ITypeLib2))
3172 *ppvObject = This;
3175 if(*ppvObject)
3177 ITypeLib2_AddRef(iface);
3178 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3179 return S_OK;
3181 TRACE("-- Interface: E_NOINTERFACE\n");
3182 return E_NOINTERFACE;
3185 /* ITypeLib::AddRef
3187 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3189 ICOM_THIS( ITypeLibImpl, iface);
3191 TRACE("(%p)->ref is %u\n",This, This->ref);
3193 return ++(This->ref);
3196 /* ITypeLib::Release
3198 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3200 ICOM_THIS( ITypeLibImpl, iface);
3202 --(This->ref);
3204 TRACE("(%p)->(%u)\n",This, This->ref);
3206 if (!This->ref)
3208 /* FIXME destroy child objects */
3210 TRACE(" destroying ITypeLib(%p)\n",This);
3212 if (This->Name)
3214 SysFreeString(This->Name);
3215 This->Name = NULL;
3218 if (This->DocString)
3220 SysFreeString(This->DocString);
3221 This->DocString = NULL;
3224 if (This->HelpFile)
3226 SysFreeString(This->HelpFile);
3227 This->HelpFile = NULL;
3230 if (This->HelpStringDll)
3232 SysFreeString(This->HelpStringDll);
3233 This->HelpStringDll = NULL;
3236 if (This->pTypeInfo) /* can be NULL */
3237 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3238 HeapFree(GetProcessHeap(),0,This);
3239 return 0;
3242 return This->ref;
3245 /* ITypeLib::GetTypeInfoCount
3247 * Returns the number of type descriptions in the type library
3249 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3251 ICOM_THIS( ITypeLibImpl, iface);
3252 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3253 return This->TypeInfoCount;
3256 /* ITypeLib::GetTypeInfo
3258 * retrieves the specified type description in the library.
3260 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3261 ITypeLib2 *iface,
3262 UINT index,
3263 ITypeInfo **ppTInfo)
3265 int i;
3267 ICOM_THIS( ITypeLibImpl, iface);
3268 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3270 TRACE("(%p)->(index=%d) \n", This, index);
3272 if (!ppTInfo) return E_INVALIDARG;
3274 /* search element n in list */
3275 for(i=0; i < index; i++)
3277 pTypeInfo = pTypeInfo->next;
3278 if (!pTypeInfo)
3280 TRACE("-- element not found\n");
3281 return TYPE_E_ELEMENTNOTFOUND;
3285 *ppTInfo = (ITypeInfo *) pTypeInfo;
3287 ITypeInfo_AddRef(*ppTInfo);
3288 TRACE("-- found (%p)\n",*ppTInfo);
3289 return S_OK;
3293 /* ITypeLibs::GetTypeInfoType
3295 * Retrieves the type of a type description.
3297 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3298 ITypeLib2 *iface,
3299 UINT index,
3300 TYPEKIND *pTKind)
3302 ICOM_THIS( ITypeLibImpl, iface);
3303 int i;
3304 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3306 TRACE("(%p) index %d \n",This, index);
3308 if(!pTKind) return E_INVALIDARG;
3310 /* search element n in list */
3311 for(i=0; i < index; i++)
3313 if(!pTInfo)
3315 TRACE("-- element not found\n");
3316 return TYPE_E_ELEMENTNOTFOUND;
3318 pTInfo = pTInfo->next;
3321 *pTKind = pTInfo->TypeAttr.typekind;
3322 TRACE("-- found Type (%d)\n", *pTKind);
3323 return S_OK;
3326 /* ITypeLib::GetTypeInfoOfGuid
3328 * Retrieves the type description that corresponds to the specified GUID.
3331 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3332 ITypeLib2 *iface,
3333 REFGUID guid,
3334 ITypeInfo **ppTInfo)
3336 ICOM_THIS( ITypeLibImpl, iface);
3337 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3339 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3341 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3343 /* search linked list for guid */
3344 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3346 pTypeInfo = pTypeInfo->next;
3348 if (!pTypeInfo)
3350 /* end of list reached */
3351 TRACE("-- element not found\n");
3352 return TYPE_E_ELEMENTNOTFOUND;
3356 TRACE("-- found (%p, %s)\n",
3357 pTypeInfo,
3358 debugstr_w(pTypeInfo->Name));
3360 *ppTInfo = (ITypeInfo*)pTypeInfo;
3361 ITypeInfo_AddRef(*ppTInfo);
3362 return S_OK;
3365 /* ITypeLib::GetLibAttr
3367 * Retrieves the structure that contains the library's attributes.
3370 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3371 ITypeLib2 *iface,
3372 LPTLIBATTR *ppTLibAttr)
3374 ICOM_THIS( ITypeLibImpl, iface);
3375 TRACE("(%p)\n",This);
3376 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3377 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3378 return S_OK;
3381 /* ITypeLib::GetTypeComp
3383 * Enables a client compiler to bind to a library's types, variables,
3384 * constants, and global functions.
3387 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3388 ITypeLib2 *iface,
3389 ITypeComp **ppTComp)
3391 ICOM_THIS( ITypeLibImpl, iface);
3392 FIXME("(%p): stub!\n",This);
3393 return E_NOTIMPL;
3396 /* ITypeLib::GetDocumentation
3398 * Retrieves the library's documentation string, the complete Help file name
3399 * and path, and the context identifier for the library Help topic in the Help
3400 * file.
3402 * On a successful return all non-null BSTR pointers will have been set,
3403 * possibly to NULL.
3405 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3406 ITypeLib2 *iface,
3407 INT index,
3408 BSTR *pBstrName,
3409 BSTR *pBstrDocString,
3410 DWORD *pdwHelpContext,
3411 BSTR *pBstrHelpFile)
3413 ICOM_THIS( ITypeLibImpl, iface);
3415 HRESULT result = E_INVALIDARG;
3417 ITypeInfo *pTInfo;
3420 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3421 This, index,
3422 pBstrName, pBstrDocString,
3423 pdwHelpContext, pBstrHelpFile);
3425 if(index<0)
3427 /* documentation for the typelib */
3428 if(pBstrName)
3430 if (This->Name)
3431 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3432 else
3433 *pBstrName = NULL;
3435 if(pBstrDocString)
3437 if (This->DocString)
3438 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3439 else if (This->Name)
3440 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3441 else
3442 *pBstrDocString = NULL;
3444 if(pdwHelpContext)
3446 *pdwHelpContext = This->dwHelpContext;
3448 if(pBstrHelpFile)
3450 if (This->HelpFile)
3451 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3452 else
3453 *pBstrHelpFile = NULL;
3456 result = S_OK;
3458 else
3460 /* for a typeinfo */
3461 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3463 if(SUCCEEDED(result))
3465 result = ITypeInfo_GetDocumentation(pTInfo,
3466 MEMBERID_NIL,
3467 pBstrName,
3468 pBstrDocString,
3469 pdwHelpContext, pBstrHelpFile);
3471 ITypeInfo_Release(pTInfo);
3474 return result;
3475 memerr3:
3476 if (pBstrDocString) SysFreeString (*pBstrDocString);
3477 memerr2:
3478 if (pBstrName) SysFreeString (*pBstrName);
3479 memerr1:
3480 return STG_E_INSUFFICIENTMEMORY;
3483 /* ITypeLib::IsName
3485 * Indicates whether a passed-in string contains the name of a type or member
3486 * described in the library.
3489 static HRESULT WINAPI ITypeLib2_fnIsName(
3490 ITypeLib2 *iface,
3491 LPOLESTR szNameBuf,
3492 ULONG lHashVal,
3493 BOOL *pfName)
3495 ICOM_THIS( ITypeLibImpl, iface);
3496 ITypeInfoImpl *pTInfo;
3497 TLBFuncDesc *pFInfo;
3498 TLBVarDesc *pVInfo;
3499 int i;
3500 UINT nNameBufLen = SysStringLen(szNameBuf);
3502 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3503 pfName);
3505 *pfName=TRUE;
3506 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3507 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3508 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3509 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3510 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3511 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3512 goto ITypeLib2_fnIsName_exit;
3514 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3515 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3518 *pfName=FALSE;
3520 ITypeLib2_fnIsName_exit:
3521 TRACE("(%p)slow! search for %s: %s found!\n", This,
3522 debugstr_w(szNameBuf), *pfName?"NOT":"");
3524 return S_OK;
3527 /* ITypeLib::FindName
3529 * Finds occurrences of a type description in a type library. This may be used
3530 * to quickly verify that a name exists in a type library.
3533 static HRESULT WINAPI ITypeLib2_fnFindName(
3534 ITypeLib2 *iface,
3535 LPOLESTR szNameBuf,
3536 ULONG lHashVal,
3537 ITypeInfo **ppTInfo,
3538 MEMBERID *rgMemId,
3539 UINT16 *pcFound)
3541 ICOM_THIS( ITypeLibImpl, iface);
3542 ITypeInfoImpl *pTInfo;
3543 TLBFuncDesc *pFInfo;
3544 TLBVarDesc *pVInfo;
3545 int i,j = 0;
3547 UINT nNameBufLen = SysStringLen(szNameBuf);
3549 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3550 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3551 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3552 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3553 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3554 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3555 goto ITypeLib2_fnFindName_exit;
3557 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3558 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3559 continue;
3560 ITypeLib2_fnFindName_exit:
3561 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3562 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3563 j++;
3565 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3566 This, *pcFound, debugstr_w(szNameBuf), j);
3568 *pcFound=j;
3570 return S_OK;
3573 /* ITypeLib::ReleaseTLibAttr
3575 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3578 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3579 ITypeLib2 *iface,
3580 TLIBATTR *pTLibAttr)
3582 ICOM_THIS( ITypeLibImpl, iface);
3583 TRACE("freeing (%p)\n",This);
3584 HeapFree(GetProcessHeap(),0,pTLibAttr);
3588 /* ITypeLib2::GetCustData
3590 * gets the custom data
3592 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3593 ITypeLib2 * iface,
3594 REFGUID guid,
3595 VARIANT *pVarVal)
3597 ICOM_THIS( ITypeLibImpl, iface);
3598 TLBCustData *pCData;
3600 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3602 if( IsEqualIID(guid, &pCData->guid)) break;
3605 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3607 if(pCData)
3609 VariantInit( pVarVal);
3610 VariantCopy( pVarVal, &pCData->data);
3611 return S_OK;
3613 return E_INVALIDARG; /* FIXME: correct? */
3616 /* ITypeLib2::GetLibStatistics
3618 * Returns statistics about a type library that are required for efficient
3619 * sizing of hash tables.
3622 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3623 ITypeLib2 * iface,
3624 ULONG *pcUniqueNames,
3625 ULONG *pcchUniqueNames)
3627 ICOM_THIS( ITypeLibImpl, iface);
3629 FIXME("(%p): stub!\n", This);
3631 if(pcUniqueNames) *pcUniqueNames=1;
3632 if(pcchUniqueNames) *pcchUniqueNames=1;
3633 return S_OK;
3636 /* ITypeLib2::GetDocumentation2
3638 * Retrieves the library's documentation string, the complete Help file name
3639 * and path, the localization context to use, and the context ID for the
3640 * library Help topic in the Help file.
3643 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3644 ITypeLib2 * iface,
3645 INT index,
3646 LCID lcid,
3647 BSTR *pbstrHelpString,
3648 DWORD *pdwHelpStringContext,
3649 BSTR *pbstrHelpStringDll)
3651 ICOM_THIS( ITypeLibImpl, iface);
3652 HRESULT result;
3653 ITypeInfo *pTInfo;
3655 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3657 /* the help string should be obtained from the helpstringdll,
3658 * using the _DLLGetDocumentation function, based on the supplied
3659 * lcid. Nice to do sometime...
3661 if(index<0)
3663 /* documentation for the typelib */
3664 if(pbstrHelpString)
3665 *pbstrHelpString=SysAllocString(This->DocString);
3666 if(pdwHelpStringContext)
3667 *pdwHelpStringContext=This->dwHelpContext;
3668 if(pbstrHelpStringDll)
3669 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3671 result = S_OK;
3673 else
3675 /* for a typeinfo */
3676 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3678 if(SUCCEEDED(result))
3680 ITypeInfo2 * pTInfo2;
3681 result = ITypeInfo_QueryInterface(pTInfo,
3682 &IID_ITypeInfo2,
3683 (LPVOID*) &pTInfo2);
3685 if(SUCCEEDED(result))
3687 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3688 MEMBERID_NIL,
3689 lcid,
3690 pbstrHelpString,
3691 pdwHelpStringContext,
3692 pbstrHelpStringDll);
3694 ITypeInfo2_Release(pTInfo2);
3697 ITypeInfo_Release(pTInfo);
3700 return result;
3703 /* ITypeLib2::GetAllCustData
3705 * Gets all custom data items for the library.
3708 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3709 ITypeLib2 * iface,
3710 CUSTDATA *pCustData)
3712 ICOM_THIS( ITypeLibImpl, iface);
3713 TLBCustData *pCData;
3714 int i;
3715 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3716 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3717 if(pCustData->prgCustData ){
3718 pCustData->cCustData=This->ctCustData;
3719 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3720 pCustData->prgCustData[i].guid=pCData->guid;
3721 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3723 }else{
3724 ERR(" OUT OF MEMORY! \n");
3725 return E_OUTOFMEMORY;
3727 return S_OK;
3730 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3731 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3732 ITypeLib2_fnQueryInterface,
3733 ITypeLib2_fnAddRef,
3734 ITypeLib2_fnRelease,
3735 ITypeLib2_fnGetTypeInfoCount,
3736 ITypeLib2_fnGetTypeInfo,
3737 ITypeLib2_fnGetTypeInfoType,
3738 ITypeLib2_fnGetTypeInfoOfGuid,
3739 ITypeLib2_fnGetLibAttr,
3740 ITypeLib2_fnGetTypeComp,
3741 ITypeLib2_fnGetDocumentation,
3742 ITypeLib2_fnIsName,
3743 ITypeLib2_fnFindName,
3744 ITypeLib2_fnReleaseTLibAttr,
3746 ITypeLib2_fnGetCustData,
3747 ITypeLib2_fnGetLibStatistics,
3748 ITypeLib2_fnGetDocumentation2,
3749 ITypeLib2_fnGetAllCustData
3752 /*================== ITypeInfo(2) Methods ===================================*/
3753 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3755 ITypeInfoImpl * pTypeInfoImpl;
3757 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3758 if (pTypeInfoImpl)
3760 pTypeInfoImpl->lpVtbl = &tinfvt;
3761 pTypeInfoImpl->ref=1;
3763 TRACE("(%p)\n", pTypeInfoImpl);
3764 return (ITypeInfo2*) pTypeInfoImpl;
3767 /* ITypeInfo::QueryInterface
3769 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3770 ITypeInfo2 *iface,
3771 REFIID riid,
3772 VOID **ppvObject)
3774 ICOM_THIS( ITypeLibImpl, iface);
3776 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3778 *ppvObject=NULL;
3779 if(IsEqualIID(riid, &IID_IUnknown) ||
3780 IsEqualIID(riid,&IID_ITypeInfo)||
3781 IsEqualIID(riid,&IID_ITypeInfo2))
3782 *ppvObject = This;
3784 if(*ppvObject){
3785 ITypeInfo_AddRef(iface);
3786 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3787 return S_OK;
3789 TRACE("-- Interface: E_NOINTERFACE\n");
3790 return E_NOINTERFACE;
3793 /* ITypeInfo::AddRef
3795 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3797 ICOM_THIS( ITypeInfoImpl, iface);
3799 ++(This->ref);
3801 TRACE("(%p)->ref is %u\n",This, This->ref);
3802 return This->ref;
3805 /* ITypeInfo::Release
3807 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3809 ICOM_THIS( ITypeInfoImpl, iface);
3811 --(This->ref);
3813 TRACE("(%p)->(%u)\n",This, This->ref);
3815 if (!This->ref)
3817 FIXME("destroy child objects\n");
3819 TRACE("destroying ITypeInfo(%p)\n",This);
3820 if (This->Name)
3822 SysFreeString(This->Name);
3823 This->Name = 0;
3826 if (This->DocString)
3828 SysFreeString(This->DocString);
3829 This->DocString = 0;
3832 if (This->next)
3834 ITypeInfo_Release((ITypeInfo*)This->next);
3837 HeapFree(GetProcessHeap(),0,This);
3838 return 0;
3840 return This->ref;
3843 /* ITypeInfo::GetTypeAttr
3845 * Retrieves a TYPEATTR structure that contains the attributes of the type
3846 * description.
3849 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3850 LPTYPEATTR *ppTypeAttr)
3852 ICOM_THIS( ITypeInfoImpl, iface);
3853 TRACE("(%p)\n",This);
3854 /* FIXME: must do a copy here */
3855 *ppTypeAttr=&This->TypeAttr;
3856 return S_OK;
3859 /* ITypeInfo::GetTypeComp
3861 * Retrieves the ITypeComp interface for the type description, which enables a
3862 * client compiler to bind to the type description's members.
3865 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3866 ITypeComp * *ppTComp)
3868 ICOM_THIS( ITypeInfoImpl, iface);
3869 FIXME("(%p) stub!\n", This);
3870 return S_OK;
3873 /* ITypeInfo::GetFuncDesc
3875 * Retrieves the FUNCDESC structure that contains information about a
3876 * specified function.
3879 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3880 LPFUNCDESC *ppFuncDesc)
3882 ICOM_THIS( ITypeInfoImpl, iface);
3883 int i;
3884 TLBFuncDesc * pFDesc;
3885 TRACE("(%p) index %d\n", This, index);
3886 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3888 if(pFDesc){
3889 /* FIXME: must do a copy here */
3890 *ppFuncDesc=&pFDesc->funcdesc;
3891 return S_OK;
3893 return E_INVALIDARG;
3896 /* ITypeInfo::GetVarDesc
3898 * Retrieves a VARDESC structure that describes the specified variable.
3901 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3902 LPVARDESC *ppVarDesc)
3904 ICOM_THIS( ITypeInfoImpl, iface);
3905 int i;
3906 TLBVarDesc * pVDesc;
3907 TRACE("(%p) index %d\n", This, index);
3908 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3910 if(pVDesc){
3911 /* FIXME: must do a copy here */
3912 *ppVarDesc=&pVDesc->vardesc;
3913 return S_OK;
3915 return E_INVALIDARG;
3918 /* ITypeInfo_GetNames
3920 * Retrieves the variable with the specified member ID (or the name of the
3921 * property or method and its parameters) that correspond to the specified
3922 * function ID.
3924 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3925 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3927 ICOM_THIS( ITypeInfoImpl, iface);
3928 TLBFuncDesc * pFDesc;
3929 TLBVarDesc * pVDesc;
3930 int i;
3931 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3932 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3933 if(pFDesc)
3935 /* function found, now return function and parameter names */
3936 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3938 if(!i)
3939 *rgBstrNames=SysAllocString(pFDesc->Name);
3940 else
3941 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3943 *pcNames=i;
3945 else
3947 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3948 if(pVDesc)
3950 *rgBstrNames=SysAllocString(pVDesc->Name);
3951 *pcNames=1;
3953 else
3955 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3957 /* recursive search */
3958 ITypeInfo *pTInfo;
3959 HRESULT result;
3960 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3961 &pTInfo);
3962 if(SUCCEEDED(result))
3964 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3965 ITypeInfo_Release(pTInfo);
3966 return result;
3968 WARN("Could not search inherited interface!\n");
3970 else
3972 WARN("no names found\n");
3974 *pcNames=0;
3975 return TYPE_E_ELEMENTNOTFOUND;
3978 return S_OK;
3982 /* ITypeInfo::GetRefTypeOfImplType
3984 * If a type description describes a COM class, it retrieves the type
3985 * description of the implemented interface types. For an interface,
3986 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3987 * if any exist.
3990 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3991 ITypeInfo2 *iface,
3992 UINT index,
3993 HREFTYPE *pRefType)
3995 ICOM_THIS( ITypeInfoImpl, iface);
3996 int(i);
3997 TLBImplType *pImpl = This->impltypelist;
3999 TRACE("(%p) index %d\n", This, index);
4000 if (TRACE_ON(ole)) dump_TypeInfo(This);
4002 if(index==(UINT)-1)
4004 /* only valid on dual interfaces;
4005 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4007 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4009 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4010 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4012 *pRefType = -1;
4014 else
4016 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4017 *pRefType = pImpl->hRef;
4020 else
4022 /* get element n from linked list */
4023 for(i=0; pImpl && i<index; i++)
4025 pImpl = pImpl->next;
4028 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4030 *pRefType = pImpl->hRef;
4032 TRACE("-- 0x%08lx\n", pImpl->hRef );
4035 return S_OK;
4039 /* ITypeInfo::GetImplTypeFlags
4041 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4042 * or base interface in a type description.
4044 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4045 UINT index, INT *pImplTypeFlags)
4047 ICOM_THIS( ITypeInfoImpl, iface);
4048 int i;
4049 TLBImplType *pImpl;
4051 TRACE("(%p) index %d\n", This, index);
4052 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4053 i++, pImpl=pImpl->next)
4055 if(i==index && pImpl){
4056 *pImplTypeFlags=pImpl->implflags;
4057 return S_OK;
4059 *pImplTypeFlags=0;
4060 return TYPE_E_ELEMENTNOTFOUND;
4063 /* GetIDsOfNames
4064 * Maps between member names and member IDs, and parameter names and
4065 * parameter IDs.
4067 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4068 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4070 ICOM_THIS( ITypeInfoImpl, iface);
4071 TLBFuncDesc * pFDesc;
4072 TLBVarDesc * pVDesc;
4073 HRESULT ret=S_OK;
4075 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4076 cNames);
4077 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4078 int i, j;
4079 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4080 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4081 for(i=1; i < cNames; i++){
4082 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4083 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4084 break;
4085 if( j<pFDesc->funcdesc.cParams)
4086 pMemId[i]=j;
4087 else
4088 ret=DISP_E_UNKNOWNNAME;
4090 return ret;
4093 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4094 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4095 if(cNames) *pMemId=pVDesc->vardesc.memid;
4096 return ret;
4099 /* not found, see if this is and interface with an inheritance */
4100 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
4101 This->TypeAttr.cImplTypes ){
4102 /* recursive search */
4103 ITypeInfo *pTInfo;
4104 ret=ITypeInfo_GetRefTypeInfo(iface,
4105 This->impltypelist->hRef, &pTInfo);
4106 if(SUCCEEDED(ret)){
4107 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4108 ITypeInfo_Release(pTInfo);
4109 return ret;
4111 WARN("Could not search inherited interface!\n");
4112 } else
4113 WARN("no names found\n");
4114 return DISP_E_UNKNOWNNAME;
4117 /* ITypeInfo::Invoke
4119 * Invokes a method, or accesses a property of an object, that implements the
4120 * interface described by the type description.
4122 DWORD
4123 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4124 DWORD res;
4126 if (TRACE_ON(ole)) {
4127 int i;
4128 TRACE("Calling %p(",func);
4129 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4130 TRACE(")\n");
4133 switch (callconv) {
4134 case CC_STDCALL:
4136 switch (nrargs) {
4137 case 0:
4138 res = func();
4139 break;
4140 case 1:
4141 res = func(args[0]);
4142 break;
4143 case 2:
4144 res = func(args[0],args[1]);
4145 break;
4146 case 3:
4147 res = func(args[0],args[1],args[2]);
4148 break;
4149 case 4:
4150 res = func(args[0],args[1],args[2],args[3]);
4151 break;
4152 case 5:
4153 res = func(args[0],args[1],args[2],args[3],args[4]);
4154 break;
4155 case 6:
4156 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4157 break;
4158 case 7:
4159 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4160 break;
4161 case 8:
4162 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4163 break;
4164 case 9:
4165 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4166 break;
4167 default:
4168 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4169 res = -1;
4170 break;
4172 break;
4173 default:
4174 FIXME("unsupported calling convention %d\n",callconv);
4175 res = -1;
4176 break;
4178 TRACE("returns %08lx\n",res);
4179 return res;
4182 extern int const _argsize(DWORD vt);
4184 /****************************************************************************
4185 * Helper functions for Dispcall / Invoke, which copies one variant
4186 * with target type onto the argument stack.
4188 static HRESULT
4189 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4190 DWORD *argpos, VARIANT *arg, VARTYPE vt
4192 UINT arglen = _argsize(vt)*sizeof(DWORD);
4193 VARTYPE oldvt;
4195 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4196 memcpy(argpos,&arg,sizeof(void*));
4197 return S_OK;
4200 if (V_VT(arg) == vt) {
4201 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4202 return S_OK;
4205 if (vt == VT_VARIANT) {
4206 memcpy(argpos, arg, arglen);
4207 return S_OK;
4209 /* Deref BYREF vars if there is need */
4210 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4211 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4212 return S_OK;
4214 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4215 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4216 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4217 return S_OK;
4219 if ((vt == VT_PTR) && tdesc)
4220 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4221 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4222 ITypeInfo *tinfo2;
4223 TYPEATTR *tattr;
4224 HRESULT hres;
4226 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4227 if (hres) {
4228 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));
4229 memcpy(argpos, &V_UNION(arg,lVal), 4);
4230 return S_OK;
4232 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4233 switch (tattr->typekind) {
4234 case TKIND_ENUM:
4235 switch ( V_VT( arg ) ) {
4236 case VT_I2:
4237 *argpos = V_UNION(arg,iVal);
4238 return S_OK;
4239 case VT_I4:
4240 memcpy(argpos, &V_UNION(arg,lVal), 4);
4241 return S_OK;
4242 default:
4243 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4244 break;
4247 case TKIND_ALIAS:
4248 tdesc = &(tattr->tdescAlias);
4249 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4250 ITypeInfo_Release(tinfo2);
4251 return hres;
4253 case TKIND_INTERFACE:
4254 if (V_VT(arg) == VT_DISPATCH) {
4255 IDispatch *disp;
4256 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4257 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4258 return S_OK;
4260 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),&IID_IDispatch,(LPVOID*)&disp);
4261 if (SUCCEEDED(hres)) {
4262 memcpy(argpos,&disp,4);
4263 IUnknown_Release(V_UNION(arg,pdispVal));
4264 return S_OK;
4266 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4267 return E_FAIL;
4269 if (V_VT(arg) == VT_UNKNOWN) {
4270 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4271 return S_OK;
4273 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg),debugstr_guid(&(tattr->guid)));
4274 break;
4275 case TKIND_DISPATCH:
4276 if (V_VT(arg) == VT_DISPATCH) {
4277 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4278 return S_OK;
4280 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4281 break;
4282 case TKIND_RECORD:
4283 FIXME("TKIND_RECORD unhandled.\n");
4284 break;
4285 default:
4286 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4287 break;
4289 return E_FAIL;
4291 oldvt = V_VT(arg);
4292 if (VariantChangeType(arg,arg,0,vt)==S_OK) {
4293 FIXME("argument was coerced in-place (0x%x -> 0x%x); source data has been modified!!!\n", oldvt, vt);
4294 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4295 return S_OK;
4297 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4298 return E_FAIL;
4301 /***********************************************************************
4302 * DispCallFunc (OLEAUT32.@)
4304 HRESULT WINAPI
4305 DispCallFunc(
4306 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4307 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4309 int i, argsize, argspos;
4310 DWORD *args;
4311 HRESULT hres;
4313 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4314 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4316 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4317 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4318 argsize = 1;
4319 for (i=0;i<cActuals;i++) {
4320 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4321 dump_Variant(prgpvarg[i]);
4322 argsize += _argsize(prgvt[i]);
4324 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4325 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4326 argspos = 1;
4327 for (i=0;i<cActuals;i++) {
4328 VARIANT *arg = prgpvarg[i];
4329 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4330 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4331 argspos += _argsize(prgvt[i]);
4334 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4336 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4337 hres=S_OK;
4339 else
4341 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4342 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4343 FIXME("Method returned %lx\n",hres);
4345 HeapFree(GetProcessHeap(),0,args);
4346 return hres;
4349 static HRESULT WINAPI ITypeInfo_fnInvoke(
4350 ITypeInfo2 *iface,
4351 VOID *pIUnk,
4352 MEMBERID memid,
4353 UINT16 dwFlags,
4354 DISPPARAMS *pDispParams,
4355 VARIANT *pVarResult,
4356 EXCEPINFO *pExcepInfo,
4357 UINT *pArgErr)
4359 ICOM_THIS( ITypeInfoImpl, iface);
4360 TLBFuncDesc * pFDesc;
4361 TLBVarDesc * pVDesc;
4362 int i;
4363 HRESULT hres;
4365 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4366 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4368 dump_DispParms(pDispParams);
4370 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4371 if (pFDesc->funcdesc.memid == memid) {
4372 if (pFDesc->funcdesc.invkind & dwFlags)
4373 break;
4375 if (pFDesc) {
4376 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4377 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4378 switch (pFDesc->funcdesc.funckind) {
4379 case FUNC_PUREVIRTUAL:
4380 case FUNC_VIRTUAL: {
4381 DWORD res;
4382 int numargs, numargs2, argspos, args2pos;
4383 DWORD *args , *args2;
4386 numargs = 1; numargs2 = 0;
4387 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4388 if (i<pDispParams->cArgs)
4389 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4390 else {
4391 numargs += 1; /* sizeof(lpvoid) */
4392 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4396 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4397 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4399 args[0] = (DWORD)pIUnk;
4400 argspos = 1; args2pos = 0;
4401 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4402 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4403 if (i<pDispParams->cArgs) {
4404 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4405 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4406 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4407 if (FAILED(hres)) return hres;
4408 argspos += arglen;
4409 } else {
4410 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4411 if (tdesc->vt != VT_PTR)
4412 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4413 /*FIXME: give pointers for the rest, so propertyget works*/
4414 args[argspos] = (DWORD)&args2[args2pos];
4416 /* If pointer to variant, pass reference it. */
4417 if ((tdesc->vt == VT_PTR) &&
4418 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4419 pVarResult
4421 args[argspos]= (DWORD)pVarResult;
4422 argspos += 1;
4423 args2pos += arglen;
4426 if (pFDesc->funcdesc.cParamsOpt)
4427 FIXME("Does not support optional parameters (%d)\n",
4428 pFDesc->funcdesc.cParamsOpt
4431 res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4],
4432 pFDesc->funcdesc.callconv,
4433 numargs,
4434 args
4436 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4437 args2pos = 0;
4438 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4439 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4440 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4441 TYPEDESC i4_tdesc;
4442 i4_tdesc.vt = VT_I4;
4444 /* If we are a pointer to a variant, we are done already */
4445 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4446 continue;
4448 VariantInit(pVarResult);
4449 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4451 if (tdesc->vt == VT_PTR)
4452 tdesc = tdesc->u.lptdesc;
4453 if (tdesc->vt == VT_USERDEFINED) {
4454 ITypeInfo *tinfo2;
4455 TYPEATTR *tattr;
4457 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4458 if (hres) {
4459 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4460 return E_FAIL;
4462 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4463 switch (tattr->typekind) {
4464 case TKIND_ENUM:
4465 /* force the return type to be VT_I4 */
4466 tdesc = &i4_tdesc;
4467 break;
4468 case TKIND_ALIAS:
4469 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4470 tdesc = &(tattr->tdescAlias);
4471 break;
4473 case TKIND_INTERFACE:
4474 FIXME("TKIND_INTERFACE unhandled.\n");
4475 break;
4476 case TKIND_DISPATCH:
4477 FIXME("TKIND_DISPATCH unhandled.\n");
4478 break;
4479 case TKIND_RECORD:
4480 FIXME("TKIND_RECORD unhandled.\n");
4481 break;
4482 default:
4483 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4484 break;
4486 ITypeInfo_Release(tinfo2);
4488 V_VT(pVarResult) = tdesc->vt;
4490 /* HACK: VB5 likes this.
4491 * I do not know why. There is 1 example in MSDN which uses
4492 * this which appears broken (mixes int vals and
4493 * IDispatch*.).
4495 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4496 V_VT(pVarResult) = VT_DISPATCH;
4497 TRACE("storing into variant:\n");
4498 dump_Variant(pVarResult);
4499 args2pos += arglen;
4502 HeapFree(GetProcessHeap(),0,args2);
4503 HeapFree(GetProcessHeap(),0,args);
4504 return S_OK;
4506 case FUNC_DISPATCH: {
4507 IDispatch *disp;
4508 HRESULT hr;
4510 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4511 if (hr) {
4512 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4513 return hr;
4515 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4516 hr = IDispatch_Invoke(
4517 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4518 pVarResult,pExcepInfo,pArgErr
4520 if (hr)
4521 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4522 IDispatch_Release(disp);
4523 return hr;
4525 default:
4526 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4527 return E_FAIL;
4529 } else {
4530 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4531 if (pVDesc->vardesc.memid == memid) {
4532 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4533 dump_TLBVarDesc(pVDesc);
4534 break;
4538 /* not found, look for it in inherited interfaces */
4539 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4540 /* recursive search */
4541 ITypeInfo *pTInfo;
4542 HRESULT hr;
4543 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4544 if(SUCCEEDED(hr)){
4545 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4546 ITypeInfo_Release(pTInfo);
4547 return hr;
4549 WARN("Could not search inherited interface!\n");
4551 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4552 return DISP_E_MEMBERNOTFOUND;
4555 /* ITypeInfo::GetDocumentation
4557 * Retrieves the documentation string, the complete Help file name and path,
4558 * and the context ID for the Help topic for a specified type description.
4560 * (Can be tested by the Visual Basic Editor in Word for instance.)
4562 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4563 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4564 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4566 ICOM_THIS( ITypeInfoImpl, iface);
4567 TLBFuncDesc * pFDesc;
4568 TLBVarDesc * pVDesc;
4569 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4570 " HelpContext(%p) HelpFile(%p)\n",
4571 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4572 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4573 if(pBstrName)
4574 *pBstrName=SysAllocString(This->Name);
4575 if(pBstrDocString)
4576 *pBstrDocString=SysAllocString(This->DocString);
4577 if(pdwHelpContext)
4578 *pdwHelpContext=This->dwHelpContext;
4579 if(pBstrHelpFile)
4580 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4581 return S_OK;
4582 }else {/* for a member */
4583 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4584 if(pFDesc->funcdesc.memid==memid){
4585 if(pBstrName)
4586 *pBstrName = SysAllocString(pFDesc->Name);
4587 if(pBstrDocString)
4588 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4589 if(pdwHelpContext)
4590 *pdwHelpContext=pFDesc->helpcontext;
4591 return S_OK;
4593 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4594 if(pVDesc->vardesc.memid==memid){
4595 if(pBstrName)
4596 *pBstrName = SysAllocString(pVDesc->Name);
4597 if(pBstrDocString)
4598 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4599 if(pdwHelpContext)
4600 *pdwHelpContext=pVDesc->HelpContext;
4601 return S_OK;
4604 return TYPE_E_ELEMENTNOTFOUND;
4607 /* ITypeInfo::GetDllEntry
4609 * Retrieves a description or specification of an entry point for a function
4610 * in a DLL.
4612 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4613 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4614 WORD *pwOrdinal)
4616 ICOM_THIS( ITypeInfoImpl, iface);
4617 TLBFuncDesc *pFDesc;
4619 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4621 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4622 if(pFDesc->funcdesc.memid==memid){
4623 dump_TypeInfo(This);
4624 dump_TLBFuncDescOne(pFDesc);
4626 /* FIXME: This is wrong, but how do you find that out? */
4627 if (pBstrDllName) {
4628 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4629 *pBstrDllName = SysAllocString(oleaut32W);
4632 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4633 if (pBstrName)
4634 *pBstrName = SysAllocString(pFDesc->Entry);
4635 if (pwOrdinal)
4636 *pwOrdinal = -1;
4637 return S_OK;
4639 if (pBstrName)
4640 *pBstrName = NULL;
4641 if (pwOrdinal)
4642 *pwOrdinal = (DWORD)pFDesc->Entry;
4643 return S_OK;
4645 return E_FAIL;
4648 /* ITypeInfo::GetRefTypeInfo
4650 * If a type description references other type descriptions, it retrieves
4651 * the referenced type descriptions.
4653 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4654 ITypeInfo2 *iface,
4655 HREFTYPE hRefType,
4656 ITypeInfo **ppTInfo)
4658 ICOM_THIS( ITypeInfoImpl, iface);
4659 HRESULT result = E_FAIL;
4662 if (hRefType == -1 &&
4663 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4664 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4666 /* when we meet a DUAL dispinterface, we must create the interface
4667 * version of it.
4669 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4672 /* the interface version contains the same information as the dispinterface
4673 * copy the contents of the structs.
4675 *pTypeInfoImpl = *This;
4676 pTypeInfoImpl->ref = 1;
4678 /* change the type to interface */
4679 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4681 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4683 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4685 result = S_OK;
4687 } else {
4688 TLBRefType *pRefType;
4689 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4690 if(pRefType->reference == hRefType)
4691 break;
4693 if(!pRefType)
4694 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4695 if(pRefType && hRefType != -1) {
4696 ITypeLib *pTLib = NULL;
4698 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4699 int Index;
4700 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4701 } else {
4702 if(pRefType->pImpTLInfo->pImpTypeLib) {
4703 TRACE("typeinfo in imported typelib that is already loaded\n");
4704 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4705 ITypeLib2_AddRef((ITypeLib*) pTLib);
4706 result = S_OK;
4707 } else {
4708 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4709 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4710 pRefType->pImpTLInfo->wVersionMajor,
4711 pRefType->pImpTLInfo->wVersionMinor,
4712 pRefType->pImpTLInfo->lcid,
4713 &pTLib);
4715 if(!SUCCEEDED(result)) {
4716 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4717 result=LoadTypeLib(libnam, &pTLib);
4718 SysFreeString(libnam);
4720 if(SUCCEEDED(result)) {
4721 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4722 ITypeLib2_AddRef(pTLib);
4726 if(SUCCEEDED(result)) {
4727 if(pRefType->index == TLB_REF_USE_GUID)
4728 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4729 &pRefType->guid,
4730 ppTInfo);
4731 else
4732 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4733 ppTInfo);
4735 if (pTLib != NULL)
4736 ITypeLib2_Release(pTLib);
4740 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4741 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4742 return result;
4745 /* ITypeInfo::AddressOfMember
4747 * Retrieves the addresses of static functions or variables, such as those
4748 * defined in a DLL.
4750 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4751 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4753 ICOM_THIS( ITypeInfoImpl, iface);
4754 FIXME("(%p) stub!\n", This);
4755 return S_OK;
4758 /* ITypeInfo::CreateInstance
4760 * Creates a new instance of a type that describes a component object class
4761 * (coclass).
4763 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4764 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4766 ICOM_THIS( ITypeInfoImpl, iface);
4767 FIXME("(%p) stub!\n", This);
4768 return S_OK;
4771 /* ITypeInfo::GetMops
4773 * Retrieves marshalling information.
4775 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4776 BSTR *pBstrMops)
4778 ICOM_THIS( ITypeInfoImpl, iface);
4779 FIXME("(%p) stub!\n", This);
4780 return S_OK;
4783 /* ITypeInfo::GetContainingTypeLib
4785 * Retrieves the containing type library and the index of the type description
4786 * within that type library.
4788 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4789 ITypeLib * *ppTLib, UINT *pIndex)
4791 ICOM_THIS( ITypeInfoImpl, iface);
4793 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
4794 if (pIndex) {
4795 *pIndex=This->index;
4796 TRACE("returning pIndex=%d", *pIndex);
4799 if (ppTLib) {
4800 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4801 ITypeLib2_AddRef(*ppTLib);
4802 TRACE("returning ppTLib=%p", *ppTLib);
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,