Fixed some issues found by winapi_check.
[wine/dcerpc.git] / dlls / oleaut32 / typelib.c
blob65028db840a27db9a6d46d736b8b359aa1d5e10c
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 #include "winerror.h"
64 #include "winnls.h" /* for PRIMARYLANGID */
65 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
66 #include "winuser.h"
68 #include "wine/unicode.h"
69 #include "wine/obj_base.h"
70 #include "heap.h"
71 #include "ole2disp.h"
72 #include "typelib.h"
73 #include "wine/debug.h"
74 #include "parsedt.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 /****************************************************************************
80 * FromLExxx
82 * Takes p_iVal (which is in little endian) and returns it
83 * in the host machine's byte order.
85 #ifdef WORDS_BIGENDIAN
86 static WORD FromLEWord(WORD p_iVal)
88 return (((p_iVal & 0x00FF) << 8) |
89 ((p_iVal & 0xFF00) >> 8));
93 static DWORD FromLEDWord(DWORD p_iVal)
95 return (((p_iVal & 0x000000FF) << 24) |
96 ((p_iVal & 0x0000FF00) << 8) |
97 ((p_iVal & 0x00FF0000) >> 8) |
98 ((p_iVal & 0xFF000000) >> 24));
100 #else
101 #define FromLEWord(X) (X)
102 #define FromLEDWord(X) (X)
103 #endif
106 /****************************************************************************
107 * FromLExxx
109 * Fix byte order in any structure if necessary
111 #ifdef WORDS_BIGENDIAN
112 static void FromLEWords(void *p_Val, int p_iSize)
114 WORD *Val = p_Val;
116 p_iSize /= sizeof(WORD);
118 while (p_iSize) {
119 *Val = FromLEWord(*Val);
120 Val++;
121 p_iSize--;
126 static void FromLEDWords(void *p_Val, int p_iSize)
128 DWORD *Val = p_Val;
130 p_iSize /= sizeof(DWORD);
132 while (p_iSize) {
133 *Val = FromLEDWord(*Val);
134 Val++;
135 p_iSize--;
138 #else
139 #define FromLEWords(X,Y) /*nothing*/
140 #define FromLEDWords(X,Y) /*nothing*/
141 #endif
144 /****************************************************************************
145 * QueryPathOfRegTypeLib [TYPELIB.14]
147 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
148 * RETURNS
149 * path of typelib
151 HRESULT WINAPI
152 QueryPathOfRegTypeLib16(
153 REFGUID guid, /* [in] referenced guid */
154 WORD wMaj, /* [in] major version */
155 WORD wMin, /* [in] minor version */
156 LCID lcid, /* [in] locale id */
157 LPBSTR16 path /* [out] path of typelib */
159 char xguid[80];
160 char typelibkey[100],pathname[260];
161 DWORD plen;
163 TRACE("\n");
165 if (HIWORD(guid)) {
166 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
167 guid->Data1, guid->Data2, guid->Data3,
168 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
169 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
170 wMaj,wMin,lcid);
171 } else {
172 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
173 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
174 return E_FAIL;
176 plen = sizeof(pathname);
177 if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
178 /* try again without lang specific id */
179 if (SUBLANGID(lcid))
180 return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
181 FIXME("key %s not found\n",typelibkey);
182 return E_FAIL;
184 *path = SysAllocString16(pathname);
185 return S_OK;
188 /****************************************************************************
189 * QueryPathOfRegTypeLib [OLEAUT32.164]
190 * RETURNS
191 * path of typelib
193 HRESULT WINAPI
194 QueryPathOfRegTypeLib(
195 REFGUID guid, /* [in] referenced guid */
196 WORD wMaj, /* [in] major version */
197 WORD wMin, /* [in] minor version */
198 LCID lcid, /* [in] locale id */
199 LPBSTR path ) /* [out] path of typelib */
201 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
202 string termination character on output strings */
204 HRESULT hr = E_FAIL;
206 LCID myLCID = lcid;
208 char szXGUID[80];
209 char szTypeLibKey[100];
210 char szPath[MAX_PATH];
211 DWORD dwPathLen = sizeof(szPath);
213 if ( !HIWORD(guid) )
215 sprintf(szXGUID,
216 "<guid 0x%08lx>",
217 (DWORD) guid);
219 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
220 return E_FAIL;
223 while (hr != S_OK)
225 sprintf(szTypeLibKey,
226 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
227 guid->Data1, guid->Data2, guid->Data3,
228 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
229 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
230 wMaj,
231 wMin,
232 myLCID);
234 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
236 if (!lcid)
237 break;
238 else if (myLCID == lcid)
240 /* try with sub-langid */
241 myLCID = SUBLANGID(lcid);
243 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
245 /* try with system langid */
246 myLCID = 0;
248 else
250 break;
253 else
255 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
256 BSTR bstrPath = SysAllocStringLen(NULL,len);
258 MultiByteToWideChar(CP_ACP,
259 MB_PRECOMPOSED,
260 szPath,
261 dwPathLen,
262 bstrPath,
263 len);
264 *path = bstrPath;
265 hr = S_OK;
269 if (hr != S_OK)
270 TRACE_(typelib)("%s not found\n", szTypeLibKey);
272 return hr;
275 /******************************************************************************
276 * CreateTypeLib [OLEAUT32.160] creates a typelib
278 * RETURNS
279 * Success: S_OK
280 * Failure: Status
282 HRESULT WINAPI CreateTypeLib(
283 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
285 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
286 return E_FAIL;
288 /******************************************************************************
289 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
290 * NOTES
291 * Docs: OLECHAR FAR* szFile
292 * Docs: iTypeLib FAR* FAR* pptLib
294 * RETURNS
295 * Success: S_OK
296 * Failure: Status
298 HRESULT WINAPI LoadTypeLib16(
299 LPOLESTR szFile, /* [in] Name of file to load from */
300 ITypeLib** pptLib) /* [out] Pointer to pointer to loaded type library */
302 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
304 if (pptLib!=0)
305 *pptLib=0;
307 return E_FAIL;
310 /******************************************************************************
311 * LoadTypeLib [OLEAUT32.161]
312 * Loads and registers a type library
313 * NOTES
314 * Docs: OLECHAR FAR* szFile
315 * Docs: iTypeLib FAR* FAR* pptLib
317 * RETURNS
318 * Success: S_OK
319 * Failure: Status
321 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
323 HRESULT WINAPI LoadTypeLib(
324 const OLECHAR *szFile,/* [in] Name of file to load from */
325 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
327 TRACE("\n");
328 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
331 /******************************************************************************
332 * LoadTypeLibEx [OLEAUT32.183]
333 * Loads and optionally registers a type library
335 * RETURNS
336 * Success: S_OK
337 * Failure: Status
339 HRESULT WINAPI LoadTypeLibEx(
340 LPCOLESTR szFile, /* [in] Name of file to load from */
341 REGKIND regkind, /* [in] Specify kind of registration */
342 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
344 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
345 WCHAR *pIndexStr;
346 HRESULT res;
347 INT index = 1;
348 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
350 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
351 NULL)) {
353 /* Look for a trailing '\\' followed by an index */
354 pIndexStr = strrchrW(szFile, '\\');
355 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
356 index = atoiW(pIndexStr);
357 memcpy(szFileCopy, szFile,
358 (pIndexStr - szFile - 1) * sizeof(WCHAR));
359 szFileCopy[pIndexStr - szFile - 1] = '\0';
360 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
361 szPath,NULL))
362 return TYPE_E_CANTLOADLIBRARY;
363 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
364 return TYPE_E_CANTLOADLIBRARY;
365 } else
366 return TYPE_E_CANTLOADLIBRARY;
369 TRACE("File %s index %d\n", debugstr_w(szPath), index);
371 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
373 if (SUCCEEDED(res))
374 switch(regkind)
376 case REGKIND_DEFAULT:
377 /* FIXME: is this correct? */
378 if (!szFile || !szFile[0] ||
379 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
380 break;
381 /* else fall-through */
382 case REGKIND_REGISTER:
383 /* FIXME: Help path? */
384 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
386 IUnknown_Release(*pptLib);
387 *pptLib = 0;
389 break;
390 case REGKIND_NONE:
391 break;
394 TRACE(" returns %08lx\n",res);
395 return res;
398 /******************************************************************************
399 * LoadRegTypeLib [OLEAUT32.162]
401 HRESULT WINAPI LoadRegTypeLib(
402 REFGUID rguid, /* [in] referenced guid */
403 WORD wVerMajor, /* [in] major version */
404 WORD wVerMinor, /* [in] minor version */
405 LCID lcid, /* [in] locale id */
406 ITypeLib **ppTLib) /* [out] path of typelib */
408 BSTR bstr=NULL;
409 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
411 if(SUCCEEDED(res))
413 res= LoadTypeLib(bstr, ppTLib);
414 SysFreeString(bstr);
417 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
419 return res;
423 /******************************************************************************
424 * RegisterTypeLib [OLEAUT32.163]
425 * Adds information about a type library to the System Registry
426 * NOTES
427 * Docs: ITypeLib FAR * ptlib
428 * Docs: OLECHAR FAR* szFullPath
429 * Docs: OLECHAR FAR* szHelpDir
431 * RETURNS
432 * Success: S_OK
433 * Failure: Status
435 HRESULT WINAPI RegisterTypeLib(
436 ITypeLib * ptlib, /* [in] Pointer to the library*/
437 OLECHAR * szFullPath, /* [in] full Path of the library*/
438 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
439 may be NULL*/
441 HRESULT res;
442 TLIBATTR *attr;
443 OLECHAR guid[80];
444 LPSTR guidA;
445 CHAR keyName[120];
446 HKEY key, subKey;
447 UINT types, tidx;
448 TYPEKIND kind;
449 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
451 if (ptlib == NULL || szFullPath == NULL)
452 return E_INVALIDARG;
454 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
455 return E_FAIL;
457 StringFromGUID2(&attr->guid, guid, 80);
458 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
459 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
460 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
461 HeapFree(GetProcessHeap(), 0, guidA);
463 res = S_OK;
464 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
465 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
467 LPOLESTR doc;
469 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
471 if (RegSetValueExW(key, NULL, 0, REG_SZ,
472 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
473 res = E_FAIL;
475 SysFreeString(doc);
477 else
478 res = E_FAIL;
480 /* FIXME: This *seems* to be 0 always, not sure though */
481 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
482 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
484 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
485 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
486 res = E_FAIL;
488 RegCloseKey(subKey);
490 else
491 res = E_FAIL;
493 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
494 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
496 CHAR buf[20];
497 /* FIXME: is %u correct? */
498 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
499 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
500 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
501 res = E_FAIL;
503 RegCloseKey(key);
505 else
506 res = E_FAIL;
508 /* register OLE Automation-compatible interfaces for this typelib */
509 types = ITypeLib_GetTypeInfoCount(ptlib);
510 for (tidx=0; tidx<types; tidx++) {
511 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
512 LPOLESTR name = NULL;
513 ITypeInfo *tinfo = NULL;
514 BOOL stop = FALSE;
515 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
516 switch (kind) {
517 case TKIND_INTERFACE:
518 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
519 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
520 break;
521 case TKIND_DISPATCH:
522 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
523 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
524 break;
525 case TKIND_COCLASS:
526 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
527 /* coclasses should probably not be registered? */
528 break;
529 default:
530 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
531 break;
533 if (tinfo) {
534 TYPEATTR *tattr = NULL;
535 ITypeInfo_GetTypeAttr(tinfo, &tattr);
536 if (tattr) {
537 TRACE_(typelib)("guid=%s, flags=%04x (",
538 debugstr_guid(&tattr->guid),
539 tattr->wTypeFlags);
540 if (TRACE_ON(typelib)) {
541 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
542 XX(FAPPOBJECT);
543 XX(FCANCREATE);
544 XX(FLICENSED);
545 XX(FPREDECLID);
546 XX(FHIDDEN);
547 XX(FCONTROL);
548 XX(FDUAL);
549 XX(FNONEXTENSIBLE);
550 XX(FOLEAUTOMATION);
551 XX(FRESTRICTED);
552 XX(FAGGREGATABLE);
553 XX(FREPLACEABLE);
554 XX(FDISPATCHABLE);
555 XX(FREVERSEBIND);
556 XX(FPROXY);
557 #undef XX
558 MESSAGE("\n");
561 * FIXME: The 1 is just here until we implement rpcrt4
562 * stub/proxy handling. Until then it helps IShield
563 * v6 to work.
565 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
567 /* register interface<->typelib coupling */
568 StringFromGUID2(&tattr->guid, guid, 80);
569 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
570 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
571 HeapFree(GetProcessHeap(), 0, guidA);
573 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
574 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
575 if (name)
576 RegSetValueExW(key, NULL, 0, REG_SZ,
577 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
579 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
580 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
581 RegSetValueExA(subKey, NULL, 0, REG_SZ,
582 PSOA, strlen(PSOA));
583 RegCloseKey(subKey);
585 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
586 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
587 RegSetValueExA(subKey, NULL, 0, REG_SZ,
588 PSOA, strlen(PSOA));
589 RegCloseKey(subKey);
592 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
593 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
594 CHAR ver[32];
595 StringFromGUID2(&attr->guid, guid, 80);
596 snprintf(ver, sizeof(ver), "%x.%x",
597 attr->wMajorVerNum, attr->wMinorVerNum);
598 RegSetValueExW(subKey, NULL, 0, REG_SZ,
599 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
600 RegSetValueExA(subKey, "Version", 0, REG_SZ,
601 ver, lstrlenA(ver));
602 RegCloseKey(subKey);
604 RegCloseKey(key);
607 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
609 ITypeInfo_Release(tinfo);
611 SysFreeString(name);
612 if (stop) break;
616 ITypeLib_ReleaseTLibAttr(ptlib, attr);
618 return res;
622 /******************************************************************************
623 * UnRegisterTypeLib [OLEAUT32.186]
624 * Removes information about a type library from the System Registry
625 * NOTES
627 * RETURNS
628 * Success: S_OK
629 * Failure: Status
631 HRESULT WINAPI UnRegisterTypeLib(
632 REFGUID libid, /* [in] Guid of the library */
633 WORD wVerMajor, /* [in] major version */
634 WORD wVerMinor, /* [in] minor version */
635 LCID lcid, /* [in] locale id */
636 SYSKIND syskind)
638 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
639 return S_OK; /* FIXME: pretend everything is OK */
642 /****************************************************************************
643 * OaBuildVersion (TYPELIB.15)
645 * known TYPELIB.DLL versions:
647 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
648 * OLE 2.02 1993-94 02 3002
649 * OLE 2.03 23 730
650 * OLE 2.03 03 3025
651 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
652 * OLE 2.1 NT 1993-95 ?? ???
653 * OLE 2.3.1 W95 23 700
654 * OLE2 4.0 NT4SP6 1993-98 40 4277
656 DWORD WINAPI OaBuildVersion16(void)
658 /* FIXME: I'd like to return the highest currently known version value
659 * in case the user didn't force a --winver, but I don't know how
660 * to retrieve the "versionForced" info from misc/version.c :(
661 * (this would be useful in other places, too) */
662 FIXME("If you get version error messages, please report them\n");
663 switch(GetVersion() & 0x8000ffff) /* mask off build number */
665 case 0x80000a03: /* WIN31 */
666 return MAKELONG(3027, 3); /* WfW 3.11 */
667 case 0x80000004: /* WIN95 */
668 return MAKELONG(700, 23); /* Win95A */
669 case 0x80000a04: /* WIN98 */
670 return MAKELONG(3024, 10); /* W98 SE */
671 case 0x00000004: /* NT4 */
672 return MAKELONG(4277, 40); /* NT4 SP6 */
673 default:
674 FIXME("Version value not known yet. Please investigate it!\n");
675 return 0;
679 /* for better debugging info leave the static out for the time being */
680 #define static
682 /*======================= ITypeLib implementation =======================*/
684 typedef struct tagTLBCustData
686 GUID guid;
687 VARIANT data;
688 struct tagTLBCustData* next;
689 } TLBCustData;
691 /* data structure for import typelibs */
692 typedef struct tagTLBImpLib
694 int offset; /* offset in the file (MSFT)
695 offset in nametable (SLTG)
696 just used to identify library while reading
697 data from file */
698 GUID guid; /* libid */
699 BSTR name; /* name */
701 LCID lcid; /* lcid of imported typelib */
703 WORD wVersionMajor; /* major version number */
704 WORD wVersionMinor; /* minor version number */
706 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
707 NULL if not yet loaded */
708 struct tagTLBImpLib * next;
709 } TLBImpLib;
711 /* internal ITypeLib data */
712 typedef struct tagITypeLibImpl
714 ICOM_VFIELD(ITypeLib2);
715 UINT ref;
716 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
718 /* strings can be stored in tlb as multibyte strings BUT they are *always*
719 * exported to the application as a UNICODE string.
721 BSTR Name;
722 BSTR DocString;
723 BSTR HelpFile;
724 BSTR HelpStringDll;
725 unsigned long dwHelpContext;
726 int TypeInfoCount; /* nr of typeinfo's in librarry */
727 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
728 int ctCustData; /* number of items in cust data list */
729 TLBCustData * pCustData; /* linked list to cust data */
730 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
731 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
732 libary. Only used while read MSFT
733 typelibs */
734 } ITypeLibImpl;
736 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
738 /* ITypeLib methods */
739 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
740 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
742 /*======================= ITypeInfo implementation =======================*/
744 /* data for refernced types */
745 typedef struct tagTLBRefType
747 INT index; /* Type index for internal ref or for external ref
748 it the format is SLTG. -2 indicates to
749 use guid */
751 GUID guid; /* guid of the referenced type */
752 /* if index == TLB_REF_USE_GUID */
754 HREFTYPE reference; /* The href of this ref */
755 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
756 TLB_REF_INTERNAL for internal refs
757 TLB_REF_NOT_FOUND for broken refs */
759 struct tagTLBRefType * next;
760 } TLBRefType;
762 #define TLB_REF_USE_GUID -2
764 #define TLB_REF_INTERNAL (void*)-2
765 #define TLB_REF_NOT_FOUND (void*)-1
767 /* internal Parameter data */
768 typedef struct tagTLBParDesc
770 BSTR Name;
771 int ctCustData;
772 TLBCustData * pCustData; /* linked list to cust data */
773 } TLBParDesc;
775 /* internal Function data */
776 typedef struct tagTLBFuncDesc
778 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
779 BSTR Name; /* the name of this function */
780 TLBParDesc *pParamDesc; /* array with param names and custom data */
781 int helpcontext;
782 int HelpStringContext;
783 BSTR HelpString;
784 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
785 int ctCustData;
786 TLBCustData * pCustData; /* linked list to cust data; */
787 struct tagTLBFuncDesc * next;
788 } TLBFuncDesc;
790 /* internal Variable data */
791 typedef struct tagTLBVarDesc
793 VARDESC vardesc; /* lots of info on the variable and its attributes. */
794 BSTR Name; /* the name of this variable */
795 int HelpContext;
796 int HelpStringContext; /* FIXME: where? */
797 BSTR HelpString;
798 int ctCustData;
799 TLBCustData * pCustData;/* linked list to cust data; */
800 struct tagTLBVarDesc * next;
801 } TLBVarDesc;
803 /* internal implemented interface data */
804 typedef struct tagTLBImplType
806 HREFTYPE hRef; /* hRef of interface */
807 int implflags; /* IMPLFLAG_*s */
808 int ctCustData;
809 TLBCustData * pCustData;/* linked list to custom data; */
810 struct tagTLBImplType *next;
811 } TLBImplType;
813 /* internal TypeInfo data */
814 typedef struct tagITypeInfoImpl
816 ICOM_VFIELD(ITypeInfo2);
817 UINT ref;
818 TYPEATTR TypeAttr ; /* _lots_ of type information. */
819 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
820 int index; /* index in this typelib; */
821 /* type libs seem to store the doc strings in ascii
822 * so why should we do it in unicode?
824 BSTR Name;
825 BSTR DocString;
826 unsigned long dwHelpContext;
827 unsigned long dwHelpStringContext;
829 /* functions */
830 TLBFuncDesc * funclist; /* linked list with function descriptions */
832 /* variables */
833 TLBVarDesc * varlist; /* linked list with variable descriptions */
835 /* Implemented Interfaces */
836 TLBImplType * impltypelist;
838 TLBRefType * reflist;
839 int ctCustData;
840 TLBCustData * pCustData; /* linked list to cust data; */
841 struct tagITypeInfoImpl * next;
842 } ITypeInfoImpl;
844 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
846 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
848 typedef struct tagTLBContext
850 unsigned int oStart; /* start of TLB in file */
851 unsigned int pos; /* current pos */
852 unsigned int length; /* total length */
853 void *mapping; /* memory mapping */
854 MSFT_SegDir * pTblDir;
855 ITypeLibImpl* pLibInfo;
856 } TLBContext;
859 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
862 debug
864 static void dump_VarType(VARTYPE vt,char *szVarType) {
865 /* FIXME : we could have better trace here, depending on the VARTYPE
866 * of the variant
868 if (vt & VT_RESERVED)
869 szVarType += strlen(strcpy(szVarType, "reserved | "));
870 if (vt & VT_BYREF)
871 szVarType += strlen(strcpy(szVarType, "ref to "));
872 if (vt & VT_ARRAY)
873 szVarType += strlen(strcpy(szVarType, "array of "));
874 if (vt & VT_VECTOR)
875 szVarType += strlen(strcpy(szVarType, "vector of "));
876 switch(vt & VT_TYPEMASK) {
877 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
878 case VT_I2: sprintf(szVarType, "VT_I2"); break;
879 case VT_I4: sprintf(szVarType, "VT_I4"); break;
880 case VT_R4: sprintf(szVarType, "VT_R4"); break;
881 case VT_R8: sprintf(szVarType, "VT_R8"); break;
882 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
883 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
884 case VT_CY: sprintf(szVarType, "VT_CY"); break;
885 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
886 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
887 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
888 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
889 case VT_I1: sprintf(szVarType, "VT_I1"); break;
890 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
891 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
892 case VT_INT: sprintf(szVarType, "VT_INT"); break;
893 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
894 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
895 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
896 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
897 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
901 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
902 if (pTD->vt & VT_RESERVED)
903 szVarType += strlen(strcpy(szVarType, "reserved | "));
904 if (pTD->vt & VT_BYREF)
905 szVarType += strlen(strcpy(szVarType, "ref to "));
906 if (pTD->vt & VT_ARRAY)
907 szVarType += strlen(strcpy(szVarType, "array of "));
908 if (pTD->vt & VT_VECTOR)
909 szVarType += strlen(strcpy(szVarType, "vector of "));
910 switch(pTD->vt & VT_TYPEMASK) {
911 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
912 case VT_I2: sprintf(szVarType, "VT_I2"); break;
913 case VT_I4: sprintf(szVarType, "VT_I4"); break;
914 case VT_R4: sprintf(szVarType, "VT_R4"); break;
915 case VT_R8: sprintf(szVarType, "VT_R8"); break;
916 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
917 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
918 case VT_CY: sprintf(szVarType, "VT_CY"); break;
919 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
920 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
921 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
922 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
923 case VT_I1: sprintf(szVarType, "VT_I1"); break;
924 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
925 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
926 case VT_INT: sprintf(szVarType, "VT_INT"); break;
927 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
928 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
929 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
930 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
931 pTD->u.hreftype); break;
932 case VT_PTR: sprintf(szVarType, "ptr to ");
933 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
934 break;
935 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
936 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
937 break;
938 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
939 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
940 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
941 break;
943 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
947 void dump_ELEMDESC(ELEMDESC *edesc) {
948 char buf[200];
949 dump_TypeDesc(&edesc->tdesc,buf);
950 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
951 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
952 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
954 void dump_FUNCDESC(FUNCDESC *funcdesc) {
955 int i;
956 MESSAGE("memid is %08lx\n",funcdesc->memid);
957 for (i=0;i<funcdesc->cParams;i++) {
958 MESSAGE("Param %d:\n",i);
959 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
961 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
962 switch (funcdesc->funckind) {
963 case FUNC_VIRTUAL: MESSAGE("virtual");break;
964 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
965 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
966 case FUNC_STATIC: MESSAGE("static");break;
967 case FUNC_DISPATCH: MESSAGE("dispatch");break;
968 default: MESSAGE("unknown");break;
970 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
971 switch (funcdesc->invkind) {
972 case INVOKE_FUNC: MESSAGE("func");break;
973 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
974 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
975 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
977 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
978 switch (funcdesc->callconv) {
979 case CC_CDECL: MESSAGE("cdecl");break;
980 case CC_PASCAL: MESSAGE("pascal");break;
981 case CC_STDCALL: MESSAGE("stdcall");break;
982 case CC_SYSCALL: MESSAGE("syscall");break;
983 default:break;
985 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
986 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
987 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
990 void dump_IDLDESC(IDLDESC *idl) {
991 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
994 static char * typekind_desc[] =
996 "TKIND_ENUM",
997 "TKIND_RECORD",
998 "TKIND_MODULE",
999 "TKIND_INTERFACE",
1000 "TKIND_DISPATCH",
1001 "TKIND_COCLASS",
1002 "TKIND_ALIAS",
1003 "TKIND_UNION",
1004 "TKIND_MAX"
1007 void dump_TYPEATTR(TYPEATTR *tattr) {
1008 char buf[200];
1009 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
1010 MESSAGE("\tlcid: %ld\n",tattr->lcid);
1011 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
1012 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
1013 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
1014 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
1015 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
1016 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
1017 MESSAGE("\tcVars: %d\n", tattr->cVars);
1018 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
1019 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
1020 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
1021 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
1022 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
1023 dump_TypeDesc(&tattr->tdescAlias,buf);
1024 MESSAGE("\ttypedesc: %s\n", buf);
1025 dump_IDLDESC(&tattr->idldescType);
1028 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1030 int i;
1031 if (!TRACE_ON(typelib))
1032 return;
1033 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1034 for (i=0;i<pfd->funcdesc.cParams;i++)
1035 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1038 dump_FUNCDESC(&(pfd->funcdesc));
1040 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1041 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1043 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1045 while (pfd)
1047 dump_TLBFuncDescOne(pfd);
1048 pfd = pfd->next;
1051 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1053 while (pvd)
1055 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1056 pvd = pvd->next;
1060 static void dump_TLBImpLib(TLBImpLib *import)
1062 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1063 debugstr_w(import->name));
1064 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1065 import->wVersionMinor, import->lcid, import->offset);
1068 static void dump_TLBRefType(TLBRefType * prt)
1070 while (prt)
1072 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1073 if(prt->index == -1)
1074 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1075 else
1076 TRACE_(typelib)("type no: %d\n", prt->index);
1078 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1079 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1080 TRACE_(typelib)("in lib\n");
1081 dump_TLBImpLib(prt->pImpTLInfo);
1083 prt = prt->next;
1087 static void dump_TLBImplType(TLBImplType * impl)
1089 while (impl) {
1090 TRACE_(typelib)(
1091 "implementing/inheriting interface hRef = %lx implflags %x\n",
1092 impl->hRef, impl->implflags);
1093 impl = impl->next;
1097 void dump_Variant(VARIANT * pvar)
1099 char szVarType[32];
1100 LPVOID ref;
1102 TRACE("(%p)\n", pvar);
1104 if (!pvar) return;
1106 ZeroMemory(szVarType, sizeof(szVarType));
1108 /* FIXME : we could have better trace here, depending on the VARTYPE
1109 * of the variant
1111 dump_VarType(V_VT(pvar),szVarType);
1113 TRACE("VARTYPE: %s\n", szVarType);
1115 if (V_VT(pvar) & VT_BYREF) {
1116 ref = V_UNION(pvar, byref);
1117 TRACE("%p\n", ref);
1119 else ref = &V_UNION(pvar, cVal);
1121 if (V_VT(pvar) & VT_ARRAY) {
1122 /* FIXME */
1123 return;
1125 if (V_VT(pvar) & VT_VECTOR) {
1126 /* FIXME */
1127 return;
1130 switch (V_VT(pvar) & VT_TYPEMASK)
1132 case VT_I2:
1133 TRACE("%d\n", *(short*)ref);
1134 break;
1136 case VT_I4:
1137 TRACE("%d\n", *(INT*)ref);
1138 break;
1140 case VT_R4:
1141 TRACE("%3.3e\n", *(float*)ref);
1142 break;
1144 case VT_R8:
1145 TRACE("%3.3e\n", *(double*)ref);
1146 break;
1148 case VT_BOOL:
1149 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1150 break;
1152 case VT_BSTR:
1153 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1154 break;
1156 case VT_UNKNOWN:
1157 case VT_DISPATCH:
1158 TRACE("%p\n", *(LPVOID*)ref);
1159 break;
1161 case VT_VARIANT:
1162 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1163 break;
1165 case VT_DATE:
1167 struct tm TM;
1168 memset( &TM, 0, sizeof(TM) );
1170 if( DateToTm( *(DATE*)ref, 0, &TM ) == FALSE ) {
1171 TRACE("invalid date? (?)%ld %f\n", *(long*)ref, *(double *)ref);
1172 } else {
1173 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1174 TM.tm_year, TM.tm_mon+1, TM.tm_mday,
1175 TM.tm_hour, TM.tm_min, TM.tm_sec, *(double *)ref);
1177 break;
1180 case VT_CY:
1181 TRACE("%ld (hi), %lu (lo)\n", ((CY *)ref)->s.Hi, ((CY *)ref)->s.Lo);
1182 break;
1185 default:
1186 TRACE("(?)%ld\n", *(long*)ref);
1187 break;
1191 static void dump_DispParms(DISPPARAMS * pdp)
1193 int index = 0;
1195 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1197 while (index < pdp->cArgs)
1199 dump_Variant( &pdp->rgvarg[index] );
1200 ++index;
1204 static void dump_TypeInfo(ITypeInfoImpl * pty)
1206 TRACE("%p ref=%u\n", pty, pty->ref);
1207 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1208 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1209 TRACE("fct:%u var:%u impl:%u\n",
1210 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1211 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1212 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1213 dump_TLBFuncDesc(pty->funclist);
1214 dump_TLBVarDesc(pty->varlist);
1215 dump_TLBImplType(pty->impltypelist);
1218 void dump_VARDESC(VARDESC *v)
1220 MESSAGE("memid %ld\n",v->memid);
1221 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1222 MESSAGE("oInst %ld\n",v->u.oInst);
1223 dump_ELEMDESC(&(v->elemdescVar));
1224 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1225 MESSAGE("varkind %d\n",v->varkind);
1228 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1230 /* VT_LPWSTR is largest type that */
1231 /* may appear in type description*/
1232 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1233 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1234 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1235 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1236 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1237 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1238 {{0},30},{{0},31}
1241 static void TLB_abort()
1243 DebugBreak();
1245 static void * TLB_Alloc(unsigned size)
1247 void * ret;
1248 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1249 /* FIXME */
1250 ERR("cannot allocate memory\n");
1252 return ret;
1255 static void TLB_Free(void * ptr)
1257 HeapFree(GetProcessHeap(), 0, ptr);
1261 /**********************************************************************
1263 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1265 /* read function */
1266 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1268 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1269 pcx->pos, count, pcx->oStart, pcx->length, where);
1271 if (where != DO_NOT_SEEK)
1273 where += pcx->oStart;
1274 if (where > pcx->length)
1276 /* FIXME */
1277 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1278 TLB_abort();
1280 pcx->pos = where;
1282 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1283 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1284 pcx->pos += count;
1285 return count;
1288 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1289 long where )
1291 DWORD ret;
1293 ret = MSFT_Read(buffer, count, pcx, where);
1294 FromLEDWords(buffer, ret);
1296 return ret;
1299 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1300 long where )
1302 DWORD ret;
1304 ret = MSFT_Read(buffer, count, pcx, where);
1305 FromLEWords(buffer, ret);
1307 return ret;
1310 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1312 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1313 memset(pGuid,0, sizeof(GUID));
1314 return;
1316 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1317 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1318 pGuid->Data2 = FromLEWord(pGuid->Data2);
1319 pGuid->Data3 = FromLEWord(pGuid->Data3);
1320 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1323 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1325 char * name;
1326 MSFT_NameIntro niName;
1327 int lengthInChars;
1328 WCHAR* pwstring = NULL;
1329 BSTR bstrName = NULL;
1331 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1332 pcx->pTblDir->pNametab.offset+offset);
1333 niName.namelen &= 0xFF; /* FIXME: correct ? */
1334 name=TLB_Alloc((niName.namelen & 0xff) +1);
1335 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1336 name[niName.namelen & 0xff]='\0';
1338 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1339 name, -1, NULL, 0);
1341 /* no invalid characters in string */
1342 if (lengthInChars)
1344 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1346 /* don't check for invalid character since this has been done previously */
1347 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1349 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1350 lengthInChars = SysStringLen(bstrName);
1351 HeapFree(GetProcessHeap(), 0, pwstring);
1354 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1355 return bstrName;
1358 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1360 char * string;
1361 INT16 length;
1362 int lengthInChars;
1363 BSTR bstr = NULL;
1365 if(offset<0) return NULL;
1366 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1367 if(length <= 0) return 0;
1368 string=TLB_Alloc(length +1);
1369 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1370 string[length]='\0';
1372 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1373 string, -1, NULL, 0);
1375 /* no invalid characters in string */
1376 if (lengthInChars)
1378 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1380 /* don't check for invalid character since this has been done previously */
1381 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1383 bstr = SysAllocStringLen(pwstring, lengthInChars);
1384 lengthInChars = SysStringLen(bstr);
1385 HeapFree(GetProcessHeap(), 0, pwstring);
1388 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1389 return bstr;
1392 * read a value and fill a VARIANT structure
1394 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1396 int size;
1398 TRACE_(typelib)("\n");
1400 if(offset <0) { /* data are packed in here */
1401 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1402 V_UNION(pVar, iVal) = offset & 0xffff;
1403 return;
1405 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1406 pcx->pTblDir->pCustData.offset + offset );
1407 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1408 switch (V_VT(pVar)){
1409 case VT_EMPTY: /* FIXME: is this right? */
1410 case VT_NULL: /* FIXME: is this right? */
1411 case VT_I2 : /* this should not happen */
1412 case VT_I4 :
1413 case VT_R4 :
1414 case VT_ERROR :
1415 case VT_BOOL :
1416 case VT_I1 :
1417 case VT_UI1 :
1418 case VT_UI2 :
1419 case VT_UI4 :
1420 case VT_INT :
1421 case VT_UINT :
1422 case VT_VOID : /* FIXME: is this right? */
1423 case VT_HRESULT :
1424 size=4; break;
1425 case VT_R8 :
1426 case VT_CY :
1427 case VT_DATE :
1428 case VT_I8 :
1429 case VT_UI8 :
1430 case VT_DECIMAL : /* FIXME: is this right? */
1431 case VT_FILETIME :
1432 size=8;break;
1433 /* pointer types with known behaviour */
1434 case VT_BSTR :{
1435 char * ptr;
1436 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1437 if(size <= 0) {
1438 FIXME("BSTR length = %d?\n", size);
1439 } else {
1440 ptr=TLB_Alloc(size);/* allocate temp buffer */
1441 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1442 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1443 /* FIXME: do we need a AtoW conversion here? */
1444 V_UNION(pVar, bstrVal[size])=L'\0';
1445 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1446 TLB_Free(ptr);
1449 size=-4; break;
1450 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1451 case VT_DISPATCH :
1452 case VT_VARIANT :
1453 case VT_UNKNOWN :
1454 case VT_PTR :
1455 case VT_SAFEARRAY :
1456 case VT_CARRAY :
1457 case VT_USERDEFINED :
1458 case VT_LPSTR :
1459 case VT_LPWSTR :
1460 case VT_BLOB :
1461 case VT_STREAM :
1462 case VT_STORAGE :
1463 case VT_STREAMED_OBJECT :
1464 case VT_STORED_OBJECT :
1465 case VT_BLOB_OBJECT :
1466 case VT_CF :
1467 case VT_CLSID :
1468 default:
1469 size=0;
1470 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1471 V_VT(pVar));
1474 if(size>0) /* (big|small) endian correct? */
1475 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1476 return;
1479 * create a linked list with custom data
1481 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1483 MSFT_CDGuid entry;
1484 TLBCustData* pNew;
1485 int count=0;
1487 TRACE_(typelib)("\n");
1489 while(offset >=0){
1490 count++;
1491 pNew=TLB_Alloc(sizeof(TLBCustData));
1492 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1493 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1494 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1495 /* add new custom data at head of the list */
1496 pNew->next=*ppCustData;
1497 *ppCustData=pNew;
1498 offset = entry.next;
1500 return count;
1503 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1504 ITypeInfoImpl *pTI)
1506 if(type <0)
1507 pTd->vt=type & VT_TYPEMASK;
1508 else
1509 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1511 if(pTd->vt == VT_USERDEFINED)
1512 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1514 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1517 static void
1518 MSFT_DoFuncs(TLBContext* pcx,
1519 ITypeInfoImpl* pTI,
1520 int cFuncs,
1521 int cVars,
1522 int offset,
1523 TLBFuncDesc** pptfd)
1526 * member information is stored in a data structure at offset
1527 * indicated by the memoffset field of the typeinfo structure
1528 * There are several distinctive parts.
1529 * the first part starts with a field that holds the total length
1530 * of this (first) part excluding this field. Then follow the records,
1531 * for each member there is one record.
1533 * First entry is always the length of the record (excluding this
1534 * length word).
1535 * Rest of the record depends on the type of the member. If there is
1536 * a field indicating the member type (function variable intereface etc)
1537 * I have not found it yet. At this time we depend on the information
1538 * in the type info and the usual order how things are stored.
1540 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1541 * for each member;
1543 * Third is a equal sized array with file offsets to the name entry
1544 * of each member.
1546 * Forth and last (?) part is an array with offsets to the records in the
1547 * first part of this file segment.
1550 int infolen, nameoffset, reclength, nrattributes, i;
1551 int recoffset = offset + sizeof(INT);
1553 char recbuf[512];
1554 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1556 TRACE_(typelib)("\n");
1558 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1560 for ( i = 0; i < cFuncs ; i++ )
1562 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1564 /* name, eventually add to a hash table */
1565 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1566 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1568 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1570 /* read the function information record */
1571 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1573 reclength &= 0x1ff;
1575 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1577 /* do the attributes */
1578 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1579 / sizeof(int);
1581 if ( nrattributes > 0 )
1583 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1585 if ( nrattributes > 1 )
1587 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1588 pFuncRec->OptAttr[1]) ;
1590 if ( nrattributes > 2 )
1592 if ( pFuncRec->FKCCIC & 0x2000 )
1594 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1596 else
1598 (*pptfd)->Entry = MSFT_ReadString(pcx,
1599 pFuncRec->OptAttr[2]);
1601 if( nrattributes > 5 )
1603 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1605 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1607 MSFT_CustData(pcx,
1608 pFuncRec->OptAttr[6],
1609 &(*pptfd)->pCustData);
1616 /* fill the FuncDesc Structure */
1617 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1618 offset + infolen + ( i + 1) * sizeof(INT));
1620 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1621 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1622 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1623 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1624 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1625 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1626 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1628 MSFT_GetTdesc(pcx,
1629 pFuncRec->DataType,
1630 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1631 pTI);
1633 /* do the parameters/arguments */
1634 if(pFuncRec->nrargs)
1636 int j = 0;
1637 MSFT_ParameterInfo paraminfo;
1639 (*pptfd)->funcdesc.lprgelemdescParam =
1640 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1642 (*pptfd)->pParamDesc =
1643 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1645 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1646 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1648 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1650 TYPEDESC* lpArgTypeDesc = 0;
1652 MSFT_GetTdesc(pcx,
1653 paraminfo.DataType,
1654 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1655 pTI);
1657 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1659 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1661 /* SEEK value = jump to offset,
1662 * from there jump to the end of record,
1663 * go back by (j-1) arguments
1665 MSFT_ReadLEDWords( &paraminfo ,
1666 sizeof(MSFT_ParameterInfo), pcx,
1667 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1668 * sizeof(MSFT_ParameterInfo)));
1669 lpArgTypeDesc =
1670 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1672 while ( lpArgTypeDesc != NULL )
1674 switch ( lpArgTypeDesc->vt )
1676 case VT_PTR:
1677 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1678 break;
1680 case VT_CARRAY:
1681 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1682 break;
1684 case VT_USERDEFINED:
1685 MSFT_DoRefType(pcx, pTI,
1686 lpArgTypeDesc->u.hreftype);
1688 lpArgTypeDesc = NULL;
1689 break;
1691 default:
1692 lpArgTypeDesc = NULL;
1698 /* parameter is the return value! */
1699 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1701 TYPEDESC* lpArgTypeDesc;
1703 (*pptfd)->funcdesc.elemdescFunc =
1704 (*pptfd)->funcdesc.lprgelemdescParam[j];
1706 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1708 while ( lpArgTypeDesc != NULL )
1710 switch ( lpArgTypeDesc->vt )
1712 case VT_PTR:
1713 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1714 break;
1715 case VT_CARRAY:
1716 lpArgTypeDesc =
1717 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1719 break;
1721 case VT_USERDEFINED:
1722 MSFT_DoRefType(pcx,
1723 pTI,
1724 lpArgTypeDesc->u.hreftype);
1726 lpArgTypeDesc = NULL;
1727 break;
1729 default:
1730 lpArgTypeDesc = NULL;
1735 /* second time around */
1736 for(j=0;j<pFuncRec->nrargs;j++)
1738 /* name */
1739 (*pptfd)->pParamDesc[j].Name =
1740 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1742 /* default value */
1743 if ( (PARAMFLAG_FHASDEFAULT &
1744 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1745 ((pFuncRec->FKCCIC) & 0x1000) )
1747 INT* pInt = (INT *)((char *)pFuncRec +
1748 reclength -
1749 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1751 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1753 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1754 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1756 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1757 pInt[j], pcx);
1759 /* custom info */
1760 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1762 MSFT_CustData(pcx,
1763 pFuncRec->OptAttr[7+j],
1764 &(*pptfd)->pParamDesc[j].pCustData);
1769 /* scode is not used: archaic win16 stuff FIXME: right? */
1770 (*pptfd)->funcdesc.cScodes = 0 ;
1771 (*pptfd)->funcdesc.lprgscode = NULL ;
1773 pptfd = & ((*pptfd)->next);
1774 recoffset += reclength;
1777 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1778 int cVars, int offset, TLBVarDesc ** pptvd)
1780 int infolen, nameoffset, reclength;
1781 char recbuf[256];
1782 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1783 int i;
1784 int recoffset;
1786 TRACE_(typelib)("\n");
1788 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1789 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1790 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1791 recoffset += offset+sizeof(INT);
1792 for(i=0;i<cVars;i++){
1793 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1794 /* name, eventually add to a hash table */
1795 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1796 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1797 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1798 /* read the variable information record */
1799 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1800 reclength &=0xff;
1801 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1802 /* Optional data */
1803 if(reclength >(6*sizeof(INT)) )
1804 (*pptvd)->HelpContext=pVarRec->HelpContext;
1805 if(reclength >(7*sizeof(INT)) )
1806 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1807 if(reclength >(8*sizeof(INT)) )
1808 if(reclength >(9*sizeof(INT)) )
1809 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1810 /* fill the VarDesc Structure */
1811 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1812 offset + infolen + ( i + 1) * sizeof(INT));
1813 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1814 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1815 MSFT_GetTdesc(pcx, pVarRec->DataType,
1816 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1817 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1818 if(pVarRec->VarKind == VAR_CONST ){
1819 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1820 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1821 pVarRec->OffsValue, pcx);
1822 } else
1823 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1824 pptvd=&((*pptvd)->next);
1825 recoffset += reclength;
1828 /* fill in data for a hreftype (offset). When the refernced type is contained
1829 * in the typelib, it's just an (file) offset in the type info base dir.
1830 * If comes from import, it's an offset+1 in the ImpInfo table
1831 * */
1832 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1833 int offset)
1835 int j;
1836 TLBRefType **ppRefType = &pTI->reflist;
1838 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1840 while(*ppRefType) {
1841 if((*ppRefType)->reference == offset)
1842 return;
1843 ppRefType = &(*ppRefType)->next;
1846 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1847 sizeof(**ppRefType));
1849 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1850 /* external typelib */
1851 MSFT_ImpInfo impinfo;
1852 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1854 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1856 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1857 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1858 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1859 if(pImpLib->offset==impinfo.oImpFile) break;
1860 pImpLib=pImpLib->next;
1862 if(pImpLib){
1863 (*ppRefType)->reference=offset;
1864 (*ppRefType)->pImpTLInfo = pImpLib;
1865 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1866 (*ppRefType)->index = TLB_REF_USE_GUID;
1867 }else{
1868 ERR("Cannot find a reference\n");
1869 (*ppRefType)->reference=-1;
1870 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1872 }else{
1873 /* in this typelib */
1874 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1875 (*ppRefType)->reference=offset;
1876 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1880 /* process Implemented Interfaces of a com class */
1881 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1882 int offset)
1884 int i;
1885 MSFT_RefRecord refrec;
1886 TLBImplType **ppImpl = &pTI->impltypelist;
1888 TRACE_(typelib)("\n");
1890 for(i=0;i<count;i++){
1891 if(offset<0) break; /* paranoia */
1892 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1893 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1894 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1895 (*ppImpl)->hRef = refrec.reftype;
1896 (*ppImpl)->implflags=refrec.flags;
1897 (*ppImpl)->ctCustData=
1898 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1899 offset=refrec.onext;
1900 ppImpl=&((*ppImpl)->next);
1904 * process a typeinfo record
1906 ITypeInfoImpl * MSFT_DoTypeInfo(
1907 TLBContext *pcx,
1908 int count,
1909 ITypeLibImpl * pLibInfo)
1911 MSFT_TypeInfoBase tiBase;
1912 ITypeInfoImpl *ptiRet;
1914 TRACE_(typelib)("count=%u\n", count);
1916 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1917 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
1918 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1919 /* this is where we are coming from */
1920 ptiRet->pTypeLib = pLibInfo;
1921 ITypeLib2_AddRef((ITypeLib2 *)pLibInfo);
1922 ptiRet->index=count;
1923 /* fill in the typeattr fields */
1924 FIXME("Assign constructor/destructor memid\n");
1926 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1927 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1928 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1929 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1930 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1931 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1932 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1933 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1934 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1935 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1936 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1937 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1938 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1939 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1940 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1941 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1942 MSFT_GetTdesc(pcx, tiBase.datatype1,
1943 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1945 /* FIXME: */
1946 /* IDLDESC idldescType; *//* never saw this one != zero */
1948 /* name, eventually add to a hash table */
1949 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1950 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1951 /* help info */
1952 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1953 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1954 ptiRet->dwHelpContext=tiBase.helpcontext;
1955 /* note: InfoType's Help file and HelpStringDll come from the containing
1956 * library. Further HelpString and Docstring appear to be the same thing :(
1958 /* functions */
1959 if(ptiRet->TypeAttr.cFuncs >0 )
1960 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1961 ptiRet->TypeAttr.cVars,
1962 tiBase.memoffset, & ptiRet->funclist);
1963 /* variables */
1964 if(ptiRet->TypeAttr.cVars >0 )
1965 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1966 ptiRet->TypeAttr.cVars,
1967 tiBase.memoffset, & ptiRet->varlist);
1968 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1969 switch(ptiRet->TypeAttr.typekind)
1971 case TKIND_COCLASS:
1972 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1973 tiBase.datatype1);
1974 break;
1975 case TKIND_DISPATCH:
1976 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1978 if (tiBase.datatype1 != -1)
1980 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1981 ptiRet->impltypelist->hRef = tiBase.datatype1;
1983 else
1984 { /* FIXME: This is a really bad hack to add IDispatch */
1985 char* szStdOle = "stdole2.tlb\0";
1986 int nStdOleLen = strlen(szStdOle);
1987 TLBRefType **ppRef = &ptiRet->reflist;
1989 while(*ppRef) {
1990 if((*ppRef)->reference == -1)
1991 break;
1992 ppRef = &(*ppRef)->next;
1994 if(!*ppRef) {
1995 *ppRef = TLB_Alloc(sizeof(**ppRef));
1996 (*ppRef)->guid = IID_IDispatch;
1997 (*ppRef)->reference = -1;
1998 (*ppRef)->index = TLB_REF_USE_GUID;
1999 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2000 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2001 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2002 nStdOleLen + 1);
2004 MultiByteToWideChar(CP_ACP,
2005 MB_PRECOMPOSED,
2006 szStdOle,
2008 (*ppRef)->pImpTLInfo->name,
2009 SysStringLen((*ppRef)->pImpTLInfo->name));
2011 (*ppRef)->pImpTLInfo->lcid = 0;
2012 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2013 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2016 break;
2017 default:
2018 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2019 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2020 ptiRet->impltypelist->hRef = tiBase.datatype1;
2021 break;
2024 ptiRet->ctCustData=
2025 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2027 TRACE_(typelib)("%s guid: %s kind:%s\n",
2028 debugstr_w(ptiRet->Name),
2029 debugstr_guid(&ptiRet->TypeAttr.guid),
2030 typekind_desc[ptiRet->TypeAttr.typekind]);
2032 return ptiRet;
2035 /****************************************************************************
2036 * TLB_ReadTypeLib
2038 * find the type of the typelib file and map the typelib resource into
2039 * the memory
2041 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2042 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2043 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2045 int ret = TYPE_E_CANTLOADLIBRARY;
2046 DWORD dwSignature = 0;
2047 HANDLE hFile;
2049 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2051 *ppTypeLib = NULL;
2053 /* check the signature of the file */
2054 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2055 if (INVALID_HANDLE_VALUE != hFile)
2057 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2058 if (hMapping)
2060 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2061 if(pBase)
2063 /* retrieve file size */
2064 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2066 /* first try to load as *.tlb */
2067 dwSignature = FromLEDWord(*((DWORD*) pBase));
2068 if ( dwSignature == MSFT_SIGNATURE)
2070 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2072 else if ( dwSignature == SLTG_SIGNATURE)
2074 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2076 UnmapViewOfFile(pBase);
2078 CloseHandle(hMapping);
2080 CloseHandle(hFile);
2083 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2085 /* find the typelibrary resource*/
2086 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2087 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2088 if (hinstDLL)
2090 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2091 "TYPELIB");
2092 if (hrsrc)
2094 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2095 if (hGlobal)
2097 LPVOID pBase = LockResource(hGlobal);
2098 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2100 if (pBase)
2102 /* try to load as incore resource */
2103 dwSignature = FromLEDWord(*((DWORD*) pBase));
2104 if ( dwSignature == MSFT_SIGNATURE)
2106 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2108 else if ( dwSignature == SLTG_SIGNATURE)
2110 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2112 else
2114 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2117 FreeResource( hGlobal );
2120 FreeLibrary(hinstDLL);
2124 if(*ppTypeLib)
2125 ret = S_OK;
2126 else
2127 ERR("Loading of typelib %s failed with error %ld\n",
2128 debugstr_w(pszFileName), GetLastError());
2130 return ret;
2133 /*================== ITypeLib(2) Methods ===================================*/
2135 /****************************************************************************
2136 * ITypeLib2_Constructor_MSFT
2138 * loading an MSFT typelib from an in-memory image
2140 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2142 TLBContext cx;
2143 long lPSegDir;
2144 MSFT_Header tlbHeader;
2145 MSFT_SegDir tlbSegDir;
2146 ITypeLibImpl * pTypeLibImpl;
2148 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2150 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2151 if (!pTypeLibImpl) return NULL;
2153 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2154 pTypeLibImpl->ref = 1;
2156 /* get pointer to beginning of typelib data */
2157 cx.pos = 0;
2158 cx.oStart=0;
2159 cx.mapping = pLib;
2160 cx.pLibInfo = pTypeLibImpl;
2161 cx.length = dwTLBLength;
2163 /* read header */
2164 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2165 TRACE("header:\n");
2166 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2167 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2168 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2169 return NULL;
2171 /* there is a small amount of information here until the next important
2172 * part:
2173 * the segment directory . Try to calculate the amount of data */
2174 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2176 /* now read the segment directory */
2177 TRACE("read segment directory (at %ld)\n",lPSegDir);
2178 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2179 cx.pTblDir = &tlbSegDir;
2181 /* just check two entries */
2182 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2184 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2185 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2186 return NULL;
2189 /* now fill our internal data */
2190 /* TLIBATTR fields */
2191 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2193 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2194 /* Windows seems to have zero here, is this correct? */
2195 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2196 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2197 else
2198 pTypeLibImpl->LibAttr.lcid = 0;
2200 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2201 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2202 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2203 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2205 /* name, eventually add to a hash table */
2206 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2208 /* help info */
2209 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2210 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2212 if( tlbHeader.varflags & HELPDLLFLAG)
2214 int offset;
2215 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2216 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2219 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2221 /* custom data */
2222 if(tlbHeader.CustomDataOffset >= 0)
2224 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2227 /* fill in typedescriptions */
2228 if(tlbSegDir.pTypdescTab.length > 0)
2230 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2231 INT16 td[4];
2232 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2233 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2234 for(i=0; i<cTD; )
2236 /* FIXME: add several sanity checks here */
2237 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2238 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2240 /* FIXME: check safearray */
2241 if(td[3] < 0)
2242 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2243 else
2244 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2246 else if(td[0] == VT_CARRAY)
2248 /* array descr table here */
2249 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2251 else if(td[0] == VT_USERDEFINED)
2253 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2255 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2258 /* second time around to fill the array subscript info */
2259 for(i=0;i<cTD;i++)
2261 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2262 if(tlbSegDir.pArrayDescriptions.offset>0)
2264 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2265 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2267 if(td[1]<0)
2268 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2269 else
2270 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2272 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2274 for(j = 0; j<td[2]; j++)
2276 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2277 sizeof(INT), &cx, DO_NOT_SEEK);
2278 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2279 sizeof(INT), &cx, DO_NOT_SEEK);
2282 else
2284 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2285 ERR("didn't find array description data\n");
2290 /* imported type libs */
2291 if(tlbSegDir.pImpFiles.offset>0)
2293 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2294 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2295 UINT16 size;
2297 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2299 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2300 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2301 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2303 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2304 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2305 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2306 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2308 size >>= 2;
2309 (*ppImpLib)->name = TLB_Alloc(size+1);
2310 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2311 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2312 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2314 ppImpLib = &(*ppImpLib)->next;
2318 /* type info's */
2319 if(tlbHeader.nrtypeinfos >= 0 )
2321 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2322 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2323 int i;
2325 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2327 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2329 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2330 ppTI = &((*ppTI)->next);
2331 (pTypeLibImpl->TypeInfoCount)++;
2335 TRACE("(%p)\n", pTypeLibImpl);
2336 return (ITypeLib2*) pTypeLibImpl;
2340 static BSTR TLB_MultiByteToBSTR(char *ptr)
2342 DWORD len;
2343 WCHAR *nameW;
2344 BSTR ret;
2346 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2347 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2348 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2349 ret = SysAllocString(nameW);
2350 HeapFree(GetProcessHeap(), 0, nameW);
2351 return ret;
2354 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2356 char b[3];
2357 int i;
2358 short s;
2360 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2361 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2362 return FALSE;
2365 guid->Data4[0] = s >> 8;
2366 guid->Data4[1] = s & 0xff;
2368 b[2] = '\0';
2369 for(i = 0; i < 6; i++) {
2370 memcpy(b, str + 24 + 2 * i, 2);
2371 guid->Data4[i + 2] = strtol(b, NULL, 16);
2373 return TRUE;
2376 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2378 WORD bytelen;
2379 DWORD len;
2380 WCHAR *nameW;
2382 *pBstr = NULL;
2383 bytelen = *(WORD*)ptr;
2384 if(bytelen == 0xffff) return 2;
2385 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2386 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2387 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2388 *pBstr = SysAllocStringLen(nameW, len);
2389 HeapFree(GetProcessHeap(), 0, nameW);
2390 return bytelen + 2;
2393 static WORD SLTG_ReadStringA(char *ptr, char **str)
2395 WORD bytelen;
2397 *str = NULL;
2398 bytelen = *(WORD*)ptr;
2399 if(bytelen == 0xffff) return 2;
2400 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2401 memcpy(*str, ptr + 2, bytelen);
2402 (*str)[bytelen] = '\0';
2403 return bytelen + 2;
2406 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2408 char *ptr = pLibBlk;
2409 WORD w;
2411 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2412 FIXME("libblk magic = %04x\n", w);
2413 return 0;
2416 ptr += 6;
2417 if((w = *(WORD*)ptr) != 0xffff) {
2418 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2419 ptr += w;
2421 ptr += 2;
2423 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2425 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2427 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2428 ptr += 4;
2430 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2431 ptr += 2;
2433 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2434 ptr += 2;
2436 ptr += 4; /* skip res12 */
2438 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2439 ptr += 2;
2441 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2442 ptr += 2;
2444 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2445 ptr += 2;
2447 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2448 ptr += sizeof(GUID);
2450 return ptr - (char*)pLibBlk;
2453 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2455 BOOL done = FALSE;
2456 TYPEDESC *pTD = &pElem->tdesc;
2458 /* Handle [in/out] first */
2459 if((*pType & 0xc000) == 0xc000)
2460 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2461 else if(*pType & 0x8000)
2462 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2463 else if(*pType & 0x4000)
2464 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2465 else
2466 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2468 if(*pType & 0x2000)
2469 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2471 if(*pType & 0x80)
2472 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2474 while(!done) {
2475 if((*pType & 0xe00) == 0xe00) {
2476 pTD->vt = VT_PTR;
2477 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2478 sizeof(TYPEDESC));
2479 pTD = pTD->u.lptdesc;
2481 switch(*pType & 0x7f) {
2482 case VT_PTR:
2483 pTD->vt = VT_PTR;
2484 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2485 sizeof(TYPEDESC));
2486 pTD = pTD->u.lptdesc;
2487 break;
2489 case VT_USERDEFINED:
2490 pTD->vt = VT_USERDEFINED;
2491 pTD->u.hreftype = *(++pType) / 4;
2492 done = TRUE;
2493 break;
2495 case VT_CARRAY:
2497 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2498 array */
2500 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2502 pTD->vt = VT_CARRAY;
2503 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2504 sizeof(ARRAYDESC) +
2505 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2506 pTD->u.lpadesc->cDims = pSA->cDims;
2507 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2508 pSA->cDims * sizeof(SAFEARRAYBOUND));
2510 pTD = &pTD->u.lpadesc->tdescElem;
2511 break;
2514 case VT_SAFEARRAY:
2516 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2517 useful? */
2519 pType++;
2520 pTD->vt = VT_SAFEARRAY;
2521 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2522 sizeof(TYPEDESC));
2523 pTD = pTD->u.lptdesc;
2524 break;
2526 default:
2527 pTD->vt = *pType & 0x7f;
2528 done = TRUE;
2529 break;
2531 pType++;
2533 return pType;
2537 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2538 char *pNameTable)
2540 int ref;
2541 char *name;
2542 TLBRefType **ppRefType;
2544 if(pRef->magic != SLTG_REF_MAGIC) {
2545 FIXME("Ref magic = %x\n", pRef->magic);
2546 return;
2548 name = ( (char*)(&pRef->names) + pRef->number);
2550 ppRefType = &pTI->reflist;
2551 for(ref = 0; ref < pRef->number >> 3; ref++) {
2552 char *refname;
2553 unsigned int lib_offs, type_num;
2555 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2556 sizeof(**ppRefType));
2558 name += SLTG_ReadStringA(name, &refname);
2559 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2560 FIXME("Can't sscanf ref\n");
2561 if(lib_offs != 0xffff) {
2562 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2564 while(*import) {
2565 if((*import)->offset == lib_offs)
2566 break;
2567 import = &(*import)->next;
2569 if(!*import) {
2570 char fname[MAX_PATH+1];
2571 int len;
2573 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2574 sizeof(**import));
2575 (*import)->offset = lib_offs;
2576 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2577 &(*import)->guid);
2578 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2579 &(*import)->wVersionMajor,
2580 &(*import)->wVersionMinor,
2581 &(*import)->lcid, fname) != 4) {
2582 FIXME("can't sscanf ref %s\n",
2583 pNameTable + lib_offs + 40);
2585 len = strlen(fname);
2586 if(fname[len-1] != '#')
2587 FIXME("fname = %s\n", fname);
2588 fname[len-1] = '\0';
2589 (*import)->name = TLB_MultiByteToBSTR(fname);
2591 (*ppRefType)->pImpTLInfo = *import;
2592 } else { /* internal ref */
2593 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2595 (*ppRefType)->reference = ref;
2596 (*ppRefType)->index = type_num;
2598 HeapFree(GetProcessHeap(), 0, refname);
2599 ppRefType = &(*ppRefType)->next;
2601 if((BYTE)*name != SLTG_REF_MAGIC)
2602 FIXME("End of ref block magic = %x\n", *name);
2603 dump_TLBRefType(pTI->reflist);
2606 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2607 BOOL OneOnly)
2609 SLTG_ImplInfo *info;
2610 TLBImplType **ppImplType = &pTI->impltypelist;
2611 /* I don't really get this structure, usually it's 0x16 bytes
2612 long, but iuser.tlb contains some that are 0x18 bytes long.
2613 That's ok because we can use the next ptr to jump to the next
2614 one. But how do we know the length of the last one? The WORD
2615 at offs 0x8 might be the clue. For now I'm just assuming that
2616 the last one is the regular 0x16 bytes. */
2618 info = (SLTG_ImplInfo*)pBlk;
2619 while(1) {
2620 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2621 sizeof(**ppImplType));
2622 (*ppImplType)->hRef = info->ref;
2623 (*ppImplType)->implflags = info->impltypeflags;
2624 pTI->TypeAttr.cImplTypes++;
2625 ppImplType = &(*ppImplType)->next;
2627 if(info->next == 0xffff)
2628 break;
2629 if(OneOnly)
2630 FIXME("Interface inheriting more than one interface\n");
2631 info = (SLTG_ImplInfo*)(pBlk + info->next);
2633 info++; /* see comment at top of function */
2634 return (char*)info;
2637 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2638 char *pNameTable)
2640 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2641 SLTG_MemberHeader *pMemHeader;
2642 char *pFirstItem, *pNextItem;
2644 if(pTIHeader->href_table != 0xffffffff) {
2645 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2646 pNameTable);
2650 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2652 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2654 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2655 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2658 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2662 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2663 char *pNameTable)
2665 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2666 SLTG_MemberHeader *pMemHeader;
2667 SLTG_Function *pFunc;
2668 char *pFirstItem, *pNextItem;
2669 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2670 int num = 0;
2672 if(pTIHeader->href_table != 0xffffffff) {
2673 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2674 pNameTable);
2677 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2679 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2681 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2682 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2685 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2686 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2688 int param;
2689 WORD *pType, *pArg;
2691 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2692 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2693 FIXME("func magic = %02x\n", pFunc->magic);
2694 return NULL;
2696 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2697 sizeof(**ppFuncDesc));
2698 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2700 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2701 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2702 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2703 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2704 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2705 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2707 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2708 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2710 if(pFunc->retnextopt & 0x80)
2711 pType = &pFunc->rettype;
2712 else
2713 pType = (WORD*)(pFirstItem + pFunc->rettype);
2716 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2718 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2719 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2720 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2721 (*ppFuncDesc)->pParamDesc =
2722 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2723 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2725 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2727 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2728 char *paramName = pNameTable + *pArg;
2729 BOOL HaveOffs;
2730 /* If arg type follows then paramName points to the 2nd
2731 letter of the name, else the next WORD is an offset to
2732 the arg type and paramName points to the first letter.
2733 So let's take one char off paramName and see if we're
2734 pointing at an alpha-numeric char. However if *pArg is
2735 0xffff or 0xfffe then the param has no name, the former
2736 meaning that the next WORD is the type, the latter
2737 meaning the the next WORD is an offset to the type. */
2739 HaveOffs = FALSE;
2740 if(*pArg == 0xffff)
2741 paramName = NULL;
2742 else if(*pArg == 0xfffe) {
2743 paramName = NULL;
2744 HaveOffs = TRUE;
2746 else if(!isalnum(*(paramName-1)))
2747 HaveOffs = TRUE;
2749 pArg++;
2751 if(HaveOffs) { /* the next word is an offset to type */
2752 pType = (WORD*)(pFirstItem + *pArg);
2753 SLTG_DoType(pType, pFirstItem,
2754 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2755 pArg++;
2756 } else {
2757 if(paramName)
2758 paramName--;
2759 pArg = SLTG_DoType(pArg, pFirstItem,
2760 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2763 /* Are we an optional param ? */
2764 if((*ppFuncDesc)->funcdesc.cParams - param <=
2765 (*ppFuncDesc)->funcdesc.cParamsOpt)
2766 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2768 if(paramName) {
2769 (*ppFuncDesc)->pParamDesc[param].Name =
2770 TLB_MultiByteToBSTR(paramName);
2774 ppFuncDesc = &((*ppFuncDesc)->next);
2775 if(pFunc->next == 0xffff) break;
2777 pTI->TypeAttr.cFuncs = num;
2778 dump_TLBFuncDesc(pTI->funclist);
2779 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2782 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2783 char *pNameTable)
2785 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2786 SLTG_MemberHeader *pMemHeader;
2787 SLTG_RecordItem *pItem;
2788 char *pFirstItem;
2789 TLBVarDesc **ppVarDesc = &pTI->varlist;
2790 int num = 0;
2791 WORD *pType;
2792 char buf[300];
2794 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2796 pFirstItem = (char*)(pMemHeader + 1);
2797 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2798 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2799 if(pItem->magic != SLTG_RECORD_MAGIC) {
2800 FIXME("record magic = %02x\n", pItem->magic);
2801 return NULL;
2803 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2804 sizeof(**ppVarDesc));
2805 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2806 (*ppVarDesc)->vardesc.memid = pItem->memid;
2807 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2808 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2810 if(pItem->typepos == 0x02)
2811 pType = &pItem->type;
2812 else if(pItem->typepos == 0x00)
2813 pType = (WORD*)(pFirstItem + pItem->type);
2814 else {
2815 FIXME("typepos = %02x\n", pItem->typepos);
2816 break;
2819 SLTG_DoType(pType, pFirstItem,
2820 &(*ppVarDesc)->vardesc.elemdescVar);
2822 /* FIXME("helpcontext, helpstring\n"); */
2824 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2826 ppVarDesc = &((*ppVarDesc)->next);
2827 if(pItem->next == 0xffff) break;
2829 pTI->TypeAttr.cVars = num;
2830 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2833 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2834 char *pNameTable)
2836 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2837 SLTG_MemberHeader *pMemHeader;
2838 SLTG_EnumItem *pItem;
2839 char *pFirstItem;
2840 TLBVarDesc **ppVarDesc = &pTI->varlist;
2841 int num = 0;
2843 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2845 pFirstItem = (char*)(pMemHeader + 1);
2846 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2847 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2848 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2849 FIXME("enumitem magic = %04x\n", pItem->magic);
2850 return NULL;
2852 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2853 sizeof(**ppVarDesc));
2854 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2855 (*ppVarDesc)->vardesc.memid = pItem->memid;
2856 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2857 sizeof(VARIANT));
2858 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2859 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2860 *(INT*)(pItem->value + pFirstItem);
2861 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2862 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2863 /* FIXME("helpcontext, helpstring\n"); */
2865 ppVarDesc = &((*ppVarDesc)->next);
2866 if(pItem->next == 0xffff) break;
2868 pTI->TypeAttr.cVars = num;
2869 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2872 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2873 managable copy of it into this */
2874 typedef struct {
2875 WORD small_no;
2876 char *index_name;
2877 char *other_name;
2878 WORD res1a;
2879 WORD name_offs;
2880 WORD more_bytes;
2881 char *extra;
2882 WORD res20;
2883 DWORD helpcontext;
2884 WORD res26;
2885 GUID uuid;
2886 } SLTG_InternalOtherTypeInfo;
2888 /****************************************************************************
2889 * ITypeLib2_Constructor_SLTG
2891 * loading a SLTG typelib from an in-memory image
2893 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2895 ITypeLibImpl *pTypeLibImpl;
2896 SLTG_Header *pHeader;
2897 SLTG_BlkEntry *pBlkEntry;
2898 SLTG_Magic *pMagic;
2899 SLTG_Index *pIndex;
2900 SLTG_Pad9 *pPad9;
2901 LPVOID pBlk, pFirstBlk;
2902 SLTG_LibBlk *pLibBlk;
2903 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2904 char *pAfterOTIBlks = NULL;
2905 char *pNameTable, *ptr;
2906 int i;
2907 DWORD len, order;
2908 ITypeInfoImpl **ppTypeInfoImpl;
2910 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2912 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2913 if (!pTypeLibImpl) return NULL;
2915 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2916 pTypeLibImpl->ref = 1;
2918 pHeader = pLib;
2920 TRACE("header:\n");
2921 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2922 pHeader->nrOfFileBlks );
2923 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
2924 FIXME("Header type magic 0x%08lx not supported.\n",
2925 pHeader->SLTG_magic);
2926 return NULL;
2929 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2930 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2932 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2933 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2935 /* Next we have a magic block */
2936 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2938 /* Let's see if we're still in sync */
2939 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2940 sizeof(SLTG_COMPOBJ_MAGIC))) {
2941 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2942 return NULL;
2944 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2945 sizeof(SLTG_DIR_MAGIC))) {
2946 FIXME("dir magic = %s\n", pMagic->dir_magic);
2947 return NULL;
2950 pIndex = (SLTG_Index*)(pMagic+1);
2952 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2954 pFirstBlk = (LPVOID)(pPad9 + 1);
2956 /* We'll set up a ptr to the main library block, which is the last one. */
2958 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2959 pBlkEntry[order].next != 0;
2960 order = pBlkEntry[order].next - 1, i++) {
2961 pBlk = (char*)pBlk + pBlkEntry[order].len;
2963 pLibBlk = pBlk;
2965 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2967 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2968 interspersed */
2970 len += 0x40;
2972 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2974 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2975 sizeof(*pOtherTypeInfoBlks) *
2976 pTypeLibImpl->TypeInfoCount);
2979 ptr = (char*)pLibBlk + len;
2981 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2982 WORD w, extra;
2983 len = 0;
2985 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2987 w = *(WORD*)(ptr + 2);
2988 if(w != 0xffff) {
2989 len += w;
2990 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2991 w+1);
2992 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2993 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2995 w = *(WORD*)(ptr + 4 + len);
2996 if(w != 0xffff) {
2997 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2998 len += w;
2999 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3000 w+1);
3001 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3002 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3004 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3005 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3006 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3007 if(extra) {
3008 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3009 extra);
3010 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3011 len += extra;
3013 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3014 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3015 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3016 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3017 len += sizeof(SLTG_OtherTypeInfo);
3018 ptr += len;
3021 pAfterOTIBlks = ptr;
3023 /* Skip this WORD and get the next DWORD */
3024 len = *(DWORD*)(pAfterOTIBlks + 2);
3026 /* Now add this to pLibBLk look at what we're pointing at and
3027 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3028 dust and we should be pointing at the beginning of the name
3029 table */
3031 pNameTable = (char*)pLibBlk + len;
3033 switch(*(WORD*)pNameTable) {
3034 case 0xffff:
3035 break;
3036 case 0x0200:
3037 pNameTable += 0x20;
3038 break;
3039 default:
3040 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3041 break;
3044 pNameTable += 0x216;
3046 pNameTable += 2;
3048 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3050 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3053 /* Hopefully we now have enough ptrs set up to actually read in
3054 some TypeInfos. It's not clear which order to do them in, so
3055 I'll just follow the links along the BlkEntry chain and read
3056 them in in the order in which they're in the file */
3058 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3060 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3061 pBlkEntry[order].next != 0;
3062 order = pBlkEntry[order].next - 1, i++) {
3064 SLTG_TypeInfoHeader *pTIHeader;
3065 SLTG_TypeInfoTail *pTITail;
3067 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3068 pOtherTypeInfoBlks[i].index_name)) {
3069 FIXME("Index strings don't match\n");
3070 return NULL;
3073 pTIHeader = pBlk;
3074 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3075 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3076 return NULL;
3078 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3079 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3080 ITypeLib2_AddRef((ITypeLib2 *)pTypeLibImpl);
3081 (*ppTypeInfoImpl)->index = i;
3082 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3083 pOtherTypeInfoBlks[i].name_offs +
3084 pNameTable);
3085 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3086 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3087 sizeof(GUID));
3088 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3089 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3090 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3091 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3092 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3094 if((pTIHeader->typeflags1 & 7) != 2)
3095 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3096 if(pTIHeader->typeflags3 != 2)
3097 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3099 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3100 debugstr_w((*ppTypeInfoImpl)->Name),
3101 typekind_desc[pTIHeader->typekind],
3102 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3103 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3105 switch(pTIHeader->typekind) {
3106 case TKIND_ENUM:
3107 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3108 break;
3110 case TKIND_RECORD:
3111 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3112 break;
3114 case TKIND_INTERFACE:
3115 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3116 break;
3118 case TKIND_COCLASS:
3119 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3120 break;
3122 default:
3123 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3124 pTITail = NULL;
3125 break;
3129 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3130 but we've already set those */
3131 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3132 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3133 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3135 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3136 pBlk = (char*)pBlk + pBlkEntry[order].len;
3139 if(i != pTypeLibImpl->TypeInfoCount) {
3140 FIXME("Somehow processed %d TypeInfos\n", i);
3141 return NULL;
3144 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3145 return (ITypeLib2*)pTypeLibImpl;
3148 /* ITypeLib::QueryInterface
3150 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3151 ITypeLib2 * iface,
3152 REFIID riid,
3153 VOID **ppvObject)
3155 ICOM_THIS( ITypeLibImpl, iface);
3157 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3159 *ppvObject=NULL;
3160 if(IsEqualIID(riid, &IID_IUnknown) ||
3161 IsEqualIID(riid,&IID_ITypeLib)||
3162 IsEqualIID(riid,&IID_ITypeLib2))
3164 *ppvObject = This;
3167 if(*ppvObject)
3169 ITypeLib2_AddRef(iface);
3170 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3171 return S_OK;
3173 TRACE("-- Interface: E_NOINTERFACE\n");
3174 return E_NOINTERFACE;
3177 /* ITypeLib::AddRef
3179 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3181 ICOM_THIS( ITypeLibImpl, iface);
3183 TRACE("(%p)->ref is %u\n",This, This->ref);
3185 return ++(This->ref);
3188 /* ITypeLib::Release
3190 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3192 ICOM_THIS( ITypeLibImpl, iface);
3194 --(This->ref);
3196 TRACE("(%p)->(%u)\n",This, This->ref);
3198 if (!This->ref)
3200 /* FIXME destroy child objects */
3202 TRACE(" destroying ITypeLib(%p)\n",This);
3204 if (This->Name)
3206 SysFreeString(This->Name);
3207 This->Name = NULL;
3210 if (This->DocString)
3212 SysFreeString(This->DocString);
3213 This->DocString = NULL;
3216 if (This->HelpFile)
3218 SysFreeString(This->HelpFile);
3219 This->HelpFile = NULL;
3222 if (This->HelpStringDll)
3224 SysFreeString(This->HelpStringDll);
3225 This->HelpStringDll = NULL;
3228 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3229 HeapFree(GetProcessHeap(),0,This);
3230 return 0;
3233 return This->ref;
3236 /* ITypeLib::GetTypeInfoCount
3238 * Returns the number of type descriptions in the type library
3240 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3242 ICOM_THIS( ITypeLibImpl, iface);
3243 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3244 return This->TypeInfoCount;
3247 /* ITypeLib::GetTypeInfo
3249 * retrieves the specified type description in the library.
3251 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3252 ITypeLib2 *iface,
3253 UINT index,
3254 ITypeInfo **ppTInfo)
3256 int i;
3258 ICOM_THIS( ITypeLibImpl, iface);
3259 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3261 TRACE("(%p)->(index=%d) \n", This, index);
3263 if (!ppTInfo) return E_INVALIDARG;
3265 /* search element n in list */
3266 for(i=0; i < index; i++)
3268 pTypeInfo = pTypeInfo->next;
3269 if (!pTypeInfo)
3271 TRACE("-- element not found\n");
3272 return TYPE_E_ELEMENTNOTFOUND;
3276 *ppTInfo = (ITypeInfo *) pTypeInfo;
3278 ITypeInfo_AddRef(*ppTInfo);
3279 TRACE("-- found (%p)\n",*ppTInfo);
3280 return S_OK;
3284 /* ITypeLibs::GetTypeInfoType
3286 * Retrieves the type of a type description.
3288 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3289 ITypeLib2 *iface,
3290 UINT index,
3291 TYPEKIND *pTKind)
3293 ICOM_THIS( ITypeLibImpl, iface);
3294 int i;
3295 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3297 TRACE("(%p) index %d \n",This, index);
3299 if(!pTKind) return E_INVALIDARG;
3301 /* search element n in list */
3302 for(i=0; i < index; i++)
3304 if(!pTInfo)
3306 TRACE("-- element not found\n");
3307 return TYPE_E_ELEMENTNOTFOUND;
3309 pTInfo = pTInfo->next;
3312 *pTKind = pTInfo->TypeAttr.typekind;
3313 TRACE("-- found Type (%d)\n", *pTKind);
3314 return S_OK;
3317 /* ITypeLib::GetTypeInfoOfGuid
3319 * Retrieves the type description that corresponds to the specified GUID.
3322 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3323 ITypeLib2 *iface,
3324 REFGUID guid,
3325 ITypeInfo **ppTInfo)
3327 ICOM_THIS( ITypeLibImpl, iface);
3328 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3330 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3332 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3334 /* search linked list for guid */
3335 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3337 pTypeInfo = pTypeInfo->next;
3339 if (!pTypeInfo)
3341 /* end of list reached */
3342 TRACE("-- element not found\n");
3343 return TYPE_E_ELEMENTNOTFOUND;
3347 TRACE("-- found (%p, %s)\n",
3348 pTypeInfo,
3349 debugstr_w(pTypeInfo->Name));
3351 *ppTInfo = (ITypeInfo*)pTypeInfo;
3352 ITypeInfo_AddRef(*ppTInfo);
3353 return S_OK;
3356 /* ITypeLib::GetLibAttr
3358 * Retrieves the structure that contains the library's attributes.
3361 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3362 ITypeLib2 *iface,
3363 LPTLIBATTR *ppTLibAttr)
3365 ICOM_THIS( ITypeLibImpl, iface);
3366 TRACE("(%p)\n",This);
3367 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3368 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3369 return S_OK;
3372 /* ITypeLib::GetTypeComp
3374 * Enables a client compiler to bind to a library's types, variables,
3375 * constants, and global functions.
3378 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3379 ITypeLib2 *iface,
3380 ITypeComp **ppTComp)
3382 ICOM_THIS( ITypeLibImpl, iface);
3383 FIXME("(%p): stub!\n",This);
3384 return E_NOTIMPL;
3387 /* ITypeLib::GetDocumentation
3389 * Retrieves the library's documentation string, the complete Help file name
3390 * and path, and the context identifier for the library Help topic in the Help
3391 * file.
3393 * On a successful return all non-null BSTR pointers will have been set,
3394 * possibly to NULL.
3396 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3397 ITypeLib2 *iface,
3398 INT index,
3399 BSTR *pBstrName,
3400 BSTR *pBstrDocString,
3401 DWORD *pdwHelpContext,
3402 BSTR *pBstrHelpFile)
3404 ICOM_THIS( ITypeLibImpl, iface);
3406 HRESULT result = E_INVALIDARG;
3408 ITypeInfo *pTInfo;
3411 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3412 This, index,
3413 pBstrName, pBstrDocString,
3414 pdwHelpContext, pBstrHelpFile);
3416 if(index<0)
3418 /* documentation for the typelib */
3419 if(pBstrName)
3421 if (This->Name)
3422 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3423 else
3424 *pBstrName = NULL;
3426 if(pBstrDocString)
3428 if (This->DocString)
3429 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3430 else if (This->Name)
3431 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3432 else
3433 *pBstrDocString = NULL;
3435 if(pdwHelpContext)
3437 *pdwHelpContext = This->dwHelpContext;
3439 if(pBstrHelpFile)
3441 if (This->HelpFile)
3442 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3443 else
3444 *pBstrHelpFile = NULL;
3447 result = S_OK;
3449 else
3451 /* for a typeinfo */
3452 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3454 if(SUCCEEDED(result))
3456 result = ITypeInfo_GetDocumentation(pTInfo,
3457 MEMBERID_NIL,
3458 pBstrName,
3459 pBstrDocString,
3460 pdwHelpContext, pBstrHelpFile);
3462 ITypeInfo_Release(pTInfo);
3465 return result;
3466 memerr3:
3467 if (pBstrDocString) SysFreeString (*pBstrDocString);
3468 memerr2:
3469 if (pBstrName) SysFreeString (*pBstrName);
3470 memerr1:
3471 return STG_E_INSUFFICIENTMEMORY;
3474 /* ITypeLib::IsName
3476 * Indicates whether a passed-in string contains the name of a type or member
3477 * described in the library.
3480 static HRESULT WINAPI ITypeLib2_fnIsName(
3481 ITypeLib2 *iface,
3482 LPOLESTR szNameBuf,
3483 ULONG lHashVal,
3484 BOOL *pfName)
3486 ICOM_THIS( ITypeLibImpl, iface);
3487 ITypeInfoImpl *pTInfo;
3488 TLBFuncDesc *pFInfo;
3489 TLBVarDesc *pVInfo;
3490 int i;
3491 UINT nNameBufLen = SysStringLen(szNameBuf);
3493 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3494 pfName);
3496 *pfName=TRUE;
3497 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3498 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3499 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3500 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3501 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3502 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3503 goto ITypeLib2_fnIsName_exit;
3505 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3506 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3509 *pfName=FALSE;
3511 ITypeLib2_fnIsName_exit:
3512 TRACE("(%p)slow! search for %s: %s found!\n", This,
3513 debugstr_w(szNameBuf), *pfName?"NOT":"");
3515 return S_OK;
3518 /* ITypeLib::FindName
3520 * Finds occurrences of a type description in a type library. This may be used
3521 * to quickly verify that a name exists in a type library.
3524 static HRESULT WINAPI ITypeLib2_fnFindName(
3525 ITypeLib2 *iface,
3526 LPOLESTR szNameBuf,
3527 ULONG lHashVal,
3528 ITypeInfo **ppTInfo,
3529 MEMBERID *rgMemId,
3530 UINT16 *pcFound)
3532 ICOM_THIS( ITypeLibImpl, iface);
3533 ITypeInfoImpl *pTInfo;
3534 TLBFuncDesc *pFInfo;
3535 TLBVarDesc *pVInfo;
3536 int i,j = 0;
3538 UINT nNameBufLen = SysStringLen(szNameBuf);
3540 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3541 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3542 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3543 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3544 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3545 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3546 goto ITypeLib2_fnFindName_exit;
3548 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3549 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3550 continue;
3551 ITypeLib2_fnFindName_exit:
3552 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3553 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3554 j++;
3556 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3557 This, *pcFound, debugstr_w(szNameBuf), j);
3559 *pcFound=j;
3561 return S_OK;
3564 /* ITypeLib::ReleaseTLibAttr
3566 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3569 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3570 ITypeLib2 *iface,
3571 TLIBATTR *pTLibAttr)
3573 ICOM_THIS( ITypeLibImpl, iface);
3574 TRACE("freeing (%p)\n",This);
3575 HeapFree(GetProcessHeap(),0,pTLibAttr);
3579 /* ITypeLib2::GetCustData
3581 * gets the custom data
3583 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3584 ITypeLib2 * iface,
3585 REFGUID guid,
3586 VARIANT *pVarVal)
3588 ICOM_THIS( ITypeLibImpl, iface);
3589 TLBCustData *pCData;
3591 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3593 if( IsEqualIID(guid, &pCData->guid)) break;
3596 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3598 if(pCData)
3600 VariantInit( pVarVal);
3601 VariantCopy( pVarVal, &pCData->data);
3602 return S_OK;
3604 return E_INVALIDARG; /* FIXME: correct? */
3607 /* ITypeLib2::GetLibStatistics
3609 * Returns statistics about a type library that are required for efficient
3610 * sizing of hash tables.
3613 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3614 ITypeLib2 * iface,
3615 ULONG *pcUniqueNames,
3616 ULONG *pcchUniqueNames)
3618 ICOM_THIS( ITypeLibImpl, iface);
3620 FIXME("(%p): stub!\n", This);
3622 if(pcUniqueNames) *pcUniqueNames=1;
3623 if(pcchUniqueNames) *pcchUniqueNames=1;
3624 return S_OK;
3627 /* ITypeLib2::GetDocumentation2
3629 * Retrieves the library's documentation string, the complete Help file name
3630 * and path, the localization context to use, and the context ID for the
3631 * library Help topic in the Help file.
3634 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3635 ITypeLib2 * iface,
3636 INT index,
3637 LCID lcid,
3638 BSTR *pbstrHelpString,
3639 DWORD *pdwHelpStringContext,
3640 BSTR *pbstrHelpStringDll)
3642 ICOM_THIS( ITypeLibImpl, iface);
3643 HRESULT result;
3644 ITypeInfo *pTInfo;
3646 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3648 /* the help string should be obtained from the helpstringdll,
3649 * using the _DLLGetDocumentation function, based on the supplied
3650 * lcid. Nice to do sometime...
3652 if(index<0)
3654 /* documentation for the typelib */
3655 if(pbstrHelpString)
3656 *pbstrHelpString=SysAllocString(This->DocString);
3657 if(pdwHelpStringContext)
3658 *pdwHelpStringContext=This->dwHelpContext;
3659 if(pbstrHelpStringDll)
3660 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3662 result = S_OK;
3664 else
3666 /* for a typeinfo */
3667 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3669 if(SUCCEEDED(result))
3671 ITypeInfo2 * pTInfo2;
3672 result = ITypeInfo_QueryInterface(pTInfo,
3673 &IID_ITypeInfo2,
3674 (LPVOID*) &pTInfo2);
3676 if(SUCCEEDED(result))
3678 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3679 MEMBERID_NIL,
3680 lcid,
3681 pbstrHelpString,
3682 pdwHelpStringContext,
3683 pbstrHelpStringDll);
3685 ITypeInfo2_Release(pTInfo2);
3688 ITypeInfo_Release(pTInfo);
3691 return result;
3694 /* ITypeLib2::GetAllCustData
3696 * Gets all custom data items for the library.
3699 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3700 ITypeLib2 * iface,
3701 CUSTDATA *pCustData)
3703 ICOM_THIS( ITypeLibImpl, iface);
3704 TLBCustData *pCData;
3705 int i;
3706 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3707 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3708 if(pCustData->prgCustData ){
3709 pCustData->cCustData=This->ctCustData;
3710 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3711 pCustData->prgCustData[i].guid=pCData->guid;
3712 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3714 }else{
3715 ERR(" OUT OF MEMORY! \n");
3716 return E_OUTOFMEMORY;
3718 return S_OK;
3721 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3722 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3723 ITypeLib2_fnQueryInterface,
3724 ITypeLib2_fnAddRef,
3725 ITypeLib2_fnRelease,
3726 ITypeLib2_fnGetTypeInfoCount,
3727 ITypeLib2_fnGetTypeInfo,
3728 ITypeLib2_fnGetTypeInfoType,
3729 ITypeLib2_fnGetTypeInfoOfGuid,
3730 ITypeLib2_fnGetLibAttr,
3731 ITypeLib2_fnGetTypeComp,
3732 ITypeLib2_fnGetDocumentation,
3733 ITypeLib2_fnIsName,
3734 ITypeLib2_fnFindName,
3735 ITypeLib2_fnReleaseTLibAttr,
3737 ITypeLib2_fnGetCustData,
3738 ITypeLib2_fnGetLibStatistics,
3739 ITypeLib2_fnGetDocumentation2,
3740 ITypeLib2_fnGetAllCustData
3743 /*================== ITypeInfo(2) Methods ===================================*/
3744 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3746 ITypeInfoImpl * pTypeInfoImpl;
3748 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3749 if (pTypeInfoImpl)
3751 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3752 pTypeInfoImpl->ref=1;
3754 TRACE("(%p)\n", pTypeInfoImpl);
3755 return (ITypeInfo2*) pTypeInfoImpl;
3758 /* ITypeInfo::QueryInterface
3760 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3761 ITypeInfo2 *iface,
3762 REFIID riid,
3763 VOID **ppvObject)
3765 ICOM_THIS( ITypeLibImpl, iface);
3767 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3769 *ppvObject=NULL;
3770 if(IsEqualIID(riid, &IID_IUnknown) ||
3771 IsEqualIID(riid,&IID_ITypeInfo)||
3772 IsEqualIID(riid,&IID_ITypeInfo2))
3773 *ppvObject = This;
3775 if(*ppvObject){
3776 ITypeInfo_AddRef(iface);
3777 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3778 return S_OK;
3780 TRACE("-- Interface: E_NOINTERFACE\n");
3781 return E_NOINTERFACE;
3784 /* ITypeInfo::AddRef
3786 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3788 ICOM_THIS( ITypeInfoImpl, iface);
3790 ++(This->ref);
3792 TRACE("(%p)->ref is %u\n",This, This->ref);
3793 return This->ref;
3796 /* ITypeInfo::Release
3798 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3800 ICOM_THIS( ITypeInfoImpl, iface);
3802 --(This->ref);
3804 TRACE("(%p)->(%u)\n",This, This->ref);
3806 if (!This->ref)
3808 FIXME("destroy child objects\n");
3810 TRACE("destroying ITypeInfo(%p)\n",This);
3811 if (This->Name)
3813 SysFreeString(This->Name);
3814 This->Name = 0;
3817 if (This->DocString)
3819 SysFreeString(This->DocString);
3820 This->DocString = 0;
3823 if (This->next)
3825 ITypeInfo_Release((ITypeInfo*)This->next);
3828 HeapFree(GetProcessHeap(),0,This);
3829 return 0;
3831 return This->ref;
3834 /* ITypeInfo::GetTypeAttr
3836 * Retrieves a TYPEATTR structure that contains the attributes of the type
3837 * description.
3840 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3841 LPTYPEATTR *ppTypeAttr)
3843 ICOM_THIS( ITypeInfoImpl, iface);
3844 TRACE("(%p)\n",This);
3845 /* FIXME: must do a copy here */
3846 *ppTypeAttr=&This->TypeAttr;
3847 return S_OK;
3850 /* ITypeInfo::GetTypeComp
3852 * Retrieves the ITypeComp interface for the type description, which enables a
3853 * client compiler to bind to the type description's members.
3856 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3857 ITypeComp * *ppTComp)
3859 ICOM_THIS( ITypeInfoImpl, iface);
3860 FIXME("(%p) stub!\n", This);
3861 return S_OK;
3864 /* ITypeInfo::GetFuncDesc
3866 * Retrieves the FUNCDESC structure that contains information about a
3867 * specified function.
3870 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3871 LPFUNCDESC *ppFuncDesc)
3873 ICOM_THIS( ITypeInfoImpl, iface);
3874 int i;
3875 TLBFuncDesc * pFDesc;
3876 TRACE("(%p) index %d\n", This, index);
3877 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3879 if(pFDesc){
3880 /* FIXME: must do a copy here */
3881 *ppFuncDesc=&pFDesc->funcdesc;
3882 return S_OK;
3884 return E_INVALIDARG;
3887 /* ITypeInfo::GetVarDesc
3889 * Retrieves a VARDESC structure that describes the specified variable.
3892 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3893 LPVARDESC *ppVarDesc)
3895 ICOM_THIS( ITypeInfoImpl, iface);
3896 int i;
3897 TLBVarDesc * pVDesc;
3898 TRACE("(%p) index %d\n", This, index);
3899 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3901 if(pVDesc){
3902 /* FIXME: must do a copy here */
3903 *ppVarDesc=&pVDesc->vardesc;
3904 return S_OK;
3906 return E_INVALIDARG;
3909 /* ITypeInfo_GetNames
3911 * Retrieves the variable with the specified member ID (or the name of the
3912 * property or method and its parameters) that correspond to the specified
3913 * function ID.
3915 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3916 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3918 ICOM_THIS( ITypeInfoImpl, iface);
3919 TLBFuncDesc * pFDesc;
3920 TLBVarDesc * pVDesc;
3921 int i;
3922 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3923 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3924 if(pFDesc)
3926 /* function found, now return function and parameter names */
3927 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3929 if(!i)
3930 *rgBstrNames=SysAllocString(pFDesc->Name);
3931 else
3932 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3934 *pcNames=i;
3936 else
3938 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3939 if(pVDesc)
3941 *rgBstrNames=SysAllocString(pVDesc->Name);
3942 *pcNames=1;
3944 else
3946 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3948 /* recursive search */
3949 ITypeInfo *pTInfo;
3950 HRESULT result;
3951 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3952 &pTInfo);
3953 if(SUCCEEDED(result))
3955 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3956 ITypeInfo_Release(pTInfo);
3957 return result;
3959 WARN("Could not search inherited interface!\n");
3961 else
3963 WARN("no names found\n");
3965 *pcNames=0;
3966 return TYPE_E_ELEMENTNOTFOUND;
3969 return S_OK;
3973 /* ITypeInfo::GetRefTypeOfImplType
3975 * If a type description describes a COM class, it retrieves the type
3976 * description of the implemented interface types. For an interface,
3977 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3978 * if any exist.
3981 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3982 ITypeInfo2 *iface,
3983 UINT index,
3984 HREFTYPE *pRefType)
3986 ICOM_THIS( ITypeInfoImpl, iface);
3987 int(i);
3988 TLBImplType *pImpl = This->impltypelist;
3990 TRACE("(%p) index %d\n", This, index);
3991 dump_TypeInfo(This);
3993 if(index==(UINT)-1)
3995 /* only valid on dual interfaces;
3996 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3998 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4000 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4001 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4003 *pRefType = -1;
4005 else
4007 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4008 *pRefType = pImpl->hRef;
4011 else
4013 /* get element n from linked list */
4014 for(i=0; pImpl && i<index; i++)
4016 pImpl = pImpl->next;
4019 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4021 *pRefType = pImpl->hRef;
4023 TRACE("-- 0x%08lx\n", pImpl->hRef );
4026 return S_OK;
4030 /* ITypeInfo::GetImplTypeFlags
4032 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4033 * or base interface in a type description.
4035 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4036 UINT index, INT *pImplTypeFlags)
4038 ICOM_THIS( ITypeInfoImpl, iface);
4039 int i;
4040 TLBImplType *pImpl;
4042 TRACE("(%p) index %d\n", This, index);
4043 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4044 i++, pImpl=pImpl->next)
4046 if(i==index && pImpl){
4047 *pImplTypeFlags=pImpl->implflags;
4048 return S_OK;
4050 *pImplTypeFlags=0;
4051 return TYPE_E_ELEMENTNOTFOUND;
4054 /* GetIDsOfNames
4055 * Maps between member names and member IDs, and parameter names and
4056 * parameter IDs.
4058 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4059 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4061 ICOM_THIS( ITypeInfoImpl, iface);
4062 TLBFuncDesc * pFDesc;
4063 TLBVarDesc * pVDesc;
4064 HRESULT ret=S_OK;
4066 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4067 cNames);
4068 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4069 int i, j;
4070 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4071 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4072 for(i=1; i < cNames; i++){
4073 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4074 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4075 break;
4076 if( j<pFDesc->funcdesc.cParams)
4077 pMemId[i]=j;
4078 else
4079 ret=DISP_E_UNKNOWNNAME;
4081 return ret;
4084 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4085 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4086 if(cNames) *pMemId=pVDesc->vardesc.memid;
4087 return ret;
4090 /* not found, see if this is and interface with an inheritance */
4091 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
4092 This->TypeAttr.cImplTypes ){
4093 /* recursive search */
4094 ITypeInfo *pTInfo;
4095 ret=ITypeInfo_GetRefTypeInfo(iface,
4096 This->impltypelist->hRef, &pTInfo);
4097 if(SUCCEEDED(ret)){
4098 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4099 ITypeInfo_Release(pTInfo);
4100 return ret;
4102 WARN("Could not search inherited interface!\n");
4103 } else
4104 WARN("no names found\n");
4105 return DISP_E_UNKNOWNNAME;
4108 /* ITypeInfo::Invoke
4110 * Invokes a method, or accesses a property of an object, that implements the
4111 * interface described by the type description.
4113 DWORD
4114 _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
4115 DWORD res;
4117 if (TRACE_ON(ole)) {
4118 int i;
4119 MESSAGE("Calling %p(",func);
4120 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
4121 MESSAGE(")\n");
4124 switch (callconv) {
4125 case CC_STDCALL:
4127 switch (nrargs) {
4128 case 0: {
4129 DWORD (WINAPI *xfunc)() = func;
4130 res = xfunc();
4131 break;
4133 case 1: {
4134 DWORD (WINAPI *xfunc)(DWORD) = func;
4135 res = xfunc(args[0]);
4136 break;
4138 case 2: {
4139 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
4140 res = xfunc(args[0],args[1]);
4141 break;
4143 case 3: {
4144 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
4145 res = xfunc(args[0],args[1],args[2]);
4146 break;
4148 case 4: {
4149 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD) = func;
4150 res = xfunc(args[0],args[1],args[2],args[3]);
4151 break;
4153 case 5: {
4154 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4155 res = xfunc(args[0],args[1],args[2],args[3],args[4]);
4156 break;
4158 case 6: {
4159 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4160 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5]);
4161 break;
4163 case 7: {
4164 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4165 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4166 break;
4168 case 8: {
4169 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4170 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4171 break;
4173 case 9: {
4174 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4175 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4176 break;
4178 default:
4179 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4180 res = -1;
4181 break;
4183 break;
4184 default:
4185 FIXME("unsupported calling convention %d\n",callconv);
4186 res = -1;
4187 break;
4189 TRACE("returns %08lx\n",res);
4190 return res;
4193 extern int const _argsize(DWORD vt);
4195 static HRESULT WINAPI ITypeInfo_fnInvoke(
4196 ITypeInfo2 *iface,
4197 VOID *pIUnk,
4198 MEMBERID memid,
4199 UINT16 dwFlags,
4200 DISPPARAMS *pDispParams,
4201 VARIANT *pVarResult,
4202 EXCEPINFO *pExcepInfo,
4203 UINT *pArgErr)
4205 ICOM_THIS( ITypeInfoImpl, iface);
4206 TLBFuncDesc * pFDesc;
4207 TLBVarDesc * pVDesc;
4208 int i;
4210 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4211 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4213 dump_DispParms(pDispParams);
4215 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4216 if (pFDesc->funcdesc.memid == memid) {
4217 if (pFDesc->funcdesc.invkind & dwFlags)
4218 break;
4220 if (pFDesc) {
4221 dump_TLBFuncDescOne(pFDesc);
4222 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4223 switch (pFDesc->funcdesc.funckind) {
4224 case FUNC_PUREVIRTUAL:
4225 case FUNC_VIRTUAL: {
4226 DWORD res;
4227 int numargs, numargs2, argspos, args2pos;
4228 DWORD *args , *args2;
4231 numargs = 1; numargs2 = 0;
4232 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4233 if (i<pDispParams->cArgs)
4234 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4235 else {
4236 numargs += 1; /* sizeof(lpvoid) */
4237 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4241 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4242 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4244 args[0] = (DWORD)pIUnk;
4245 argspos = 1; args2pos = 0;
4246 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4247 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4248 if (i<pDispParams->cArgs) {
4249 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4250 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4252 if (V_VT(arg) == tdesc->vt) {
4253 memcpy(&args[argspos],&V_UNION(arg,lVal), arglen*sizeof(DWORD));
4254 } else {
4255 if (tdesc->vt == VT_VARIANT) {
4256 memcpy(&args[argspos],arg, arglen*sizeof(DWORD));
4257 } else {
4258 ERR("Set arg %d to disparg type %d vs %d\n",i,
4259 V_VT(arg),tdesc->vt
4263 argspos += arglen;
4264 } else {
4265 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4266 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4267 /*FIXME: give pointers for the rest, so propertyget works*/
4268 args[argspos] = (DWORD)&args2[args2pos];
4270 /* If pointer to variant, pass reference it. */
4271 if ((tdesc->vt == VT_PTR) &&
4272 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4273 pVarResult
4275 args[argspos]= (DWORD)pVarResult;
4276 argspos += 1;
4277 args2pos += arglen;
4280 if (pFDesc->funcdesc.cParamsOpt)
4281 FIXME("Does not support optional parameters (%d)\n",
4282 pFDesc->funcdesc.cParamsOpt
4285 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4286 pFDesc->funcdesc.callconv,
4287 numargs,
4288 args
4290 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4291 args2pos = 0;
4292 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4293 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4294 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4295 /* If we are a pointer to a variant, we are done already */
4296 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4297 continue;
4299 VariantInit(pVarResult);
4300 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4302 if (tdesc->vt == VT_PTR)
4303 tdesc = tdesc->u.lptdesc;
4304 V_VT(pVarResult) = tdesc->vt;
4306 /* HACK: VB5 likes this.
4307 * I do not know why. There is 1 example in MSDN which uses
4308 * this which appears broken (mixes int vals and
4309 * IDispatch*.).
4311 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4312 V_VT(pVarResult) = VT_DISPATCH;
4313 TRACE("storing into variant:\n");
4314 dump_Variant(pVarResult);
4315 args2pos += arglen;
4318 HeapFree(GetProcessHeap(),0,args2);
4319 HeapFree(GetProcessHeap(),0,args);
4320 return S_OK;
4322 case FUNC_DISPATCH: {
4323 IDispatch *disp;
4324 HRESULT hr;
4326 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4327 if (hr) {
4328 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4329 return hr;
4331 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4332 hr = IDispatch_Invoke(
4333 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4334 pVarResult,pExcepInfo,pArgErr
4336 if (hr)
4337 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4338 IDispatch_Release(disp);
4339 return hr;
4341 default:
4342 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4343 return E_FAIL;
4345 } else {
4346 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4347 if (pVDesc->vardesc.memid == memid) {
4348 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4349 dump_TLBVarDesc(pVDesc);
4350 break;
4354 /* not found, look for it in inherited interfaces */
4355 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4356 /* recursive search */
4357 ITypeInfo *pTInfo;
4358 HRESULT hr;
4359 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4360 if(SUCCEEDED(hr)){
4361 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4362 ITypeInfo_Release(pTInfo);
4363 return hr;
4365 WARN("Could not search inherited interface!\n");
4367 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4368 return DISP_E_MEMBERNOTFOUND;
4371 /* ITypeInfo::GetDocumentation
4373 * Retrieves the documentation string, the complete Help file name and path,
4374 * and the context ID for the Help topic for a specified type description.
4376 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4377 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4378 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4380 ICOM_THIS( ITypeInfoImpl, iface);
4381 TLBFuncDesc * pFDesc;
4382 TLBVarDesc * pVDesc;
4383 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4384 " HelpContext(%p) HelpFile(%p)\n",
4385 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4386 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4387 if(pBstrName)
4388 *pBstrName=SysAllocString(This->Name);
4389 if(pBstrDocString)
4390 *pBstrDocString=SysAllocString(This->DocString);
4391 if(pdwHelpContext)
4392 *pdwHelpContext=This->dwHelpContext;
4393 if(pBstrHelpFile)
4394 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4395 return S_OK;
4396 }else {/* for a member */
4397 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4398 if(pFDesc->funcdesc.memid==memid){
4399 if(pBstrName)
4400 *pBstrName = SysAllocString(pFDesc->Name);
4401 if(pBstrDocString)
4402 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4403 if(pdwHelpContext)
4404 *pdwHelpContext=pFDesc->helpcontext;
4405 return S_OK;
4407 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4408 if(pVDesc->vardesc.memid==memid){
4409 FIXME("Not implemented\n");
4410 return S_OK;
4413 return TYPE_E_ELEMENTNOTFOUND;
4416 /* ITypeInfo::GetDllEntry
4418 * Retrieves a description or specification of an entry point for a function
4419 * in a DLL.
4421 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4422 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4423 WORD *pwOrdinal)
4425 ICOM_THIS( ITypeInfoImpl, iface);
4426 FIXME("(%p) stub!\n", This);
4427 return E_FAIL;
4430 /* ITypeInfo::GetRefTypeInfo
4432 * If a type description references other type descriptions, it retrieves
4433 * the referenced type descriptions.
4435 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4436 ITypeInfo2 *iface,
4437 HREFTYPE hRefType,
4438 ITypeInfo **ppTInfo)
4440 ICOM_THIS( ITypeInfoImpl, iface);
4441 HRESULT result = E_FAIL;
4444 if (hRefType == -1 &&
4445 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4446 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4448 /* when we meet a DUAL dispinterface, we must create the interface
4449 * version of it.
4451 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4454 /* the interface version contains the same information as the dispinterface
4455 * copy the contents of the structs.
4457 *pTypeInfoImpl = *This;
4458 pTypeInfoImpl->ref = 1;
4460 /* change the type to interface */
4461 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4463 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4465 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4467 result = S_OK;
4469 } else {
4470 TLBRefType *pRefType;
4471 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4472 if(pRefType->reference == hRefType)
4473 break;
4475 if(!pRefType)
4476 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4477 if(pRefType && hRefType != -1) {
4478 ITypeLib *pTLib = NULL;
4480 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4481 int Index;
4482 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4483 } else {
4484 if(pRefType->pImpTLInfo->pImpTypeLib) {
4485 TRACE("typeinfo in imported typelib that is already loaded\n");
4486 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4487 ITypeLib2_AddRef((ITypeLib*) pTLib);
4488 result = S_OK;
4489 } else {
4490 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4491 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4492 pRefType->pImpTLInfo->wVersionMajor,
4493 pRefType->pImpTLInfo->wVersionMinor,
4494 pRefType->pImpTLInfo->lcid,
4495 &pTLib);
4497 if(!SUCCEEDED(result)) {
4498 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4499 result=LoadTypeLib(libnam, &pTLib);
4500 SysFreeString(libnam);
4502 if(SUCCEEDED(result)) {
4503 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4504 ITypeLib2_AddRef(pTLib);
4508 if(SUCCEEDED(result)) {
4509 if(pRefType->index == TLB_REF_USE_GUID)
4510 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4511 &pRefType->guid,
4512 ppTInfo);
4513 else
4514 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4515 ppTInfo);
4517 if (pTLib != NULL)
4518 ITypeLib2_Release(pTLib);
4522 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4523 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4524 return result;
4527 /* ITypeInfo::AddressOfMember
4529 * Retrieves the addresses of static functions or variables, such as those
4530 * defined in a DLL.
4532 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4533 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4535 ICOM_THIS( ITypeInfoImpl, iface);
4536 FIXME("(%p) stub!\n", This);
4537 return S_OK;
4540 /* ITypeInfo::CreateInstance
4542 * Creates a new instance of a type that describes a component object class
4543 * (coclass).
4545 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4546 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4548 ICOM_THIS( ITypeInfoImpl, iface);
4549 FIXME("(%p) stub!\n", This);
4550 return S_OK;
4553 /* ITypeInfo::GetMops
4555 * Retrieves marshaling information.
4557 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4558 BSTR *pBstrMops)
4560 ICOM_THIS( ITypeInfoImpl, iface);
4561 FIXME("(%p) stub!\n", This);
4562 return S_OK;
4565 /* ITypeInfo::GetContainingTypeLib
4567 * Retrieves the containing type library and the index of the type description
4568 * within that type library.
4570 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4571 ITypeLib * *ppTLib, UINT *pIndex)
4573 ICOM_THIS( ITypeInfoImpl, iface);
4574 if (!pIndex)
4575 return E_INVALIDARG;
4576 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4577 *pIndex=This->index;
4578 ITypeLib2_AddRef(*ppTLib);
4579 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4580 return S_OK;
4583 /* ITypeInfo::ReleaseTypeAttr
4585 * Releases a TYPEATTR previously returned by GetTypeAttr.
4588 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4589 TYPEATTR* pTypeAttr)
4591 ICOM_THIS( ITypeInfoImpl, iface);
4592 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4593 return S_OK;
4596 /* ITypeInfo::ReleaseFuncDesc
4598 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4600 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4601 ITypeInfo2 *iface,
4602 FUNCDESC *pFuncDesc)
4604 ICOM_THIS( ITypeInfoImpl, iface);
4605 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4606 return S_OK;
4609 /* ITypeInfo::ReleaseVarDesc
4611 * Releases a VARDESC previously returned by GetVarDesc.
4613 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4614 VARDESC *pVarDesc)
4616 ICOM_THIS( ITypeInfoImpl, iface);
4617 TRACE("(%p)->(%p)\n", This, pVarDesc);
4618 return S_OK;
4621 /* ITypeInfo2::GetTypeKind
4623 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4626 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4627 TYPEKIND *pTypeKind)
4629 ICOM_THIS( ITypeInfoImpl, iface);
4630 *pTypeKind=This->TypeAttr.typekind;
4631 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4632 return S_OK;
4635 /* ITypeInfo2::GetTypeFlags
4637 * Returns the type flags without any allocations. This returns a DWORD type
4638 * flag, which expands the type flags without growing the TYPEATTR (type
4639 * attribute).
4642 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4643 UINT *pTypeFlags)
4645 ICOM_THIS( ITypeInfoImpl, iface);
4646 *pTypeFlags=This->TypeAttr.wTypeFlags;
4647 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4648 return S_OK;
4651 /* ITypeInfo2::GetFuncIndexOfMemId
4652 * Binds to a specific member based on a known DISPID, where the member name
4653 * is not known (for example, when binding to a default member).
4656 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4657 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4659 ICOM_THIS( ITypeInfoImpl, iface);
4660 TLBFuncDesc *pFuncInfo;
4661 int i;
4662 HRESULT result;
4663 /* FIXME: should check for invKind??? */
4664 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4665 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4666 if(pFuncInfo){
4667 *pFuncIndex=i;
4668 result= S_OK;
4669 }else{
4670 *pFuncIndex=0;
4671 result=E_INVALIDARG;
4673 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4674 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4675 return result;
4678 /* TypeInfo2::GetVarIndexOfMemId
4680 * Binds to a specific member based on a known DISPID, where the member name
4681 * is not known (for example, when binding to a default member).
4684 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4685 MEMBERID memid, UINT *pVarIndex)
4687 ICOM_THIS( ITypeInfoImpl, iface);
4688 TLBVarDesc *pVarInfo;
4689 int i;
4690 HRESULT result;
4691 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4692 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4694 if(pVarInfo){
4695 *pVarIndex=i;
4696 result= S_OK;
4697 }else{
4698 *pVarIndex=0;
4699 result=E_INVALIDARG;
4701 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4702 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4703 return result;
4706 /* ITypeInfo2::GetCustData
4708 * Gets the custom data
4710 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4711 ITypeInfo2 * iface,
4712 REFGUID guid,
4713 VARIANT *pVarVal)
4715 ICOM_THIS( ITypeInfoImpl, iface);
4716 TLBCustData *pCData;
4718 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4719 if( IsEqualIID(guid, &pCData->guid)) break;
4721 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4723 if(pCData)
4725 VariantInit( pVarVal);
4726 VariantCopy( pVarVal, &pCData->data);
4727 return S_OK;
4729 return E_INVALIDARG; /* FIXME: correct? */
4732 /* ITypeInfo2::GetFuncCustData
4734 * Gets the custom data
4736 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4737 ITypeInfo2 * iface,
4738 UINT index,
4739 REFGUID guid,
4740 VARIANT *pVarVal)
4742 ICOM_THIS( ITypeInfoImpl, iface);
4743 TLBCustData *pCData=NULL;
4744 TLBFuncDesc * pFDesc;
4745 int i;
4746 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4747 pFDesc=pFDesc->next);
4749 if(pFDesc)
4750 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4751 if( IsEqualIID(guid, &pCData->guid)) break;
4753 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4755 if(pCData){
4756 VariantInit( pVarVal);
4757 VariantCopy( pVarVal, &pCData->data);
4758 return S_OK;
4760 return E_INVALIDARG; /* FIXME: correct? */
4763 /* ITypeInfo2::GetParamCustData
4765 * Gets the custom data
4767 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4768 ITypeInfo2 * iface,
4769 UINT indexFunc,
4770 UINT indexParam,
4771 REFGUID guid,
4772 VARIANT *pVarVal)
4774 ICOM_THIS( ITypeInfoImpl, iface);
4775 TLBCustData *pCData=NULL;
4776 TLBFuncDesc * pFDesc;
4777 int i;
4779 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4781 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4782 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4783 pCData = pCData->next)
4784 if( IsEqualIID(guid, &pCData->guid)) break;
4786 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4788 if(pCData)
4790 VariantInit( pVarVal);
4791 VariantCopy( pVarVal, &pCData->data);
4792 return S_OK;
4794 return E_INVALIDARG; /* FIXME: correct? */
4797 /* ITypeInfo2::GetVarCustData
4799 * Gets the custom data
4801 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4802 ITypeInfo2 * iface,
4803 UINT index,
4804 REFGUID guid,
4805 VARIANT *pVarVal)
4807 ICOM_THIS( ITypeInfoImpl, iface);
4808 TLBCustData *pCData=NULL;
4809 TLBVarDesc * pVDesc;
4810 int i;
4812 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4814 if(pVDesc)
4816 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4818 if( IsEqualIID(guid, &pCData->guid)) break;
4822 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4824 if(pCData)
4826 VariantInit( pVarVal);
4827 VariantCopy( pVarVal, &pCData->data);
4828 return S_OK;
4830 return E_INVALIDARG; /* FIXME: correct? */
4833 /* ITypeInfo2::GetImplCustData
4835 * Gets the custom data
4837 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4838 ITypeInfo2 * iface,
4839 UINT index,
4840 REFGUID guid,
4841 VARIANT *pVarVal)
4843 ICOM_THIS( ITypeInfoImpl, iface);
4844 TLBCustData *pCData=NULL;
4845 TLBImplType * pRDesc;
4846 int i;
4848 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4850 if(pRDesc)
4852 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4854 if( IsEqualIID(guid, &pCData->guid)) break;
4858 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4860 if(pCData)
4862 VariantInit( pVarVal);
4863 VariantCopy( pVarVal, &pCData->data);
4864 return S_OK;
4866 return E_INVALIDARG; /* FIXME: correct? */
4869 /* ITypeInfo2::GetDocumentation2
4871 * Retrieves the documentation string, the complete Help file name and path,
4872 * the localization context to use, and the context ID for the library Help
4873 * topic in the Help file.
4876 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4877 ITypeInfo2 * iface,
4878 MEMBERID memid,
4879 LCID lcid,
4880 BSTR *pbstrHelpString,
4881 DWORD *pdwHelpStringContext,
4882 BSTR *pbstrHelpStringDll)
4884 ICOM_THIS( ITypeInfoImpl, iface);
4885 TLBFuncDesc * pFDesc;
4886 TLBVarDesc * pVDesc;
4887 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4888 "HelpStringContext(%p) HelpStringDll(%p)\n",
4889 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4890 pbstrHelpStringDll );
4891 /* the help string should be obtained from the helpstringdll,
4892 * using the _DLLGetDocumentation function, based on the supplied
4893 * lcid. Nice to do sometime...
4895 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4896 if(pbstrHelpString)
4897 *pbstrHelpString=SysAllocString(This->Name);
4898 if(pdwHelpStringContext)
4899 *pdwHelpStringContext=This->dwHelpStringContext;
4900 if(pbstrHelpStringDll)
4901 *pbstrHelpStringDll=
4902 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4903 return S_OK;
4904 }else {/* for a member */
4905 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4906 if(pFDesc->funcdesc.memid==memid){
4907 if(pbstrHelpString)
4908 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4909 if(pdwHelpStringContext)
4910 *pdwHelpStringContext=pFDesc->HelpStringContext;
4911 if(pbstrHelpStringDll)
4912 *pbstrHelpStringDll=
4913 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4914 return S_OK;
4916 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4917 if(pVDesc->vardesc.memid==memid){
4918 if(pbstrHelpString)
4919 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4920 if(pdwHelpStringContext)
4921 *pdwHelpStringContext=pVDesc->HelpStringContext;
4922 if(pbstrHelpStringDll)
4923 *pbstrHelpStringDll=
4924 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4925 return S_OK;
4928 return TYPE_E_ELEMENTNOTFOUND;
4931 /* ITypeInfo2::GetAllCustData
4933 * Gets all custom data items for the Type info.
4936 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4937 ITypeInfo2 * iface,
4938 CUSTDATA *pCustData)
4940 ICOM_THIS( ITypeInfoImpl, iface);
4941 TLBCustData *pCData;
4942 int i;
4944 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4946 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4947 if(pCustData->prgCustData ){
4948 pCustData->cCustData=This->ctCustData;
4949 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4950 pCustData->prgCustData[i].guid=pCData->guid;
4951 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4953 }else{
4954 ERR(" OUT OF MEMORY! \n");
4955 return E_OUTOFMEMORY;
4957 return S_OK;
4960 /* ITypeInfo2::GetAllFuncCustData
4962 * Gets all custom data items for the specified Function
4965 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4966 ITypeInfo2 * iface,
4967 UINT index,
4968 CUSTDATA *pCustData)
4970 ICOM_THIS( ITypeInfoImpl, iface);
4971 TLBCustData *pCData;
4972 TLBFuncDesc * pFDesc;
4973 int i;
4974 TRACE("(%p) index %d\n", This, index);
4975 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4976 pFDesc=pFDesc->next)
4978 if(pFDesc){
4979 pCustData->prgCustData =
4980 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4981 if(pCustData->prgCustData ){
4982 pCustData->cCustData=pFDesc->ctCustData;
4983 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4984 pCData = pCData->next){
4985 pCustData->prgCustData[i].guid=pCData->guid;
4986 VariantCopy(& pCustData->prgCustData[i].varValue,
4987 & pCData->data);
4989 }else{
4990 ERR(" OUT OF MEMORY! \n");
4991 return E_OUTOFMEMORY;
4993 return S_OK;
4995 return TYPE_E_ELEMENTNOTFOUND;
4998 /* ITypeInfo2::GetAllParamCustData
5000 * Gets all custom data items for the Functions
5003 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5004 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5006 ICOM_THIS( ITypeInfoImpl, iface);
5007 TLBCustData *pCData=NULL;
5008 TLBFuncDesc * pFDesc;
5009 int i;
5010 TRACE("(%p) index %d\n", This, indexFunc);
5011 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5012 pFDesc=pFDesc->next)
5014 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5015 pCustData->prgCustData =
5016 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5017 sizeof(CUSTDATAITEM));
5018 if(pCustData->prgCustData ){
5019 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5020 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5021 pCData; i++, pCData = pCData->next){
5022 pCustData->prgCustData[i].guid=pCData->guid;
5023 VariantCopy(& pCustData->prgCustData[i].varValue,
5024 & pCData->data);
5026 }else{
5027 ERR(" OUT OF MEMORY! \n");
5028 return E_OUTOFMEMORY;
5030 return S_OK;
5032 return TYPE_E_ELEMENTNOTFOUND;
5035 /* ITypeInfo2::GetAllVarCustData
5037 * Gets all custom data items for the specified Variable
5040 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5041 UINT index, CUSTDATA *pCustData)
5043 ICOM_THIS( ITypeInfoImpl, iface);
5044 TLBCustData *pCData;
5045 TLBVarDesc * pVDesc;
5046 int i;
5047 TRACE("(%p) index %d\n", This, index);
5048 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5049 pVDesc=pVDesc->next)
5051 if(pVDesc){
5052 pCustData->prgCustData =
5053 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5054 if(pCustData->prgCustData ){
5055 pCustData->cCustData=pVDesc->ctCustData;
5056 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5057 pCData = pCData->next){
5058 pCustData->prgCustData[i].guid=pCData->guid;
5059 VariantCopy(& pCustData->prgCustData[i].varValue,
5060 & pCData->data);
5062 }else{
5063 ERR(" OUT OF MEMORY! \n");
5064 return E_OUTOFMEMORY;
5066 return S_OK;
5068 return TYPE_E_ELEMENTNOTFOUND;
5071 /* ITypeInfo2::GetAllImplCustData
5073 * Gets all custom data items for the specified implementation type
5076 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5077 ITypeInfo2 * iface,
5078 UINT index,
5079 CUSTDATA *pCustData)
5081 ICOM_THIS( ITypeInfoImpl, iface);
5082 TLBCustData *pCData;
5083 TLBImplType * pRDesc;
5084 int i;
5085 TRACE("(%p) index %d\n", This, index);
5086 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5087 pRDesc=pRDesc->next)
5089 if(pRDesc){
5090 pCustData->prgCustData =
5091 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5092 if(pCustData->prgCustData ){
5093 pCustData->cCustData=pRDesc->ctCustData;
5094 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5095 pCData = pCData->next){
5096 pCustData->prgCustData[i].guid=pCData->guid;
5097 VariantCopy(& pCustData->prgCustData[i].varValue,
5098 & pCData->data);
5100 }else{
5101 ERR(" OUT OF MEMORY! \n");
5102 return E_OUTOFMEMORY;
5104 return S_OK;
5106 return TYPE_E_ELEMENTNOTFOUND;
5109 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5111 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5113 ITypeInfo_fnQueryInterface,
5114 ITypeInfo_fnAddRef,
5115 ITypeInfo_fnRelease,
5117 ITypeInfo_fnGetTypeAttr,
5118 ITypeInfo_fnGetTypeComp,
5119 ITypeInfo_fnGetFuncDesc,
5120 ITypeInfo_fnGetVarDesc,
5121 ITypeInfo_fnGetNames,
5122 ITypeInfo_fnGetRefTypeOfImplType,
5123 ITypeInfo_fnGetImplTypeFlags,
5124 ITypeInfo_fnGetIDsOfNames,
5125 ITypeInfo_fnInvoke,
5126 ITypeInfo_fnGetDocumentation,
5127 ITypeInfo_fnGetDllEntry,
5128 ITypeInfo_fnGetRefTypeInfo,
5129 ITypeInfo_fnAddressOfMember,
5130 ITypeInfo_fnCreateInstance,
5131 ITypeInfo_fnGetMops,
5132 ITypeInfo_fnGetContainingTypeLib,
5133 ITypeInfo_fnReleaseTypeAttr,
5134 ITypeInfo_fnReleaseFuncDesc,
5135 ITypeInfo_fnReleaseVarDesc,
5137 ITypeInfo2_fnGetTypeKind,
5138 ITypeInfo2_fnGetTypeFlags,
5139 ITypeInfo2_fnGetFuncIndexOfMemId,
5140 ITypeInfo2_fnGetVarIndexOfMemId,
5141 ITypeInfo2_fnGetCustData,
5142 ITypeInfo2_fnGetFuncCustData,
5143 ITypeInfo2_fnGetParamCustData,
5144 ITypeInfo2_fnGetVarCustData,
5145 ITypeInfo2_fnGetImplTypeCustData,
5146 ITypeInfo2_fnGetDocumentation2,
5147 ITypeInfo2_fnGetAllCustData,
5148 ITypeInfo2_fnGetAllFuncCustData,
5149 ITypeInfo2_fnGetAllParamCustData,
5150 ITypeInfo2_fnGetAllVarCustData,
5151 ITypeInfo2_fnGetAllImplTypeCustData,