Add a generic TYPEDESC VT to VARIANT VT mapper so we can use the
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blobc38c9d2ef21e0e21df5d6653262a74af148ec2e2
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
47 * behaviour.
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
55 #include "config.h"
56 #include "wine/port.h"
58 #include <stdlib.h>
59 #include <string.h>
60 #include <stdarg.h>
61 #include <stdio.h>
62 #include <ctype.h>
64 #define COBJMACROS
65 #define NONAMELESSUNION
66 #define NONAMELESSSTRUCT
68 #include "winerror.h"
69 #include "windef.h"
70 #include "winbase.h"
71 #include "winnls.h"
72 #include "winreg.h"
73 #include "winuser.h"
75 #include "wine/unicode.h"
76 #include "objbase.h"
77 #include "typelib.h"
78 #include "wine/debug.h"
79 #include "variant.h"
81 WINE_DEFAULT_DEBUG_CHANNEL(ole);
82 WINE_DECLARE_DEBUG_CHANNEL(typelib);
84 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
85 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
87 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt);
89 /****************************************************************************
90 * FromLExxx
92 * Takes p_iVal (which is in little endian) and returns it
93 * in the host machine's byte order.
95 #ifdef WORDS_BIGENDIAN
96 static WORD FromLEWord(WORD p_iVal)
98 return (((p_iVal & 0x00FF) << 8) |
99 ((p_iVal & 0xFF00) >> 8));
103 static DWORD FromLEDWord(DWORD p_iVal)
105 return (((p_iVal & 0x000000FF) << 24) |
106 ((p_iVal & 0x0000FF00) << 8) |
107 ((p_iVal & 0x00FF0000) >> 8) |
108 ((p_iVal & 0xFF000000) >> 24));
110 #else
111 #define FromLEWord(X) (X)
112 #define FromLEDWord(X) (X)
113 #endif
116 /****************************************************************************
117 * FromLExxx
119 * Fix byte order in any structure if necessary
121 #ifdef WORDS_BIGENDIAN
122 static void FromLEWords(void *p_Val, int p_iSize)
124 WORD *Val = p_Val;
126 p_iSize /= sizeof(WORD);
128 while (p_iSize) {
129 *Val = FromLEWord(*Val);
130 Val++;
131 p_iSize--;
136 static void FromLEDWords(void *p_Val, int p_iSize)
138 DWORD *Val = p_Val;
140 p_iSize /= sizeof(DWORD);
142 while (p_iSize) {
143 *Val = FromLEDWord(*Val);
144 Val++;
145 p_iSize--;
148 #else
149 #define FromLEWords(X,Y) /*nothing*/
150 #define FromLEDWords(X,Y) /*nothing*/
151 #endif
153 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
154 /* buffer must be at least 60 characters long */
155 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
157 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
158 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
160 memcpy( buffer, TypelibW, sizeof(TypelibW) );
161 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
162 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
163 return buffer;
166 /* get the path of an interface key, in the form "Interface\\<guid>" */
167 /* buffer must be at least 50 characters long */
168 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
170 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
172 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
173 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
174 return buffer;
177 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
178 /* buffer must be at least 16 characters long */
179 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
181 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
182 static const WCHAR win16W[] = {'w','i','n','1','6',0};
183 static const WCHAR win32W[] = {'w','i','n','3','2',0};
185 sprintfW( buffer, LcidFormatW, lcid );
186 switch(syskind)
188 case SYS_WIN16: strcatW( buffer, win16W ); break;
189 case SYS_WIN32: strcatW( buffer, win32W ); break;
190 default:
191 TRACE("Typelib is for unsupported syskind %i\n", syskind);
192 return NULL;
194 return buffer;
197 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
200 /****************************************************************************
201 * QueryPathOfRegTypeLib [OLEAUT32.164]
203 * Gets the path to a registered type library.
205 * PARAMS
206 * guid [I] referenced guid
207 * wMaj [I] major version
208 * wMin [I] minor version
209 * lcid [I] locale id
210 * path [O] path of typelib
212 * RETURNS
213 * Success: S_OK.
214 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
215 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
216 * opened.
218 HRESULT WINAPI QueryPathOfRegTypeLib(
219 REFGUID guid,
220 WORD wMaj,
221 WORD wMin,
222 LCID lcid,
223 LPBSTR path )
225 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
226 LCID myLCID = lcid;
227 HKEY hkey;
228 WCHAR buffer[60];
229 WCHAR Path[MAX_PATH];
230 LONG res;
232 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
234 get_typelib_key( guid, wMaj, wMin, buffer );
236 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
237 if (res == ERROR_FILE_NOT_FOUND)
239 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
240 return TYPE_E_LIBNOTREGISTERED;
242 else if (res != ERROR_SUCCESS)
244 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
245 return TYPE_E_REGISTRYACCESS;
248 while (hr != S_OK)
250 DWORD dwPathLen = sizeof(Path);
252 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
254 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
256 if (!lcid)
257 break;
258 else if (myLCID == lcid)
260 /* try with sub-langid */
261 myLCID = SUBLANGID(lcid);
263 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
265 /* try with system langid */
266 myLCID = 0;
268 else
270 break;
273 else
275 *path = SysAllocString( Path );
276 hr = S_OK;
279 RegCloseKey( hkey );
280 TRACE_(typelib)("-- 0x%08lx\n", hr);
281 return hr;
284 /******************************************************************************
285 * CreateTypeLib [OLEAUT32.160] creates a typelib
287 * RETURNS
288 * Success: S_OK
289 * Failure: Status
291 HRESULT WINAPI CreateTypeLib(
292 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
294 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
295 return E_FAIL;
298 /******************************************************************************
299 * LoadTypeLib [OLEAUT32.161]
301 * Loads a type library
303 * PARAMS
304 * szFile [I] Name of file to load from.
305 * pptLib [O] Pointer that receives ITypeLib object on success.
307 * RETURNS
308 * Success: S_OK
309 * Failure: Status
311 * SEE
312 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
314 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
316 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
317 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
320 /******************************************************************************
321 * LoadTypeLibEx [OLEAUT32.183]
323 * Loads and optionally registers a type library
325 * RETURNS
326 * Success: S_OK
327 * Failure: Status
329 HRESULT WINAPI LoadTypeLibEx(
330 LPCOLESTR szFile, /* [in] Name of file to load from */
331 REGKIND regkind, /* [in] Specify kind of registration */
332 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
334 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
335 WCHAR *pIndexStr;
336 HRESULT res;
337 INT index = 1;
339 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
341 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
342 memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR));
344 *pptLib = NULL;
345 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
346 NULL)) {
348 /* Look for a trailing '\\' followed by an index */
349 pIndexStr = strrchrW(szFile, '\\');
350 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
351 index = atoiW(pIndexStr);
352 memcpy(szFileCopy, szFile,
353 (pIndexStr - szFile - 1) * sizeof(WCHAR));
354 szFileCopy[pIndexStr - szFile - 1] = '\0';
355 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
356 szPath,NULL))
357 return TYPE_E_CANTLOADLIBRARY;
358 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
359 return TYPE_E_CANTLOADLIBRARY;
363 TRACE("File %s index %d\n", debugstr_w(szPath), index);
365 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
367 if (SUCCEEDED(res))
368 switch(regkind)
370 case REGKIND_DEFAULT:
371 /* don't register typelibs supplied with full path. Experimentation confirms the following */
372 if ((!szFile) ||
373 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
374 (szFile[0] && (szFile[1] == ':'))) break;
375 /* else fall-through */
377 case REGKIND_REGISTER:
378 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
380 IUnknown_Release(*pptLib);
381 *pptLib = 0;
383 break;
384 case REGKIND_NONE:
385 break;
388 TRACE(" returns %08lx\n",res);
389 return res;
392 /******************************************************************************
393 * LoadRegTypeLib [OLEAUT32.162]
395 * Loads a registered type library.
397 * PARAMS
398 * rguid [I] GUID of the registered type library.
399 * wVerMajor [I] major version.
400 * wVerMinor [I] minor version.
401 * lcid [I] locale ID.
402 * ppTLib [O] pointer that receives an ITypeLib object on success.
404 * RETURNS
405 * Success: S_OK.
406 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
407 * LoadTypeLib.
409 HRESULT WINAPI LoadRegTypeLib(
410 REFGUID rguid,
411 WORD wVerMajor,
412 WORD wVerMinor,
413 LCID lcid,
414 ITypeLib **ppTLib)
416 BSTR bstr=NULL;
417 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
419 if(SUCCEEDED(res))
421 res= LoadTypeLib(bstr, ppTLib);
422 SysFreeString(bstr);
425 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
427 return res;
431 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
432 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
433 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
434 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
435 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
436 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
438 /******************************************************************************
439 * RegisterTypeLib [OLEAUT32.163]
440 * Adds information about a type library to the System Registry
441 * NOTES
442 * Docs: ITypeLib FAR * ptlib
443 * Docs: OLECHAR FAR* szFullPath
444 * Docs: OLECHAR FAR* szHelpDir
446 * RETURNS
447 * Success: S_OK
448 * Failure: Status
450 HRESULT WINAPI RegisterTypeLib(
451 ITypeLib * ptlib, /* [in] Pointer to the library*/
452 OLECHAR * szFullPath, /* [in] full Path of the library*/
453 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
454 may be NULL*/
456 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
457 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
458 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
459 HRESULT res;
460 TLIBATTR *attr;
461 WCHAR keyName[60];
462 WCHAR tmp[16];
463 HKEY key, subKey;
464 UINT types, tidx;
465 TYPEKIND kind;
466 DWORD disposition;
468 if (ptlib == NULL || szFullPath == NULL)
469 return E_INVALIDARG;
471 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
472 return E_FAIL;
474 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
476 res = S_OK;
477 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
478 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
480 LPOLESTR doc;
482 /* Set the human-readable name of the typelib */
483 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
485 if (RegSetValueExW(key, NULL, 0, REG_SZ,
486 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
487 res = E_FAIL;
489 SysFreeString(doc);
491 else
492 res = E_FAIL;
494 /* Make up the name of the typelib path subkey */
495 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
497 /* Create the typelib path subkey */
498 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
499 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
501 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
502 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
503 res = E_FAIL;
505 RegCloseKey(subKey);
507 else
508 res = E_FAIL;
510 /* Create the flags subkey */
511 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
512 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
514 /* FIXME: is %u correct? */
515 static const WCHAR formatW[] = {'%','u',0};
516 WCHAR buf[20];
517 sprintfW(buf, formatW, attr->wLibFlags);
518 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
519 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
520 res = E_FAIL;
522 RegCloseKey(subKey);
524 else
525 res = E_FAIL;
527 /* create the helpdir subkey */
528 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
529 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
531 BOOL freeHelpDir = FALSE;
532 OLECHAR* pIndexStr;
534 /* if we created a new key, and helpDir was null, set the helpdir
535 to the directory which contains the typelib. However,
536 if we just opened an existing key, we leave the helpdir alone */
537 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
538 szHelpDir = SysAllocString(szFullPath);
539 pIndexStr = strrchrW(szHelpDir, '\\');
540 if (pIndexStr) {
541 *pIndexStr = 0;
543 freeHelpDir = TRUE;
546 /* if we have an szHelpDir, set it! */
547 if (szHelpDir != NULL) {
548 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
549 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
550 res = E_FAIL;
554 /* tidy up */
555 if (freeHelpDir) SysFreeString(szHelpDir);
556 RegCloseKey(subKey);
558 } else {
559 res = E_FAIL;
562 RegCloseKey(key);
564 else
565 res = E_FAIL;
567 /* register OLE Automation-compatible interfaces for this typelib */
568 types = ITypeLib_GetTypeInfoCount(ptlib);
569 for (tidx=0; tidx<types; tidx++) {
570 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
571 LPOLESTR name = NULL;
572 ITypeInfo *tinfo = NULL;
574 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
576 switch (kind) {
577 case TKIND_INTERFACE:
578 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
579 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
580 break;
582 case TKIND_DISPATCH:
583 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
584 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
585 break;
587 default:
588 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
589 break;
592 if (tinfo) {
593 TYPEATTR *tattr = NULL;
594 ITypeInfo_GetTypeAttr(tinfo, &tattr);
596 if (tattr) {
597 TRACE_(typelib)("guid=%s, flags=%04x (",
598 debugstr_guid(&tattr->guid),
599 tattr->wTypeFlags);
601 if (TRACE_ON(typelib)) {
602 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
603 XX(FAPPOBJECT);
604 XX(FCANCREATE);
605 XX(FLICENSED);
606 XX(FPREDECLID);
607 XX(FHIDDEN);
608 XX(FCONTROL);
609 XX(FDUAL);
610 XX(FNONEXTENSIBLE);
611 XX(FOLEAUTOMATION);
612 XX(FRESTRICTED);
613 XX(FAGGREGATABLE);
614 XX(FREPLACEABLE);
615 XX(FDISPATCHABLE);
616 XX(FREVERSEBIND);
617 XX(FPROXY);
618 #undef XX
619 MESSAGE("\n");
623 * FIXME: The 1 is just here until we implement rpcrt4
624 * stub/proxy handling. Until then it helps IShield
625 * v6 to work.
627 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
629 if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {
630 FIXME("Registering non-oleautomation interface!\n");
633 /* register interface<->typelib coupling */
634 get_interface_key( &tattr->guid, keyName );
635 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
636 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
638 if (name)
639 RegSetValueExW(key, NULL, 0, REG_SZ,
640 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
642 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
643 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
644 RegSetValueExW(subKey, NULL, 0, REG_SZ,
645 (BYTE*)PSOA, sizeof PSOA);
646 RegCloseKey(subKey);
649 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
650 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
651 RegSetValueExW(subKey, NULL, 0, REG_SZ,
652 (BYTE*)PSOA, sizeof PSOA);
653 RegCloseKey(subKey);
656 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
657 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
659 WCHAR buffer[40];
660 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
661 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
663 StringFromGUID2(&attr->guid, buffer, 40);
664 RegSetValueExW(subKey, NULL, 0, REG_SZ,
665 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
666 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
667 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
668 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
669 RegCloseKey(subKey);
672 RegCloseKey(key);
676 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
679 ITypeInfo_Release(tinfo);
682 SysFreeString(name);
686 ITypeLib_ReleaseTLibAttr(ptlib, attr);
688 return res;
692 /******************************************************************************
693 * UnRegisterTypeLib [OLEAUT32.186]
694 * Removes information about a type library from the System Registry
695 * NOTES
697 * RETURNS
698 * Success: S_OK
699 * Failure: Status
701 HRESULT WINAPI UnRegisterTypeLib(
702 REFGUID libid, /* [in] Guid of the library */
703 WORD wVerMajor, /* [in] major version */
704 WORD wVerMinor, /* [in] minor version */
705 LCID lcid, /* [in] locale id */
706 SYSKIND syskind)
708 BSTR tlibPath = NULL;
709 DWORD tmpLength;
710 WCHAR keyName[60];
711 WCHAR subKeyName[50];
712 int result = S_OK;
713 DWORD i = 0;
714 BOOL deleteOtherStuff;
715 HKEY key = NULL;
716 HKEY subKey = NULL;
717 TYPEATTR* typeAttr = NULL;
718 TYPEKIND kind;
719 ITypeInfo* typeInfo = NULL;
720 ITypeLib* typeLib = NULL;
721 int numTypes;
723 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
725 /* Create the path to the key */
726 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
728 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
730 TRACE("Unsupported syskind %i\n", syskind);
731 result = E_INVALIDARG;
732 goto end;
735 /* get the path to the typelib on disk */
736 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
737 result = E_INVALIDARG;
738 goto end;
741 /* Try and open the key to the type library. */
742 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
743 result = E_INVALIDARG;
744 goto end;
747 /* Try and load the type library */
748 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
749 result = TYPE_E_INVALIDSTATE;
750 goto end;
753 /* remove any types registered with this typelib */
754 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
755 for (i=0; i<numTypes; i++) {
756 /* get the kind of type */
757 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
758 goto enddeleteloop;
761 /* skip non-interfaces, and get type info for the type */
762 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
763 goto enddeleteloop;
765 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
766 goto enddeleteloop;
768 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
769 goto enddeleteloop;
772 /* the path to the type */
773 get_interface_key( &typeAttr->guid, subKeyName );
775 /* Delete its bits */
776 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
777 goto enddeleteloop;
779 RegDeleteKeyW(subKey, ProxyStubClsidW);
780 RegDeleteKeyW(subKey, ProxyStubClsid32W);
781 RegDeleteKeyW(subKey, TypeLibW);
782 RegCloseKey(subKey);
783 subKey = NULL;
784 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
786 enddeleteloop:
787 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
788 typeAttr = NULL;
789 if (typeInfo) ITypeInfo_Release(typeInfo);
790 typeInfo = NULL;
793 /* Now, delete the type library path subkey */
794 get_lcid_subkey( lcid, syskind, subKeyName );
795 RegDeleteKeyW(key, subKeyName);
796 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
797 RegDeleteKeyW(key, subKeyName);
799 /* check if there is anything besides the FLAGS/HELPDIR keys.
800 If there is, we don't delete them */
801 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
802 deleteOtherStuff = TRUE;
803 i = 0;
804 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
805 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
807 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
808 if (!strcmpW(subKeyName, FLAGSW)) continue;
809 if (!strcmpW(subKeyName, HELPDIRW)) continue;
810 deleteOtherStuff = FALSE;
811 break;
814 /* only delete the other parts of the key if we're absolutely sure */
815 if (deleteOtherStuff) {
816 RegDeleteKeyW(key, FLAGSW);
817 RegDeleteKeyW(key, HELPDIRW);
818 RegCloseKey(key);
819 key = NULL;
821 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
822 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
823 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
826 end:
827 if (tlibPath) SysFreeString(tlibPath);
828 if (typeLib) ITypeLib_Release(typeLib);
829 if (subKey) RegCloseKey(subKey);
830 if (key) RegCloseKey(key);
831 return result;
834 /*======================= ITypeLib implementation =======================*/
836 typedef struct tagTLBCustData
838 GUID guid;
839 VARIANT data;
840 struct tagTLBCustData* next;
841 } TLBCustData;
843 /* data structure for import typelibs */
844 typedef struct tagTLBImpLib
846 int offset; /* offset in the file (MSFT)
847 offset in nametable (SLTG)
848 just used to identify library while reading
849 data from file */
850 GUID guid; /* libid */
851 BSTR name; /* name */
853 LCID lcid; /* lcid of imported typelib */
855 WORD wVersionMajor; /* major version number */
856 WORD wVersionMinor; /* minor version number */
858 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
859 NULL if not yet loaded */
860 struct tagTLBImpLib * next;
861 } TLBImpLib;
863 /* internal ITypeLib data */
864 typedef struct tagITypeLibImpl
866 const ITypeLib2Vtbl *lpVtbl;
867 const ITypeCompVtbl *lpVtblTypeComp;
868 ULONG ref;
869 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
871 /* strings can be stored in tlb as multibyte strings BUT they are *always*
872 * exported to the application as a UNICODE string.
874 BSTR Name;
875 BSTR DocString;
876 BSTR HelpFile;
877 BSTR HelpStringDll;
878 unsigned long dwHelpContext;
879 int TypeInfoCount; /* nr of typeinfo's in librarry */
880 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
881 int ctCustData; /* number of items in cust data list */
882 TLBCustData * pCustData; /* linked list to cust data */
883 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
884 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
885 libary. Only used while read MSFT
886 typelibs */
888 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
889 struct tagITypeLibImpl *next, *prev;
890 WCHAR *path;
891 INT index;
892 } ITypeLibImpl;
894 static const ITypeLib2Vtbl tlbvt;
895 static const ITypeCompVtbl tlbtcvt;
897 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
898 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
900 /* ITypeLib methods */
901 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
902 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
904 /*======================= ITypeInfo implementation =======================*/
906 /* data for referenced types */
907 typedef struct tagTLBRefType
909 INT index; /* Type index for internal ref or for external ref
910 it the format is SLTG. -2 indicates to
911 use guid */
913 GUID guid; /* guid of the referenced type */
914 /* if index == TLB_REF_USE_GUID */
916 HREFTYPE reference; /* The href of this ref */
917 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
918 TLB_REF_INTERNAL for internal refs
919 TLB_REF_NOT_FOUND for broken refs */
921 struct tagTLBRefType * next;
922 } TLBRefType;
924 #define TLB_REF_USE_GUID -2
926 #define TLB_REF_INTERNAL (void*)-2
927 #define TLB_REF_NOT_FOUND (void*)-1
929 /* internal Parameter data */
930 typedef struct tagTLBParDesc
932 BSTR Name;
933 int ctCustData;
934 TLBCustData * pCustData; /* linked list to cust data */
935 } TLBParDesc;
937 /* internal Function data */
938 typedef struct tagTLBFuncDesc
940 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
941 BSTR Name; /* the name of this function */
942 TLBParDesc *pParamDesc; /* array with param names and custom data */
943 int helpcontext;
944 int HelpStringContext;
945 BSTR HelpString;
946 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
947 int ctCustData;
948 TLBCustData * pCustData; /* linked list to cust data; */
949 struct tagTLBFuncDesc * next;
950 } TLBFuncDesc;
952 /* internal Variable data */
953 typedef struct tagTLBVarDesc
955 VARDESC vardesc; /* lots of info on the variable and its attributes. */
956 BSTR Name; /* the name of this variable */
957 int HelpContext;
958 int HelpStringContext; /* FIXME: where? */
959 BSTR HelpString;
960 int ctCustData;
961 TLBCustData * pCustData;/* linked list to cust data; */
962 struct tagTLBVarDesc * next;
963 } TLBVarDesc;
965 /* internal implemented interface data */
966 typedef struct tagTLBImplType
968 HREFTYPE hRef; /* hRef of interface */
969 int implflags; /* IMPLFLAG_*s */
970 int ctCustData;
971 TLBCustData * pCustData;/* linked list to custom data; */
972 struct tagTLBImplType *next;
973 } TLBImplType;
975 /* internal TypeInfo data */
976 typedef struct tagITypeInfoImpl
978 const ITypeInfo2Vtbl *lpVtbl;
979 const ITypeCompVtbl *lpVtblTypeComp;
980 ULONG ref;
981 TYPEATTR TypeAttr ; /* _lots_ of type information. */
982 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
983 int index; /* index in this typelib; */
984 /* type libs seem to store the doc strings in ascii
985 * so why should we do it in unicode?
987 BSTR Name;
988 BSTR DocString;
989 unsigned long dwHelpContext;
990 unsigned long dwHelpStringContext;
992 /* functions */
993 TLBFuncDesc * funclist; /* linked list with function descriptions */
995 /* variables */
996 TLBVarDesc * varlist; /* linked list with variable descriptions */
998 /* Implemented Interfaces */
999 TLBImplType * impltypelist;
1001 TLBRefType * reflist;
1002 int ctCustData;
1003 TLBCustData * pCustData; /* linked list to cust data; */
1004 struct tagITypeInfoImpl * next;
1005 } ITypeInfoImpl;
1007 static const ITypeInfo2Vtbl tinfvt;
1008 static const ITypeCompVtbl tcompvt;
1010 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1012 typedef struct tagTLBContext
1014 unsigned int oStart; /* start of TLB in file */
1015 unsigned int pos; /* current pos */
1016 unsigned int length; /* total length */
1017 void *mapping; /* memory mapping */
1018 MSFT_SegDir * pTblDir;
1019 ITypeLibImpl* pLibInfo;
1020 } TLBContext;
1023 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1026 debug
1028 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1029 if (pTD->vt & VT_RESERVED)
1030 szVarType += strlen(strcpy(szVarType, "reserved | "));
1031 if (pTD->vt & VT_BYREF)
1032 szVarType += strlen(strcpy(szVarType, "ref to "));
1033 if (pTD->vt & VT_ARRAY)
1034 szVarType += strlen(strcpy(szVarType, "array of "));
1035 if (pTD->vt & VT_VECTOR)
1036 szVarType += strlen(strcpy(szVarType, "vector of "));
1037 switch(pTD->vt & VT_TYPEMASK) {
1038 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1039 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1040 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1041 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1042 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1043 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1044 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1045 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1046 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1047 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1048 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1049 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1050 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1051 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1052 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1053 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1054 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1055 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1056 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1057 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1058 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1059 pTD->u.hreftype); break;
1060 case VT_PTR: sprintf(szVarType, "ptr to ");
1061 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1062 break;
1063 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1064 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1065 break;
1066 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1067 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1068 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1069 break;
1071 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1075 void dump_ELEMDESC(ELEMDESC *edesc) {
1076 char buf[200];
1077 dump_TypeDesc(&edesc->tdesc,buf);
1078 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1079 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
1080 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1082 void dump_FUNCDESC(FUNCDESC *funcdesc) {
1083 int i;
1084 MESSAGE("memid is %08lx\n",funcdesc->memid);
1085 for (i=0;i<funcdesc->cParams;i++) {
1086 MESSAGE("Param %d:\n",i);
1087 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1089 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1090 switch (funcdesc->funckind) {
1091 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1092 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1093 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1094 case FUNC_STATIC: MESSAGE("static");break;
1095 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1096 default: MESSAGE("unknown");break;
1098 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1099 switch (funcdesc->invkind) {
1100 case INVOKE_FUNC: MESSAGE("func");break;
1101 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1102 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1103 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1105 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1106 switch (funcdesc->callconv) {
1107 case CC_CDECL: MESSAGE("cdecl");break;
1108 case CC_PASCAL: MESSAGE("pascal");break;
1109 case CC_STDCALL: MESSAGE("stdcall");break;
1110 case CC_SYSCALL: MESSAGE("syscall");break;
1111 default:break;
1113 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1114 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1115 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1117 MESSAGE("\telemdescFunc (return value type):\n");
1118 dump_ELEMDESC(&funcdesc->elemdescFunc);
1121 void dump_IDLDESC(IDLDESC *idl) {
1122 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
1125 static const char * typekind_desc[] =
1127 "TKIND_ENUM",
1128 "TKIND_RECORD",
1129 "TKIND_MODULE",
1130 "TKIND_INTERFACE",
1131 "TKIND_DISPATCH",
1132 "TKIND_COCLASS",
1133 "TKIND_ALIAS",
1134 "TKIND_UNION",
1135 "TKIND_MAX"
1138 void dump_TYPEATTR(TYPEATTR *tattr) {
1139 char buf[200];
1140 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
1141 MESSAGE("\tlcid: %ld\n",tattr->lcid);
1142 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
1143 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
1144 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
1145 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
1146 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
1147 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
1148 MESSAGE("\tcVars: %d\n", tattr->cVars);
1149 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
1150 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
1151 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
1152 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
1153 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
1154 dump_TypeDesc(&tattr->tdescAlias,buf);
1155 MESSAGE("\ttypedesc: %s\n", buf);
1156 dump_IDLDESC(&tattr->idldescType);
1159 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1161 int i;
1162 if (!TRACE_ON(typelib))
1163 return;
1164 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1165 for (i=0;i<pfd->funcdesc.cParams;i++)
1166 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1169 dump_FUNCDESC(&(pfd->funcdesc));
1171 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1172 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1174 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1176 while (pfd)
1178 dump_TLBFuncDescOne(pfd);
1179 pfd = pfd->next;
1182 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1184 while (pvd)
1186 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1187 pvd = pvd->next;
1191 static void dump_TLBImpLib(TLBImpLib *import)
1193 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1194 debugstr_w(import->name));
1195 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1196 import->wVersionMinor, import->lcid, import->offset);
1199 static void dump_TLBRefType(TLBRefType * prt)
1201 while (prt)
1203 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1204 if(prt->index == -1)
1205 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1206 else
1207 TRACE_(typelib)("type no: %d\n", prt->index);
1209 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1210 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1211 TRACE_(typelib)("in lib\n");
1212 dump_TLBImpLib(prt->pImpTLInfo);
1214 prt = prt->next;
1218 static void dump_TLBImplType(TLBImplType * impl)
1220 while (impl) {
1221 TRACE_(typelib)(
1222 "implementing/inheriting interface hRef = %lx implflags %x\n",
1223 impl->hRef, impl->implflags);
1224 impl = impl->next;
1228 void dump_Variant(VARIANT * pvar)
1230 SYSTEMTIME st;
1232 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1234 if (pvar)
1236 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1237 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1239 TRACE(",%p", V_BYREF(pvar));
1241 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1243 TRACE(",FIXME");
1245 else switch (V_TYPE(pvar))
1247 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1248 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1249 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1250 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1251 case VT_INT:
1252 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1253 case VT_UINT:
1254 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1255 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1256 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1257 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1258 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1259 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1260 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1261 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1262 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1263 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1264 V_CY(pvar).s.Lo); break;
1265 case VT_DATE:
1266 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1267 TRACE(",<invalid>");
1268 else
1269 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1270 st.wHour, st.wMinute, st.wSecond);
1271 break;
1272 case VT_ERROR:
1273 case VT_VOID:
1274 case VT_USERDEFINED:
1275 case VT_EMPTY:
1276 case VT_NULL: break;
1277 default: TRACE(",?"); break;
1280 TRACE("}\n");
1283 static void dump_DispParms(DISPPARAMS * pdp)
1285 int index = 0;
1287 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1289 while (index < pdp->cArgs)
1291 dump_Variant( &pdp->rgvarg[index] );
1292 ++index;
1296 static void dump_TypeInfo(ITypeInfoImpl * pty)
1298 TRACE("%p ref=%lu\n", pty, pty->ref);
1299 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1300 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1301 TRACE("fct:%u var:%u impl:%u\n",
1302 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1303 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1304 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1305 dump_TLBFuncDesc(pty->funclist);
1306 dump_TLBVarDesc(pty->varlist);
1307 dump_TLBImplType(pty->impltypelist);
1310 void dump_VARDESC(VARDESC *v)
1312 MESSAGE("memid %ld\n",v->memid);
1313 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1314 MESSAGE("oInst %ld\n",v->u.oInst);
1315 dump_ELEMDESC(&(v->elemdescVar));
1316 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1317 MESSAGE("varkind %d\n",v->varkind);
1320 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1322 /* VT_LPWSTR is largest type that */
1323 /* may appear in type description*/
1324 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1325 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1326 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1327 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1328 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1329 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1330 {{0},30},{{0},31}
1333 static void TLB_abort(void)
1335 DebugBreak();
1337 static void * TLB_Alloc(unsigned size)
1339 void * ret;
1340 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1341 /* FIXME */
1342 ERR("cannot allocate memory\n");
1344 return ret;
1347 static void TLB_Free(void * ptr)
1349 HeapFree(GetProcessHeap(), 0, ptr);
1352 /* deep copy a typedesc */
1353 static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in)
1355 out->vt = in->vt;
1356 switch(in->vt) {
1357 case VT_PTR:
1358 out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC));
1359 copy_typedesc(out->u.lptdesc, in->u.lptdesc);
1360 break;
1361 case VT_USERDEFINED:
1362 out->u.hreftype = in->u.hreftype;
1363 break;
1364 case VT_CARRAY:
1365 out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) +
1366 (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND));
1367 copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem);
1368 out->u.lpadesc->cDims = in->u.lpadesc->cDims;
1369 memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND));
1370 break;
1371 default:
1372 break;
1376 /* free()s any allocated memory pointed to by the tdesc. NB does not
1377 free the tdesc itself - this is because the tdesc is typically part
1378 of a larger structure */
1379 static void free_deep_typedesc(TYPEDESC *tdesc)
1381 switch(tdesc->vt) {
1382 case VT_PTR:
1383 free_deep_typedesc(tdesc->u.lptdesc);
1384 HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc);
1385 tdesc->u.lptdesc = NULL;
1386 break;
1387 case VT_CARRAY:
1388 free_deep_typedesc(&tdesc->u.lpadesc->tdescElem);
1389 HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc);
1390 tdesc->u.lpadesc = NULL;
1391 break;
1392 default:
1393 break;
1397 /**********************************************************************
1399 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1401 /* read function */
1402 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1404 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1405 pcx->pos, count, pcx->oStart, pcx->length, where);
1407 if (where != DO_NOT_SEEK)
1409 where += pcx->oStart;
1410 if (where > pcx->length)
1412 /* FIXME */
1413 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1414 TLB_abort();
1416 pcx->pos = where;
1418 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1419 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1420 pcx->pos += count;
1421 return count;
1424 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1425 long where )
1427 DWORD ret;
1429 ret = MSFT_Read(buffer, count, pcx, where);
1430 FromLEDWords(buffer, ret);
1432 return ret;
1435 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1436 long where )
1438 DWORD ret;
1440 ret = MSFT_Read(buffer, count, pcx, where);
1441 FromLEWords(buffer, ret);
1443 return ret;
1446 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1448 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1449 memset(pGuid,0, sizeof(GUID));
1450 return;
1452 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1453 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1454 pGuid->Data2 = FromLEWord(pGuid->Data2);
1455 pGuid->Data3 = FromLEWord(pGuid->Data3);
1456 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1459 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1461 char * name;
1462 MSFT_NameIntro niName;
1463 int lengthInChars;
1464 WCHAR* pwstring = NULL;
1465 BSTR bstrName = NULL;
1467 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1468 pcx->pTblDir->pNametab.offset+offset);
1469 niName.namelen &= 0xFF; /* FIXME: correct ? */
1470 name=TLB_Alloc((niName.namelen & 0xff) +1);
1471 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1472 name[niName.namelen & 0xff]='\0';
1474 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1475 name, -1, NULL, 0);
1477 /* no invalid characters in string */
1478 if (lengthInChars)
1480 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1482 /* don't check for invalid character since this has been done previously */
1483 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1485 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1486 lengthInChars = SysStringLen(bstrName);
1487 HeapFree(GetProcessHeap(), 0, pwstring);
1490 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1491 return bstrName;
1494 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1496 char * string;
1497 INT16 length;
1498 int lengthInChars;
1499 BSTR bstr = NULL;
1501 if(offset<0) return NULL;
1502 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1503 if(length <= 0) return 0;
1504 string=TLB_Alloc(length +1);
1505 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1506 string[length]='\0';
1508 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1509 string, -1, NULL, 0);
1511 /* no invalid characters in string */
1512 if (lengthInChars)
1514 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1516 /* don't check for invalid character since this has been done previously */
1517 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1519 bstr = SysAllocStringLen(pwstring, lengthInChars);
1520 lengthInChars = SysStringLen(bstr);
1521 HeapFree(GetProcessHeap(), 0, pwstring);
1524 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1525 return bstr;
1528 * read a value and fill a VARIANT structure
1530 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1532 int size;
1534 TRACE_(typelib)("\n");
1536 if(offset <0) { /* data are packed in here */
1537 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1538 V_I2(pVar) = offset & 0x3ffffff;
1539 return;
1541 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1542 pcx->pTblDir->pCustData.offset + offset );
1543 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1544 switch (V_VT(pVar)){
1545 case VT_EMPTY: /* FIXME: is this right? */
1546 case VT_NULL: /* FIXME: is this right? */
1547 case VT_I2 : /* this should not happen */
1548 case VT_I4 :
1549 case VT_R4 :
1550 case VT_ERROR :
1551 case VT_BOOL :
1552 case VT_I1 :
1553 case VT_UI1 :
1554 case VT_UI2 :
1555 case VT_UI4 :
1556 case VT_INT :
1557 case VT_UINT :
1558 case VT_VOID : /* FIXME: is this right? */
1559 case VT_HRESULT :
1560 size=4; break;
1561 case VT_R8 :
1562 case VT_CY :
1563 case VT_DATE :
1564 case VT_I8 :
1565 case VT_UI8 :
1566 case VT_DECIMAL : /* FIXME: is this right? */
1567 case VT_FILETIME :
1568 size=8;break;
1569 /* pointer types with known behaviour */
1570 case VT_BSTR :{
1571 char * ptr;
1572 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1573 if(size < 0) {
1574 FIXME("BSTR length = %d?\n", size);
1575 } else {
1576 ptr=TLB_Alloc(size);/* allocate temp buffer */
1577 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1578 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1579 /* FIXME: do we need a AtoW conversion here? */
1580 V_UNION(pVar, bstrVal[size])=L'\0';
1581 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1582 TLB_Free(ptr);
1585 size=-4; break;
1586 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1587 case VT_DISPATCH :
1588 case VT_VARIANT :
1589 case VT_UNKNOWN :
1590 case VT_PTR :
1591 case VT_SAFEARRAY :
1592 case VT_CARRAY :
1593 case VT_USERDEFINED :
1594 case VT_LPSTR :
1595 case VT_LPWSTR :
1596 case VT_BLOB :
1597 case VT_STREAM :
1598 case VT_STORAGE :
1599 case VT_STREAMED_OBJECT :
1600 case VT_STORED_OBJECT :
1601 case VT_BLOB_OBJECT :
1602 case VT_CF :
1603 case VT_CLSID :
1604 default:
1605 size=0;
1606 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1607 V_VT(pVar));
1610 if(size>0) /* (big|small) endian correct? */
1611 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1612 return;
1615 * create a linked list with custom data
1617 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1619 MSFT_CDGuid entry;
1620 TLBCustData* pNew;
1621 int count=0;
1623 TRACE_(typelib)("\n");
1625 while(offset >=0){
1626 count++;
1627 pNew=TLB_Alloc(sizeof(TLBCustData));
1628 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1629 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1630 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1631 /* add new custom data at head of the list */
1632 pNew->next=*ppCustData;
1633 *ppCustData=pNew;
1634 offset = entry.next;
1636 return count;
1639 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1640 ITypeInfoImpl *pTI)
1642 if(type <0)
1643 pTd->vt=type & VT_TYPEMASK;
1644 else
1645 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1647 if(pTd->vt == VT_USERDEFINED)
1648 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1650 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1653 static void
1654 MSFT_DoFuncs(TLBContext* pcx,
1655 ITypeInfoImpl* pTI,
1656 int cFuncs,
1657 int cVars,
1658 int offset,
1659 TLBFuncDesc** pptfd)
1662 * member information is stored in a data structure at offset
1663 * indicated by the memoffset field of the typeinfo structure
1664 * There are several distinctive parts.
1665 * The first part starts with a field that holds the total length
1666 * of this (first) part excluding this field. Then follow the records,
1667 * for each member there is one record.
1669 * The first entry is always the length of the record (including this
1670 * length word).
1671 * The rest of the record depends on the type of the member. If there is
1672 * a field indicating the member type (function, variable, interface, etc)
1673 * I have not found it yet. At this time we depend on the information
1674 * in the type info and the usual order how things are stored.
1676 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1677 * for each member;
1679 * Third is an equal sized array with file offsets to the name entry
1680 * of each member.
1682 * The fourth and last (?) part is an array with offsets to the records
1683 * in the first part of this file segment.
1686 int infolen, nameoffset, reclength, nrattributes, i;
1687 int recoffset = offset + sizeof(INT);
1689 char recbuf[512];
1690 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1692 TRACE_(typelib)("\n");
1694 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1696 for ( i = 0; i < cFuncs ; i++ )
1698 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1700 /* name, eventually add to a hash table */
1701 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1702 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1704 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1706 /* read the function information record */
1707 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1709 reclength &= 0x1ff;
1711 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1713 /* do the attributes */
1714 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1715 / sizeof(int);
1717 if ( nrattributes > 0 )
1719 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1721 if ( nrattributes > 1 )
1723 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1724 pFuncRec->OptAttr[1]) ;
1726 if ( nrattributes > 2 )
1728 if ( pFuncRec->FKCCIC & 0x2000 )
1730 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1732 else
1734 (*pptfd)->Entry = MSFT_ReadString(pcx,
1735 pFuncRec->OptAttr[2]);
1737 if( nrattributes > 5 )
1739 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1741 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1743 MSFT_CustData(pcx,
1744 pFuncRec->OptAttr[6],
1745 &(*pptfd)->pCustData);
1752 /* fill the FuncDesc Structure */
1753 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1754 offset + infolen + ( i + 1) * sizeof(INT));
1756 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1757 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1758 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1759 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1760 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1761 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1762 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1764 MSFT_GetTdesc(pcx,
1765 pFuncRec->DataType,
1766 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1767 pTI);
1769 /* do the parameters/arguments */
1770 if(pFuncRec->nrargs)
1772 int j = 0;
1773 MSFT_ParameterInfo paraminfo;
1775 (*pptfd)->funcdesc.lprgelemdescParam =
1776 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1778 (*pptfd)->pParamDesc =
1779 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1781 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1782 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1784 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1786 TYPEDESC* lpArgTypeDesc = 0;
1788 MSFT_GetTdesc(pcx,
1789 paraminfo.DataType,
1790 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1791 pTI);
1793 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1795 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1797 /* SEEK value = jump to offset,
1798 * from there jump to the end of record,
1799 * go back by (j-1) arguments
1801 MSFT_ReadLEDWords( &paraminfo ,
1802 sizeof(MSFT_ParameterInfo), pcx,
1803 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1804 * sizeof(MSFT_ParameterInfo)));
1805 lpArgTypeDesc =
1806 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1808 while ( lpArgTypeDesc != NULL )
1810 switch ( lpArgTypeDesc->vt )
1812 case VT_PTR:
1813 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1814 break;
1816 case VT_CARRAY:
1817 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1818 break;
1820 case VT_USERDEFINED:
1821 MSFT_DoRefType(pcx, pTI,
1822 lpArgTypeDesc->u.hreftype);
1824 lpArgTypeDesc = NULL;
1825 break;
1827 default:
1828 lpArgTypeDesc = NULL;
1834 /* parameter is the return value! */
1835 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1837 TYPEDESC* lpArgTypeDesc;
1839 (*pptfd)->funcdesc.elemdescFunc =
1840 (*pptfd)->funcdesc.lprgelemdescParam[j];
1842 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1844 while ( lpArgTypeDesc != NULL )
1846 switch ( lpArgTypeDesc->vt )
1848 case VT_PTR:
1849 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1850 break;
1851 case VT_CARRAY:
1852 lpArgTypeDesc =
1853 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1855 break;
1857 case VT_USERDEFINED:
1858 MSFT_DoRefType(pcx,
1859 pTI,
1860 lpArgTypeDesc->u.hreftype);
1862 lpArgTypeDesc = NULL;
1863 break;
1865 default:
1866 lpArgTypeDesc = NULL;
1871 /* second time around */
1872 for(j=0;j<pFuncRec->nrargs;j++)
1874 /* name */
1875 (*pptfd)->pParamDesc[j].Name =
1876 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1878 /* default value */
1879 if ( (PARAMFLAG_FHASDEFAULT &
1880 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1881 ((pFuncRec->FKCCIC) & 0x1000) )
1883 INT* pInt = (INT *)((char *)pFuncRec +
1884 reclength -
1885 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1887 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1889 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1890 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1892 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1893 pInt[j], pcx);
1895 /* custom info */
1896 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1898 MSFT_CustData(pcx,
1899 pFuncRec->OptAttr[7+j],
1900 &(*pptfd)->pParamDesc[j].pCustData);
1905 /* scode is not used: archaic win16 stuff FIXME: right? */
1906 (*pptfd)->funcdesc.cScodes = 0 ;
1907 (*pptfd)->funcdesc.lprgscode = NULL ;
1909 pptfd = & ((*pptfd)->next);
1910 recoffset += reclength;
1914 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1915 int cVars, int offset, TLBVarDesc ** pptvd)
1917 int infolen, nameoffset, reclength;
1918 char recbuf[256];
1919 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1920 int i;
1921 int recoffset;
1923 TRACE_(typelib)("\n");
1925 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1926 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1927 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1928 recoffset += offset+sizeof(INT);
1929 for(i=0;i<cVars;i++){
1930 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1931 /* name, eventually add to a hash table */
1932 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1933 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1934 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1935 /* read the variable information record */
1936 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1937 reclength &=0xff;
1938 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1939 /* Optional data */
1940 if(reclength >(6*sizeof(INT)) )
1941 (*pptvd)->HelpContext=pVarRec->HelpContext;
1942 if(reclength >(7*sizeof(INT)) )
1943 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1944 if(reclength >(8*sizeof(INT)) )
1945 if(reclength >(9*sizeof(INT)) )
1946 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1947 /* fill the VarDesc Structure */
1948 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1949 offset + infolen + ( i + 1) * sizeof(INT));
1950 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1951 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1952 MSFT_GetTdesc(pcx, pVarRec->DataType,
1953 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1954 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1955 if(pVarRec->VarKind == VAR_CONST ){
1956 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1957 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1958 pVarRec->OffsValue, pcx);
1959 } else
1960 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1961 pptvd=&((*pptvd)->next);
1962 recoffset += reclength;
1965 /* fill in data for a hreftype (offset). When the referenced type is contained
1966 * in the typelib, it's just an (file) offset in the type info base dir.
1967 * If comes from import, it's an offset+1 in the ImpInfo table
1968 * */
1969 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1970 int offset)
1972 int j;
1973 TLBRefType **ppRefType = &pTI->reflist;
1975 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1977 while(*ppRefType) {
1978 if((*ppRefType)->reference == offset)
1979 return;
1980 ppRefType = &(*ppRefType)->next;
1983 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1984 sizeof(**ppRefType));
1986 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1987 /* external typelib */
1988 MSFT_ImpInfo impinfo;
1989 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1991 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1993 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1994 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1995 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1996 if(pImpLib->offset==impinfo.oImpFile) break;
1997 pImpLib=pImpLib->next;
1999 if(pImpLib){
2000 (*ppRefType)->reference=offset;
2001 (*ppRefType)->pImpTLInfo = pImpLib;
2002 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2003 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
2004 (*ppRefType)->index = TLB_REF_USE_GUID;
2005 } else
2006 (*ppRefType)->index = impinfo.oGuid;
2007 }else{
2008 ERR("Cannot find a reference\n");
2009 (*ppRefType)->reference=-1;
2010 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2012 }else{
2013 /* in this typelib */
2014 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2015 (*ppRefType)->reference=offset;
2016 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2020 /* process Implemented Interfaces of a com class */
2021 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2022 int offset)
2024 int i;
2025 MSFT_RefRecord refrec;
2026 TLBImplType **ppImpl = &pTI->impltypelist;
2028 TRACE_(typelib)("\n");
2030 for(i=0;i<count;i++){
2031 if(offset<0) break; /* paranoia */
2032 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2033 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2034 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2035 (*ppImpl)->hRef = refrec.reftype;
2036 (*ppImpl)->implflags=refrec.flags;
2037 (*ppImpl)->ctCustData=
2038 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2039 offset=refrec.onext;
2040 ppImpl=&((*ppImpl)->next);
2044 * process a typeinfo record
2046 ITypeInfoImpl * MSFT_DoTypeInfo(
2047 TLBContext *pcx,
2048 int count,
2049 ITypeLibImpl * pLibInfo)
2051 MSFT_TypeInfoBase tiBase;
2052 ITypeInfoImpl *ptiRet;
2054 TRACE_(typelib)("count=%u\n", count);
2056 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2057 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2058 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2059 /* this is where we are coming from */
2060 ptiRet->pTypeLib = pLibInfo;
2061 ptiRet->index=count;
2062 /* fill in the typeattr fields */
2063 WARN("Assign constructor/destructor memid\n");
2065 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2066 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2067 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2068 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2069 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2070 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2071 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2072 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2073 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2074 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2075 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2076 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2077 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2078 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2079 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2080 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2081 MSFT_GetTdesc(pcx, tiBase.datatype1,
2082 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2084 /* FIXME: */
2085 /* IDLDESC idldescType; *//* never saw this one != zero */
2087 /* name, eventually add to a hash table */
2088 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2089 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2090 /* help info */
2091 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2092 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2093 ptiRet->dwHelpContext=tiBase.helpcontext;
2094 /* note: InfoType's Help file and HelpStringDll come from the containing
2095 * library. Further HelpString and Docstring appear to be the same thing :(
2097 /* functions */
2098 if(ptiRet->TypeAttr.cFuncs >0 )
2099 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2100 ptiRet->TypeAttr.cVars,
2101 tiBase.memoffset, & ptiRet->funclist);
2102 /* variables */
2103 if(ptiRet->TypeAttr.cVars >0 )
2104 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2105 ptiRet->TypeAttr.cVars,
2106 tiBase.memoffset, & ptiRet->varlist);
2107 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2108 switch(ptiRet->TypeAttr.typekind)
2110 case TKIND_COCLASS:
2111 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2112 tiBase.datatype1);
2113 break;
2114 case TKIND_DISPATCH:
2115 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2117 if (tiBase.datatype1 != -1)
2119 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2120 ptiRet->impltypelist->hRef = tiBase.datatype1;
2122 else
2123 { /* FIXME: This is a really bad hack to add IDispatch */
2124 const char* szStdOle = "stdole2.tlb\0";
2125 int nStdOleLen = strlen(szStdOle);
2126 TLBRefType **ppRef = &ptiRet->reflist;
2128 while(*ppRef) {
2129 if((*ppRef)->reference == -1)
2130 break;
2131 ppRef = &(*ppRef)->next;
2133 if(!*ppRef) {
2134 *ppRef = TLB_Alloc(sizeof(**ppRef));
2135 (*ppRef)->guid = IID_IDispatch;
2136 (*ppRef)->reference = -1;
2137 (*ppRef)->index = TLB_REF_USE_GUID;
2138 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2139 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2140 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2141 nStdOleLen + 1);
2143 MultiByteToWideChar(CP_ACP,
2144 MB_PRECOMPOSED,
2145 szStdOle,
2147 (*ppRef)->pImpTLInfo->name,
2148 SysStringLen((*ppRef)->pImpTLInfo->name));
2150 (*ppRef)->pImpTLInfo->lcid = 0;
2151 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2152 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2155 break;
2156 default:
2157 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2158 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2159 ptiRet->impltypelist->hRef = tiBase.datatype1;
2160 break;
2163 ptiRet->ctCustData=
2164 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2166 TRACE_(typelib)("%s guid: %s kind:%s\n",
2167 debugstr_w(ptiRet->Name),
2168 debugstr_guid(&ptiRet->TypeAttr.guid),
2169 typekind_desc[ptiRet->TypeAttr.typekind]);
2171 return ptiRet;
2174 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2175 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2176 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2177 * tradeoff here.
2179 static ITypeLibImpl *tlb_cache_first;
2180 static CRITICAL_SECTION cache_section;
2181 static CRITICAL_SECTION_DEBUG cache_section_debug =
2183 0, 0, &cache_section,
2184 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2185 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
2187 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2190 /****************************************************************************
2191 * TLB_ReadTypeLib
2193 * find the type of the typelib file and map the typelib resource into
2194 * the memory
2196 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2197 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2198 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2200 ITypeLibImpl *entry;
2201 int ret = TYPE_E_CANTLOADLIBRARY;
2202 DWORD dwSignature = 0;
2203 HANDLE hFile;
2205 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2207 *ppTypeLib = NULL;
2209 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2210 EnterCriticalSection(&cache_section);
2211 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2213 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2215 TRACE("cache hit\n");
2216 *ppTypeLib = (ITypeLib2*)entry;
2217 ITypeLib_AddRef(*ppTypeLib);
2218 LeaveCriticalSection(&cache_section);
2219 return S_OK;
2222 LeaveCriticalSection(&cache_section);
2224 /* check the signature of the file */
2225 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2226 if (INVALID_HANDLE_VALUE != hFile)
2228 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2229 if (hMapping)
2231 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2232 if(pBase)
2234 /* retrieve file size */
2235 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2237 /* first try to load as *.tlb */
2238 dwSignature = FromLEDWord(*((DWORD*) pBase));
2239 if ( dwSignature == MSFT_SIGNATURE)
2241 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2243 else if ( dwSignature == SLTG_SIGNATURE)
2245 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2247 UnmapViewOfFile(pBase);
2249 CloseHandle(hMapping);
2251 CloseHandle(hFile);
2253 else
2255 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2258 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2259 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2261 /* find the typelibrary resource*/
2262 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2263 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2264 if (hinstDLL)
2266 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2267 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2268 if (hrsrc)
2270 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2271 if (hGlobal)
2273 LPVOID pBase = LockResource(hGlobal);
2274 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2276 if (pBase)
2278 /* try to load as incore resource */
2279 dwSignature = FromLEDWord(*((DWORD*) pBase));
2280 if ( dwSignature == MSFT_SIGNATURE)
2282 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2284 else if ( dwSignature == SLTG_SIGNATURE)
2286 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2288 else
2290 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2293 FreeResource( hGlobal );
2296 FreeLibrary(hinstDLL);
2300 if(*ppTypeLib) {
2301 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2303 TRACE("adding to cache\n");
2304 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2305 lstrcpyW(impl->path, pszFileName);
2306 /* We should really canonicalise the path here. */
2307 impl->index = index;
2309 /* FIXME: check if it has added already in the meantime */
2310 EnterCriticalSection(&cache_section);
2311 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2312 impl->prev = NULL;
2313 tlb_cache_first = impl;
2314 LeaveCriticalSection(&cache_section);
2315 ret = S_OK;
2316 } else
2317 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2319 return ret;
2322 /*================== ITypeLib(2) Methods ===================================*/
2324 /****************************************************************************
2325 * ITypeLib2_Constructor_MSFT
2327 * loading an MSFT typelib from an in-memory image
2329 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2331 TLBContext cx;
2332 long lPSegDir;
2333 MSFT_Header tlbHeader;
2334 MSFT_SegDir tlbSegDir;
2335 ITypeLibImpl * pTypeLibImpl;
2337 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2339 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2340 if (!pTypeLibImpl) return NULL;
2342 pTypeLibImpl->lpVtbl = &tlbvt;
2343 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2344 pTypeLibImpl->ref = 1;
2346 /* get pointer to beginning of typelib data */
2347 cx.pos = 0;
2348 cx.oStart=0;
2349 cx.mapping = pLib;
2350 cx.pLibInfo = pTypeLibImpl;
2351 cx.length = dwTLBLength;
2353 /* read header */
2354 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2355 TRACE("header:\n");
2356 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2357 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2358 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2359 return NULL;
2361 /* there is a small amount of information here until the next important
2362 * part:
2363 * the segment directory . Try to calculate the amount of data */
2364 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2366 /* now read the segment directory */
2367 TRACE("read segment directory (at %ld)\n",lPSegDir);
2368 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2369 cx.pTblDir = &tlbSegDir;
2371 /* just check two entries */
2372 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2374 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2375 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2376 return NULL;
2379 /* now fill our internal data */
2380 /* TLIBATTR fields */
2381 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2383 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2384 /* Windows seems to have zero here, is this correct? */
2385 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2386 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2387 else
2388 pTypeLibImpl->LibAttr.lcid = 0;
2390 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2391 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2392 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2393 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2395 /* name, eventually add to a hash table */
2396 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2398 /* help info */
2399 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2400 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2402 if( tlbHeader.varflags & HELPDLLFLAG)
2404 int offset;
2405 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2406 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2409 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2411 /* custom data */
2412 if(tlbHeader.CustomDataOffset >= 0)
2414 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2417 /* fill in typedescriptions */
2418 if(tlbSegDir.pTypdescTab.length > 0)
2420 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2421 INT16 td[4];
2422 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2423 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2424 for(i=0; i<cTD; )
2426 /* FIXME: add several sanity checks here */
2427 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2428 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2430 /* FIXME: check safearray */
2431 if(td[3] < 0)
2432 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2433 else
2434 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2436 else if(td[0] == VT_CARRAY)
2438 /* array descr table here */
2439 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2441 else if(td[0] == VT_USERDEFINED)
2443 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2445 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2448 /* second time around to fill the array subscript info */
2449 for(i=0;i<cTD;i++)
2451 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2452 if(tlbSegDir.pArrayDescriptions.offset>0)
2454 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2455 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2457 if(td[1]<0)
2458 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2459 else
2460 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2462 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2464 for(j = 0; j<td[2]; j++)
2466 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2467 sizeof(INT), &cx, DO_NOT_SEEK);
2468 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2469 sizeof(INT), &cx, DO_NOT_SEEK);
2472 else
2474 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2475 ERR("didn't find array description data\n");
2480 /* imported type libs */
2481 if(tlbSegDir.pImpFiles.offset>0)
2483 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2484 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2485 UINT16 size;
2487 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2489 char *name;
2490 DWORD len;
2492 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2493 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2494 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2496 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2497 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2498 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2499 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2501 size >>= 2;
2502 name = TLB_Alloc(size+1);
2503 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2504 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2505 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2506 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2507 TLB_Free(name);
2509 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2510 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2512 ppImpLib = &(*ppImpLib)->next;
2516 /* type info's */
2517 if(tlbHeader.nrtypeinfos >= 0 )
2519 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2520 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2521 int i;
2523 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2525 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2527 ppTI = &((*ppTI)->next);
2528 (pTypeLibImpl->TypeInfoCount)++;
2532 TRACE("(%p)\n", pTypeLibImpl);
2533 return (ITypeLib2*) pTypeLibImpl;
2537 static BSTR TLB_MultiByteToBSTR(char *ptr)
2539 DWORD len;
2540 WCHAR *nameW;
2541 BSTR ret;
2543 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2544 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2545 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2546 ret = SysAllocString(nameW);
2547 HeapFree(GetProcessHeap(), 0, nameW);
2548 return ret;
2551 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2553 char b[3];
2554 int i;
2555 short s;
2557 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2558 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2559 return FALSE;
2562 guid->Data4[0] = s >> 8;
2563 guid->Data4[1] = s & 0xff;
2565 b[2] = '\0';
2566 for(i = 0; i < 6; i++) {
2567 memcpy(b, str + 24 + 2 * i, 2);
2568 guid->Data4[i + 2] = strtol(b, NULL, 16);
2570 return TRUE;
2573 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2575 WORD bytelen;
2576 DWORD len;
2577 WCHAR *nameW;
2579 *pBstr = NULL;
2580 bytelen = *(WORD*)ptr;
2581 if(bytelen == 0xffff) return 2;
2582 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2583 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2584 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2585 *pBstr = SysAllocStringLen(nameW, len);
2586 HeapFree(GetProcessHeap(), 0, nameW);
2587 return bytelen + 2;
2590 static WORD SLTG_ReadStringA(char *ptr, char **str)
2592 WORD bytelen;
2594 *str = NULL;
2595 bytelen = *(WORD*)ptr;
2596 if(bytelen == 0xffff) return 2;
2597 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2598 memcpy(*str, ptr + 2, bytelen);
2599 (*str)[bytelen] = '\0';
2600 return bytelen + 2;
2603 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2605 char *ptr = pLibBlk;
2606 WORD w;
2608 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2609 FIXME("libblk magic = %04x\n", w);
2610 return 0;
2613 ptr += 6;
2614 if((w = *(WORD*)ptr) != 0xffff) {
2615 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2616 ptr += w;
2618 ptr += 2;
2620 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2622 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2624 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2625 ptr += 4;
2627 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2628 ptr += 2;
2630 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2631 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2632 else
2633 pTypeLibImpl->LibAttr.lcid = 0;
2634 ptr += 2;
2636 ptr += 4; /* skip res12 */
2638 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2639 ptr += 2;
2641 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2642 ptr += 2;
2644 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2645 ptr += 2;
2647 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2648 ptr += sizeof(GUID);
2650 return ptr - (char*)pLibBlk;
2653 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2655 BOOL done = FALSE;
2656 TYPEDESC *pTD = &pElem->tdesc;
2658 /* Handle [in/out] first */
2659 if((*pType & 0xc000) == 0xc000)
2660 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2661 else if(*pType & 0x8000)
2662 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2663 else if(*pType & 0x4000)
2664 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2665 else
2666 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2668 if(*pType & 0x2000)
2669 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2671 if(*pType & 0x80)
2672 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2674 while(!done) {
2675 if((*pType & 0xe00) == 0xe00) {
2676 pTD->vt = VT_PTR;
2677 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2678 sizeof(TYPEDESC));
2679 pTD = pTD->u.lptdesc;
2681 switch(*pType & 0x7f) {
2682 case VT_PTR:
2683 pTD->vt = VT_PTR;
2684 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2685 sizeof(TYPEDESC));
2686 pTD = pTD->u.lptdesc;
2687 break;
2689 case VT_USERDEFINED:
2690 pTD->vt = VT_USERDEFINED;
2691 pTD->u.hreftype = *(++pType) / 4;
2692 done = TRUE;
2693 break;
2695 case VT_CARRAY:
2697 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2698 array */
2700 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2702 pTD->vt = VT_CARRAY;
2703 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2704 sizeof(ARRAYDESC) +
2705 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2706 pTD->u.lpadesc->cDims = pSA->cDims;
2707 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2708 pSA->cDims * sizeof(SAFEARRAYBOUND));
2710 pTD = &pTD->u.lpadesc->tdescElem;
2711 break;
2714 case VT_SAFEARRAY:
2716 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2717 useful? */
2719 pType++;
2720 pTD->vt = VT_SAFEARRAY;
2721 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2722 sizeof(TYPEDESC));
2723 pTD = pTD->u.lptdesc;
2724 break;
2726 default:
2727 pTD->vt = *pType & 0x7f;
2728 done = TRUE;
2729 break;
2731 pType++;
2733 return pType;
2737 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2738 char *pNameTable)
2740 int ref;
2741 char *name;
2742 TLBRefType **ppRefType;
2744 if(pRef->magic != SLTG_REF_MAGIC) {
2745 FIXME("Ref magic = %x\n", pRef->magic);
2746 return;
2748 name = ( (char*)(&pRef->names) + pRef->number);
2750 ppRefType = &pTI->reflist;
2751 for(ref = 0; ref < pRef->number >> 3; ref++) {
2752 char *refname;
2753 unsigned int lib_offs, type_num;
2755 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2756 sizeof(**ppRefType));
2758 name += SLTG_ReadStringA(name, &refname);
2759 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2760 FIXME("Can't sscanf ref\n");
2761 if(lib_offs != 0xffff) {
2762 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2764 while(*import) {
2765 if((*import)->offset == lib_offs)
2766 break;
2767 import = &(*import)->next;
2769 if(!*import) {
2770 char fname[MAX_PATH+1];
2771 int len;
2773 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2774 sizeof(**import));
2775 (*import)->offset = lib_offs;
2776 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2777 &(*import)->guid);
2778 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2779 &(*import)->wVersionMajor,
2780 &(*import)->wVersionMinor,
2781 &(*import)->lcid, fname) != 4) {
2782 FIXME("can't sscanf ref %s\n",
2783 pNameTable + lib_offs + 40);
2785 len = strlen(fname);
2786 if(fname[len-1] != '#')
2787 FIXME("fname = %s\n", fname);
2788 fname[len-1] = '\0';
2789 (*import)->name = TLB_MultiByteToBSTR(fname);
2791 (*ppRefType)->pImpTLInfo = *import;
2792 } else { /* internal ref */
2793 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2795 (*ppRefType)->reference = ref;
2796 (*ppRefType)->index = type_num;
2798 HeapFree(GetProcessHeap(), 0, refname);
2799 ppRefType = &(*ppRefType)->next;
2801 if((BYTE)*name != SLTG_REF_MAGIC)
2802 FIXME("End of ref block magic = %x\n", *name);
2803 dump_TLBRefType(pTI->reflist);
2806 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2807 BOOL OneOnly)
2809 SLTG_ImplInfo *info;
2810 TLBImplType **ppImplType = &pTI->impltypelist;
2811 /* I don't really get this structure, usually it's 0x16 bytes
2812 long, but iuser.tlb contains some that are 0x18 bytes long.
2813 That's ok because we can use the next ptr to jump to the next
2814 one. But how do we know the length of the last one? The WORD
2815 at offs 0x8 might be the clue. For now I'm just assuming that
2816 the last one is the regular 0x16 bytes. */
2818 info = (SLTG_ImplInfo*)pBlk;
2819 while(1) {
2820 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2821 sizeof(**ppImplType));
2822 (*ppImplType)->hRef = info->ref;
2823 (*ppImplType)->implflags = info->impltypeflags;
2824 pTI->TypeAttr.cImplTypes++;
2825 ppImplType = &(*ppImplType)->next;
2827 if(info->next == 0xffff)
2828 break;
2829 if(OneOnly)
2830 FIXME("Interface inheriting more than one interface\n");
2831 info = (SLTG_ImplInfo*)(pBlk + info->next);
2833 info++; /* see comment at top of function */
2834 return (char*)info;
2837 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2838 char *pNameTable)
2840 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2841 SLTG_MemberHeader *pMemHeader;
2842 char *pFirstItem, *pNextItem;
2844 if(pTIHeader->href_table != 0xffffffff) {
2845 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2846 pNameTable);
2850 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2852 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2854 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2855 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2858 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2862 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2863 char *pNameTable)
2865 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2866 SLTG_MemberHeader *pMemHeader;
2867 SLTG_Function *pFunc;
2868 char *pFirstItem, *pNextItem;
2869 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2870 int num = 0;
2872 if(pTIHeader->href_table != 0xffffffff) {
2873 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2874 pNameTable);
2877 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2879 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2881 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2882 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2885 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2886 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2888 int param;
2889 WORD *pType, *pArg;
2891 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2892 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2893 FIXME("func magic = %02x\n", pFunc->magic);
2894 return NULL;
2896 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2897 sizeof(**ppFuncDesc));
2898 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2900 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2901 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2902 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2903 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2904 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2905 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2907 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2908 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2910 if(pFunc->retnextopt & 0x80)
2911 pType = &pFunc->rettype;
2912 else
2913 pType = (WORD*)(pFirstItem + pFunc->rettype);
2916 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2918 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2919 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2920 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2921 (*ppFuncDesc)->pParamDesc =
2922 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2923 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2925 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2927 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2928 char *paramName = pNameTable + *pArg;
2929 BOOL HaveOffs;
2930 /* If arg type follows then paramName points to the 2nd
2931 letter of the name, else the next WORD is an offset to
2932 the arg type and paramName points to the first letter.
2933 So let's take one char off paramName and see if we're
2934 pointing at an alpha-numeric char. However if *pArg is
2935 0xffff or 0xfffe then the param has no name, the former
2936 meaning that the next WORD is the type, the latter
2937 meaning the the next WORD is an offset to the type. */
2939 HaveOffs = FALSE;
2940 if(*pArg == 0xffff)
2941 paramName = NULL;
2942 else if(*pArg == 0xfffe) {
2943 paramName = NULL;
2944 HaveOffs = TRUE;
2946 else if(!isalnum(*(paramName-1)))
2947 HaveOffs = TRUE;
2949 pArg++;
2951 if(HaveOffs) { /* the next word is an offset to type */
2952 pType = (WORD*)(pFirstItem + *pArg);
2953 SLTG_DoType(pType, pFirstItem,
2954 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2955 pArg++;
2956 } else {
2957 if(paramName)
2958 paramName--;
2959 pArg = SLTG_DoType(pArg, pFirstItem,
2960 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2963 /* Are we an optional param ? */
2964 if((*ppFuncDesc)->funcdesc.cParams - param <=
2965 (*ppFuncDesc)->funcdesc.cParamsOpt)
2966 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2968 if(paramName) {
2969 (*ppFuncDesc)->pParamDesc[param].Name =
2970 TLB_MultiByteToBSTR(paramName);
2974 ppFuncDesc = &((*ppFuncDesc)->next);
2975 if(pFunc->next == 0xffff) break;
2977 pTI->TypeAttr.cFuncs = num;
2978 dump_TLBFuncDesc(pTI->funclist);
2979 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2982 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2983 char *pNameTable)
2985 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2986 SLTG_MemberHeader *pMemHeader;
2987 SLTG_RecordItem *pItem;
2988 char *pFirstItem;
2989 TLBVarDesc **ppVarDesc = &pTI->varlist;
2990 int num = 0;
2991 WORD *pType;
2992 char buf[300];
2994 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2996 pFirstItem = (char*)(pMemHeader + 1);
2997 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2998 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2999 if(pItem->magic != SLTG_RECORD_MAGIC) {
3000 FIXME("record magic = %02x\n", pItem->magic);
3001 return NULL;
3003 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3004 sizeof(**ppVarDesc));
3005 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3006 (*ppVarDesc)->vardesc.memid = pItem->memid;
3007 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3008 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3010 if(pItem->typepos == 0x02)
3011 pType = &pItem->type;
3012 else if(pItem->typepos == 0x00)
3013 pType = (WORD*)(pFirstItem + pItem->type);
3014 else {
3015 FIXME("typepos = %02x\n", pItem->typepos);
3016 break;
3019 SLTG_DoType(pType, pFirstItem,
3020 &(*ppVarDesc)->vardesc.elemdescVar);
3022 /* FIXME("helpcontext, helpstring\n"); */
3024 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3026 ppVarDesc = &((*ppVarDesc)->next);
3027 if(pItem->next == 0xffff) break;
3029 pTI->TypeAttr.cVars = num;
3030 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3033 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3034 char *pNameTable)
3036 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3037 SLTG_MemberHeader *pMemHeader;
3038 SLTG_AliasItem *pItem;
3039 int i, mustbelast;
3041 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3042 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3044 mustbelast = 0;
3045 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3046 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3047 if (pItem->vt == 0xffff) {
3048 if (i<(pMemHeader->cbExtra/4-1))
3049 FIXME("Endmarker too early in process alias data!\n");
3050 break;
3052 if (mustbelast) {
3053 FIXME("Chain extends over last entry?\n");
3054 break;
3056 if (pItem->vt == VT_USERDEFINED) {
3057 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3058 /* guessing here ... */
3059 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3060 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3061 mustbelast = 1;
3062 } else {
3063 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3064 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3066 pItem++;
3068 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3071 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3072 char *pNameTable)
3074 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3075 SLTG_MemberHeader *pMemHeader;
3076 SLTG_AliasItem *pItem;
3078 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3079 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3080 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3081 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3082 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3085 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3086 char *pNameTable)
3088 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3089 SLTG_MemberHeader *pMemHeader;
3090 SLTG_EnumItem *pItem;
3091 char *pFirstItem;
3092 TLBVarDesc **ppVarDesc = &pTI->varlist;
3093 int num = 0;
3095 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3097 pFirstItem = (char*)(pMemHeader + 1);
3098 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3099 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3100 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3101 FIXME("enumitem magic = %04x\n", pItem->magic);
3102 return NULL;
3104 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3105 sizeof(**ppVarDesc));
3106 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3107 (*ppVarDesc)->vardesc.memid = pItem->memid;
3108 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3109 sizeof(VARIANT));
3110 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3111 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3112 *(INT*)(pItem->value + pFirstItem);
3113 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3114 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3115 /* FIXME("helpcontext, helpstring\n"); */
3117 ppVarDesc = &((*ppVarDesc)->next);
3118 if(pItem->next == 0xffff) break;
3120 pTI->TypeAttr.cVars = num;
3121 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3124 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3125 managable copy of it into this */
3126 typedef struct {
3127 WORD small_no;
3128 char *index_name;
3129 char *other_name;
3130 WORD res1a;
3131 WORD name_offs;
3132 WORD more_bytes;
3133 char *extra;
3134 WORD res20;
3135 DWORD helpcontext;
3136 WORD res26;
3137 GUID uuid;
3138 } SLTG_InternalOtherTypeInfo;
3140 /****************************************************************************
3141 * ITypeLib2_Constructor_SLTG
3143 * loading a SLTG typelib from an in-memory image
3145 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3147 ITypeLibImpl *pTypeLibImpl;
3148 SLTG_Header *pHeader;
3149 SLTG_BlkEntry *pBlkEntry;
3150 SLTG_Magic *pMagic;
3151 SLTG_Index *pIndex;
3152 SLTG_Pad9 *pPad9;
3153 LPVOID pBlk, pFirstBlk;
3154 SLTG_LibBlk *pLibBlk;
3155 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3156 char *pAfterOTIBlks = NULL;
3157 char *pNameTable, *ptr;
3158 int i;
3159 DWORD len, order;
3160 ITypeInfoImpl **ppTypeInfoImpl;
3162 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3164 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3165 if (!pTypeLibImpl) return NULL;
3167 pTypeLibImpl->lpVtbl = &tlbvt;
3168 pTypeLibImpl->ref = 1;
3170 pHeader = pLib;
3172 TRACE("header:\n");
3173 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3174 pHeader->nrOfFileBlks );
3175 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3176 FIXME("Header type magic 0x%08lx not supported.\n",
3177 pHeader->SLTG_magic);
3178 return NULL;
3181 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3182 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3184 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3185 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3187 /* Next we have a magic block */
3188 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3190 /* Let's see if we're still in sync */
3191 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3192 sizeof(SLTG_COMPOBJ_MAGIC))) {
3193 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3194 return NULL;
3196 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3197 sizeof(SLTG_DIR_MAGIC))) {
3198 FIXME("dir magic = %s\n", pMagic->dir_magic);
3199 return NULL;
3202 pIndex = (SLTG_Index*)(pMagic+1);
3204 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3206 pFirstBlk = (LPVOID)(pPad9 + 1);
3208 /* We'll set up a ptr to the main library block, which is the last one. */
3210 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3211 pBlkEntry[order].next != 0;
3212 order = pBlkEntry[order].next - 1, i++) {
3213 pBlk = (char*)pBlk + pBlkEntry[order].len;
3215 pLibBlk = pBlk;
3217 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3219 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3220 interspersed */
3222 len += 0x40;
3224 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3226 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3227 sizeof(*pOtherTypeInfoBlks) *
3228 pTypeLibImpl->TypeInfoCount);
3231 ptr = (char*)pLibBlk + len;
3233 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3234 WORD w, extra;
3235 len = 0;
3237 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3239 w = *(WORD*)(ptr + 2);
3240 if(w != 0xffff) {
3241 len += w;
3242 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3243 w+1);
3244 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3245 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3247 w = *(WORD*)(ptr + 4 + len);
3248 if(w != 0xffff) {
3249 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3250 len += w;
3251 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3252 w+1);
3253 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3254 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3256 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3257 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3258 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3259 if(extra) {
3260 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3261 extra);
3262 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3263 len += extra;
3265 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3266 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3267 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3268 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3269 len += sizeof(SLTG_OtherTypeInfo);
3270 ptr += len;
3273 pAfterOTIBlks = ptr;
3275 /* Skip this WORD and get the next DWORD */
3276 len = *(DWORD*)(pAfterOTIBlks + 2);
3278 /* Now add this to pLibBLk look at what we're pointing at and
3279 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3280 dust and we should be pointing at the beginning of the name
3281 table */
3283 pNameTable = (char*)pLibBlk + len;
3285 switch(*(WORD*)pNameTable) {
3286 case 0xffff:
3287 break;
3288 case 0x0200:
3289 pNameTable += 0x20;
3290 break;
3291 default:
3292 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3293 break;
3296 pNameTable += 0x216;
3298 pNameTable += 2;
3300 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3302 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3305 /* Hopefully we now have enough ptrs set up to actually read in
3306 some TypeInfos. It's not clear which order to do them in, so
3307 I'll just follow the links along the BlkEntry chain and read
3308 them in in the order in which they're in the file */
3310 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3312 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3313 pBlkEntry[order].next != 0;
3314 order = pBlkEntry[order].next - 1, i++) {
3316 SLTG_TypeInfoHeader *pTIHeader;
3317 SLTG_TypeInfoTail *pTITail;
3319 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3320 pOtherTypeInfoBlks[i].index_name)) {
3321 FIXME("Index strings don't match\n");
3322 return NULL;
3325 pTIHeader = pBlk;
3326 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3327 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3328 return NULL;
3330 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3331 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3332 (*ppTypeInfoImpl)->index = i;
3333 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3334 pOtherTypeInfoBlks[i].name_offs +
3335 pNameTable);
3336 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3337 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3338 sizeof(GUID));
3339 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3340 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3341 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3342 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3343 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3345 if((pTIHeader->typeflags1 & 7) != 2)
3346 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3347 if(pTIHeader->typeflags3 != 2)
3348 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3350 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3351 debugstr_w((*ppTypeInfoImpl)->Name),
3352 typekind_desc[pTIHeader->typekind],
3353 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3354 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3356 switch(pTIHeader->typekind) {
3357 case TKIND_ENUM:
3358 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3359 break;
3361 case TKIND_RECORD:
3362 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3363 break;
3365 case TKIND_INTERFACE:
3366 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3367 break;
3369 case TKIND_COCLASS:
3370 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3371 break;
3373 case TKIND_ALIAS:
3374 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3375 if (pTITail->tdescalias_vt)
3376 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3377 break;
3379 case TKIND_DISPATCH:
3380 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3381 break;
3383 default:
3384 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3385 pTITail = NULL;
3386 break;
3390 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3391 but we've already set those */
3392 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3393 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3394 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3396 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3397 X(06);
3398 X(08);
3399 X(0a);
3400 X(0c);
3401 X(0e);
3402 X(10);
3403 X(12);
3404 X(16);
3405 X(18);
3406 X(1a);
3407 X(1c);
3408 X(1e);
3409 X(24);
3410 X(26);
3411 X(2a);
3412 X(2c);
3413 X(2e);
3414 X(30);
3415 X(32);
3416 X(34);
3418 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3419 pBlk = (char*)pBlk + pBlkEntry[order].len;
3422 if(i != pTypeLibImpl->TypeInfoCount) {
3423 FIXME("Somehow processed %d TypeInfos\n", i);
3424 return NULL;
3427 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3428 return (ITypeLib2*)pTypeLibImpl;
3431 /* ITypeLib::QueryInterface
3433 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3434 ITypeLib2 * iface,
3435 REFIID riid,
3436 VOID **ppvObject)
3438 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3440 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3442 *ppvObject=NULL;
3443 if(IsEqualIID(riid, &IID_IUnknown) ||
3444 IsEqualIID(riid,&IID_ITypeLib)||
3445 IsEqualIID(riid,&IID_ITypeLib2))
3447 *ppvObject = This;
3450 if(*ppvObject)
3452 ITypeLib2_AddRef(iface);
3453 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3454 return S_OK;
3456 TRACE("-- Interface: E_NOINTERFACE\n");
3457 return E_NOINTERFACE;
3460 /* ITypeLib::AddRef
3462 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3464 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3465 ULONG ref = InterlockedIncrement(&This->ref);
3467 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3469 return ref;
3472 /* ITypeLib::Release
3474 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3476 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3477 ULONG ref = InterlockedDecrement(&This->ref);
3479 TRACE("(%p)->(%lu)\n",This, ref);
3481 if (!ref)
3483 /* remove cache entry */
3484 TRACE("removing from cache list\n");
3485 EnterCriticalSection(&cache_section);
3486 if (This->next) This->next->prev = This->prev;
3487 if (This->prev) This->prev->next = This->next;
3488 else tlb_cache_first = This->next;
3489 LeaveCriticalSection(&cache_section);
3491 /* FIXME destroy child objects */
3492 TRACE(" destroying ITypeLib(%p)\n",This);
3494 if (This->Name)
3496 SysFreeString(This->Name);
3497 This->Name = NULL;
3500 if (This->DocString)
3502 SysFreeString(This->DocString);
3503 This->DocString = NULL;
3506 if (This->HelpFile)
3508 SysFreeString(This->HelpFile);
3509 This->HelpFile = NULL;
3512 if (This->HelpStringDll)
3514 SysFreeString(This->HelpStringDll);
3515 This->HelpStringDll = NULL;
3518 if (This->pTypeInfo) /* can be NULL */
3519 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3520 HeapFree(GetProcessHeap(),0,This);
3521 return 0;
3524 return ref;
3527 /* ITypeLib::GetTypeInfoCount
3529 * Returns the number of type descriptions in the type library
3531 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3533 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3534 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3535 return This->TypeInfoCount;
3538 /* ITypeLib::GetTypeInfo
3540 * retrieves the specified type description in the library.
3542 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3543 ITypeLib2 *iface,
3544 UINT index,
3545 ITypeInfo **ppTInfo)
3547 int i;
3549 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3550 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3552 TRACE("(%p)->(index=%d) \n", This, index);
3554 if (!ppTInfo) return E_INVALIDARG;
3556 /* search element n in list */
3557 for(i=0; i < index; i++)
3559 pTypeInfo = pTypeInfo->next;
3560 if (!pTypeInfo)
3562 TRACE("-- element not found\n");
3563 return TYPE_E_ELEMENTNOTFOUND;
3567 *ppTInfo = (ITypeInfo *) pTypeInfo;
3569 ITypeInfo_AddRef(*ppTInfo);
3570 TRACE("-- found (%p)\n",*ppTInfo);
3571 return S_OK;
3575 /* ITypeLibs::GetTypeInfoType
3577 * Retrieves the type of a type description.
3579 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3580 ITypeLib2 *iface,
3581 UINT index,
3582 TYPEKIND *pTKind)
3584 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3585 int i;
3586 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3588 TRACE("(%p) index %d \n",This, index);
3590 if(!pTKind) return E_INVALIDARG;
3592 /* search element n in list */
3593 for(i=0; i < index; i++)
3595 if(!pTInfo)
3597 TRACE("-- element not found\n");
3598 return TYPE_E_ELEMENTNOTFOUND;
3600 pTInfo = pTInfo->next;
3603 *pTKind = pTInfo->TypeAttr.typekind;
3604 TRACE("-- found Type (%d)\n", *pTKind);
3605 return S_OK;
3608 /* ITypeLib::GetTypeInfoOfGuid
3610 * Retrieves the type description that corresponds to the specified GUID.
3613 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3614 ITypeLib2 *iface,
3615 REFGUID guid,
3616 ITypeInfo **ppTInfo)
3618 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3619 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3621 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3623 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3625 /* search linked list for guid */
3626 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3628 pTypeInfo = pTypeInfo->next;
3630 if (!pTypeInfo)
3632 /* end of list reached */
3633 TRACE("-- element not found\n");
3634 return TYPE_E_ELEMENTNOTFOUND;
3638 TRACE("-- found (%p, %s)\n",
3639 pTypeInfo,
3640 debugstr_w(pTypeInfo->Name));
3642 *ppTInfo = (ITypeInfo*)pTypeInfo;
3643 ITypeInfo_AddRef(*ppTInfo);
3644 return S_OK;
3647 /* ITypeLib::GetLibAttr
3649 * Retrieves the structure that contains the library's attributes.
3652 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3653 ITypeLib2 *iface,
3654 LPTLIBATTR *ppTLibAttr)
3656 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3657 TRACE("(%p)\n",This);
3658 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3659 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3660 return S_OK;
3663 /* ITypeLib::GetTypeComp
3665 * Enables a client compiler to bind to a library's types, variables,
3666 * constants, and global functions.
3669 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3670 ITypeLib2 *iface,
3671 ITypeComp **ppTComp)
3673 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3675 TRACE("(%p)->(%p)\n",This,ppTComp);
3676 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3677 ITypeComp_AddRef(*ppTComp);
3679 return S_OK;
3682 /* ITypeLib::GetDocumentation
3684 * Retrieves the library's documentation string, the complete Help file name
3685 * and path, and the context identifier for the library Help topic in the Help
3686 * file.
3688 * On a successful return all non-null BSTR pointers will have been set,
3689 * possibly to NULL.
3691 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3692 ITypeLib2 *iface,
3693 INT index,
3694 BSTR *pBstrName,
3695 BSTR *pBstrDocString,
3696 DWORD *pdwHelpContext,
3697 BSTR *pBstrHelpFile)
3699 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3701 HRESULT result = E_INVALIDARG;
3703 ITypeInfo *pTInfo;
3706 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3707 This, index,
3708 pBstrName, pBstrDocString,
3709 pdwHelpContext, pBstrHelpFile);
3711 if(index<0)
3713 /* documentation for the typelib */
3714 if(pBstrName)
3716 if (This->Name)
3717 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3718 else
3719 *pBstrName = NULL;
3721 if(pBstrDocString)
3723 if (This->DocString)
3724 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3725 else if (This->Name)
3726 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3727 else
3728 *pBstrDocString = NULL;
3730 if(pdwHelpContext)
3732 *pdwHelpContext = This->dwHelpContext;
3734 if(pBstrHelpFile)
3736 if (This->HelpFile)
3737 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3738 else
3739 *pBstrHelpFile = NULL;
3742 result = S_OK;
3744 else
3746 /* for a typeinfo */
3747 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3749 if(SUCCEEDED(result))
3751 result = ITypeInfo_GetDocumentation(pTInfo,
3752 MEMBERID_NIL,
3753 pBstrName,
3754 pBstrDocString,
3755 pdwHelpContext, pBstrHelpFile);
3757 ITypeInfo_Release(pTInfo);
3760 return result;
3761 memerr3:
3762 if (pBstrDocString) SysFreeString (*pBstrDocString);
3763 memerr2:
3764 if (pBstrName) SysFreeString (*pBstrName);
3765 memerr1:
3766 return STG_E_INSUFFICIENTMEMORY;
3769 /* ITypeLib::IsName
3771 * Indicates whether a passed-in string contains the name of a type or member
3772 * described in the library.
3775 static HRESULT WINAPI ITypeLib2_fnIsName(
3776 ITypeLib2 *iface,
3777 LPOLESTR szNameBuf,
3778 ULONG lHashVal,
3779 BOOL *pfName)
3781 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3782 ITypeInfoImpl *pTInfo;
3783 TLBFuncDesc *pFInfo;
3784 TLBVarDesc *pVInfo;
3785 int i;
3786 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3788 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3789 pfName);
3791 *pfName=TRUE;
3792 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3793 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3794 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3795 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3796 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3797 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3798 goto ITypeLib2_fnIsName_exit;
3800 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3801 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3804 *pfName=FALSE;
3806 ITypeLib2_fnIsName_exit:
3807 TRACE("(%p)slow! search for %s: %s found!\n", This,
3808 debugstr_w(szNameBuf), *pfName?"NOT":"");
3810 return S_OK;
3813 /* ITypeLib::FindName
3815 * Finds occurrences of a type description in a type library. This may be used
3816 * to quickly verify that a name exists in a type library.
3819 static HRESULT WINAPI ITypeLib2_fnFindName(
3820 ITypeLib2 *iface,
3821 LPOLESTR szNameBuf,
3822 ULONG lHashVal,
3823 ITypeInfo **ppTInfo,
3824 MEMBERID *rgMemId,
3825 UINT16 *pcFound)
3827 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3828 ITypeInfoImpl *pTInfo;
3829 TLBFuncDesc *pFInfo;
3830 TLBVarDesc *pVInfo;
3831 int i,j = 0;
3832 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3834 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3835 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3836 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3837 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3838 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3839 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3840 goto ITypeLib2_fnFindName_exit;
3843 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3844 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3845 continue;
3846 ITypeLib2_fnFindName_exit:
3847 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3848 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3849 j++;
3851 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3852 This, *pcFound, debugstr_w(szNameBuf), j);
3854 *pcFound=j;
3856 return S_OK;
3859 /* ITypeLib::ReleaseTLibAttr
3861 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3864 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3865 ITypeLib2 *iface,
3866 TLIBATTR *pTLibAttr)
3868 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3869 TRACE("freeing (%p)\n",This);
3870 HeapFree(GetProcessHeap(),0,pTLibAttr);
3874 /* ITypeLib2::GetCustData
3876 * gets the custom data
3878 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3879 ITypeLib2 * iface,
3880 REFGUID guid,
3881 VARIANT *pVarVal)
3883 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3884 TLBCustData *pCData;
3886 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3888 if( IsEqualIID(guid, &pCData->guid)) break;
3891 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3893 if(pCData)
3895 VariantInit( pVarVal);
3896 VariantCopy( pVarVal, &pCData->data);
3897 return S_OK;
3899 return E_INVALIDARG; /* FIXME: correct? */
3902 /* ITypeLib2::GetLibStatistics
3904 * Returns statistics about a type library that are required for efficient
3905 * sizing of hash tables.
3908 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3909 ITypeLib2 * iface,
3910 ULONG *pcUniqueNames,
3911 ULONG *pcchUniqueNames)
3913 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3915 FIXME("(%p): stub!\n", This);
3917 if(pcUniqueNames) *pcUniqueNames=1;
3918 if(pcchUniqueNames) *pcchUniqueNames=1;
3919 return S_OK;
3922 /* ITypeLib2::GetDocumentation2
3924 * Retrieves the library's documentation string, the complete Help file name
3925 * and path, the localization context to use, and the context ID for the
3926 * library Help topic in the Help file.
3929 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3930 ITypeLib2 * iface,
3931 INT index,
3932 LCID lcid,
3933 BSTR *pbstrHelpString,
3934 DWORD *pdwHelpStringContext,
3935 BSTR *pbstrHelpStringDll)
3937 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3938 HRESULT result;
3939 ITypeInfo *pTInfo;
3941 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3943 /* the help string should be obtained from the helpstringdll,
3944 * using the _DLLGetDocumentation function, based on the supplied
3945 * lcid. Nice to do sometime...
3947 if(index<0)
3949 /* documentation for the typelib */
3950 if(pbstrHelpString)
3951 *pbstrHelpString=SysAllocString(This->DocString);
3952 if(pdwHelpStringContext)
3953 *pdwHelpStringContext=This->dwHelpContext;
3954 if(pbstrHelpStringDll)
3955 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3957 result = S_OK;
3959 else
3961 /* for a typeinfo */
3962 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3964 if(SUCCEEDED(result))
3966 ITypeInfo2 * pTInfo2;
3967 result = ITypeInfo_QueryInterface(pTInfo,
3968 &IID_ITypeInfo2,
3969 (LPVOID*) &pTInfo2);
3971 if(SUCCEEDED(result))
3973 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3974 MEMBERID_NIL,
3975 lcid,
3976 pbstrHelpString,
3977 pdwHelpStringContext,
3978 pbstrHelpStringDll);
3980 ITypeInfo2_Release(pTInfo2);
3983 ITypeInfo_Release(pTInfo);
3986 return result;
3989 /* ITypeLib2::GetAllCustData
3991 * Gets all custom data items for the library.
3994 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3995 ITypeLib2 * iface,
3996 CUSTDATA *pCustData)
3998 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3999 TLBCustData *pCData;
4000 int i;
4001 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4002 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4003 if(pCustData->prgCustData ){
4004 pCustData->cCustData=This->ctCustData;
4005 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4006 pCustData->prgCustData[i].guid=pCData->guid;
4007 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4009 }else{
4010 ERR(" OUT OF MEMORY! \n");
4011 return E_OUTOFMEMORY;
4013 return S_OK;
4016 static const ITypeLib2Vtbl tlbvt = {
4017 ITypeLib2_fnQueryInterface,
4018 ITypeLib2_fnAddRef,
4019 ITypeLib2_fnRelease,
4020 ITypeLib2_fnGetTypeInfoCount,
4021 ITypeLib2_fnGetTypeInfo,
4022 ITypeLib2_fnGetTypeInfoType,
4023 ITypeLib2_fnGetTypeInfoOfGuid,
4024 ITypeLib2_fnGetLibAttr,
4025 ITypeLib2_fnGetTypeComp,
4026 ITypeLib2_fnGetDocumentation,
4027 ITypeLib2_fnIsName,
4028 ITypeLib2_fnFindName,
4029 ITypeLib2_fnReleaseTLibAttr,
4031 ITypeLib2_fnGetCustData,
4032 ITypeLib2_fnGetLibStatistics,
4033 ITypeLib2_fnGetDocumentation2,
4034 ITypeLib2_fnGetAllCustData
4038 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4040 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4042 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
4045 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4047 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4049 return ITypeInfo_AddRef((ITypeInfo *)This);
4052 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4054 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4056 return ITypeInfo_Release((ITypeInfo *)This);
4059 static HRESULT WINAPI ITypeLibComp_fnBind(
4060 ITypeComp * iface,
4061 OLECHAR * szName,
4062 ULONG lHash,
4063 WORD wFlags,
4064 ITypeInfo ** ppTInfo,
4065 DESCKIND * pDescKind,
4066 BINDPTR * pBindPtr)
4068 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4069 return E_NOTIMPL;
4072 static HRESULT WINAPI ITypeLibComp_fnBindType(
4073 ITypeComp * iface,
4074 OLECHAR * szName,
4075 ULONG lHash,
4076 ITypeInfo ** ppTInfo,
4077 ITypeComp ** ppTComp)
4079 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4080 return E_NOTIMPL;
4083 static const ITypeCompVtbl tlbtcvt =
4086 ITypeLibComp_fnQueryInterface,
4087 ITypeLibComp_fnAddRef,
4088 ITypeLibComp_fnRelease,
4090 ITypeLibComp_fnBind,
4091 ITypeLibComp_fnBindType
4094 /*================== ITypeInfo(2) Methods ===================================*/
4095 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4097 ITypeInfoImpl * pTypeInfoImpl;
4099 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4100 if (pTypeInfoImpl)
4102 pTypeInfoImpl->lpVtbl = &tinfvt;
4103 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4104 pTypeInfoImpl->ref=1;
4106 TRACE("(%p)\n", pTypeInfoImpl);
4107 return (ITypeInfo2*) pTypeInfoImpl;
4110 /* ITypeInfo::QueryInterface
4112 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4113 ITypeInfo2 *iface,
4114 REFIID riid,
4115 VOID **ppvObject)
4117 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4119 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4121 *ppvObject=NULL;
4122 if(IsEqualIID(riid, &IID_IUnknown) ||
4123 IsEqualIID(riid,&IID_ITypeInfo)||
4124 IsEqualIID(riid,&IID_ITypeInfo2))
4125 *ppvObject = This;
4127 if(*ppvObject){
4128 ITypeInfo_AddRef(iface);
4129 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4130 return S_OK;
4132 TRACE("-- Interface: E_NOINTERFACE\n");
4133 return E_NOINTERFACE;
4136 /* ITypeInfo::AddRef
4138 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4140 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4141 ULONG ref = InterlockedIncrement(&This->ref);
4143 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4145 TRACE("(%p)->ref is %lu\n",This, ref);
4146 return ref;
4149 /* ITypeInfo::Release
4151 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4153 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4154 ULONG ref = InterlockedDecrement(&This->ref);
4156 TRACE("(%p)->(%lu)\n",This, ref);
4158 if (ref) {
4159 /* We don't release ITypeLib when ref=0 because
4160 it means that function is called by ITypeLib2_Release */
4161 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4162 } else {
4163 FIXME("destroy child objects\n");
4165 TRACE("destroying ITypeInfo(%p)\n",This);
4166 if (This->Name)
4168 SysFreeString(This->Name);
4169 This->Name = 0;
4172 if (This->DocString)
4174 SysFreeString(This->DocString);
4175 This->DocString = 0;
4178 if (This->next)
4180 ITypeInfo_Release((ITypeInfo*)This->next);
4183 HeapFree(GetProcessHeap(),0,This);
4184 return 0;
4186 return ref;
4189 /* ITypeInfo::GetTypeAttr
4191 * Retrieves a TYPEATTR structure that contains the attributes of the type
4192 * description.
4195 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4196 LPTYPEATTR *ppTypeAttr)
4198 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4199 TRACE("(%p)\n",This);
4200 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr));
4201 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4203 if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */
4204 copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias);
4206 if((*ppTypeAttr)->typekind == TKIND_DISPATCH && (*ppTypeAttr)->wTypeFlags & TYPEFLAG_FDUAL) {
4207 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4208 funcs */
4209 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4210 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4212 return S_OK;
4215 /* ITypeInfo::GetTypeComp
4217 * Retrieves the ITypeComp interface for the type description, which enables a
4218 * client compiler to bind to the type description's members.
4221 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4222 ITypeComp * *ppTComp)
4224 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4226 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4228 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4229 ITypeComp_AddRef(*ppTComp);
4230 return S_OK;
4233 /* ITypeInfo::GetFuncDesc
4235 * Retrieves the FUNCDESC structure that contains information about a
4236 * specified function.
4239 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4240 LPFUNCDESC *ppFuncDesc)
4242 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4243 int i;
4244 TLBFuncDesc * pFDesc;
4245 TRACE("(%p) index %d\n", This, index);
4246 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4248 if(pFDesc){
4249 /* FIXME: must do a copy here */
4250 *ppFuncDesc=&pFDesc->funcdesc;
4251 return S_OK;
4253 return E_INVALIDARG;
4256 /* ITypeInfo::GetVarDesc
4258 * Retrieves a VARDESC structure that describes the specified variable.
4261 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4262 LPVARDESC *ppVarDesc)
4264 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4265 int i;
4266 TLBVarDesc * pVDesc;
4267 TRACE("(%p) index %d\n", This, index);
4268 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4270 if(pVDesc){
4271 /* FIXME: must do a copy here */
4272 *ppVarDesc=&pVDesc->vardesc;
4273 return S_OK;
4275 return E_INVALIDARG;
4278 /* ITypeInfo_GetNames
4280 * Retrieves the variable with the specified member ID (or the name of the
4281 * property or method and its parameters) that correspond to the specified
4282 * function ID.
4284 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4285 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4287 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4288 TLBFuncDesc * pFDesc;
4289 TLBVarDesc * pVDesc;
4290 int i;
4291 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4292 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4293 if(pFDesc)
4295 /* function found, now return function and parameter names */
4296 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4298 if(!i)
4299 *rgBstrNames=SysAllocString(pFDesc->Name);
4300 else
4301 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4303 *pcNames=i;
4305 else
4307 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4308 if(pVDesc)
4310 *rgBstrNames=SysAllocString(pVDesc->Name);
4311 *pcNames=1;
4313 else
4315 if(This->TypeAttr.cImplTypes &&
4316 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4317 /* recursive search */
4318 ITypeInfo *pTInfo;
4319 HRESULT result;
4320 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4321 &pTInfo);
4322 if(SUCCEEDED(result))
4324 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4325 ITypeInfo_Release(pTInfo);
4326 return result;
4328 WARN("Could not search inherited interface!\n");
4330 else
4332 WARN("no names found\n");
4334 *pcNames=0;
4335 return TYPE_E_ELEMENTNOTFOUND;
4338 return S_OK;
4342 /* ITypeInfo::GetRefTypeOfImplType
4344 * If a type description describes a COM class, it retrieves the type
4345 * description of the implemented interface types. For an interface,
4346 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4347 * if any exist.
4350 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4351 ITypeInfo2 *iface,
4352 UINT index,
4353 HREFTYPE *pRefType)
4355 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4356 int(i);
4357 TLBImplType *pImpl = This->impltypelist;
4359 TRACE("(%p) index %d\n", This, index);
4360 if (TRACE_ON(ole)) dump_TypeInfo(This);
4362 if(index==(UINT)-1)
4364 /* only valid on dual interfaces;
4365 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4367 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4369 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4370 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4372 *pRefType = -1;
4374 else
4376 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4377 *pRefType = pImpl->hRef;
4380 else
4382 /* get element n from linked list */
4383 for(i=0; pImpl && i<index; i++)
4385 pImpl = pImpl->next;
4388 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4390 *pRefType = pImpl->hRef;
4392 TRACE("-- 0x%08lx\n", pImpl->hRef );
4395 return S_OK;
4399 /* ITypeInfo::GetImplTypeFlags
4401 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4402 * or base interface in a type description.
4404 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4405 UINT index, INT *pImplTypeFlags)
4407 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4408 int i;
4409 TLBImplType *pImpl;
4411 TRACE("(%p) index %d\n", This, index);
4412 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4413 i++, pImpl=pImpl->next)
4415 if(i==index && pImpl){
4416 *pImplTypeFlags=pImpl->implflags;
4417 return S_OK;
4419 *pImplTypeFlags=0;
4420 return TYPE_E_ELEMENTNOTFOUND;
4423 /* GetIDsOfNames
4424 * Maps between member names and member IDs, and parameter names and
4425 * parameter IDs.
4427 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4428 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4430 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4431 TLBFuncDesc * pFDesc;
4432 TLBVarDesc * pVDesc;
4433 HRESULT ret=S_OK;
4435 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4436 cNames);
4437 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4438 int i, j;
4439 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4440 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4441 for(i=1; i < cNames; i++){
4442 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4443 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4444 break;
4445 if( j<pFDesc->funcdesc.cParams)
4446 pMemId[i]=j;
4447 else
4448 ret=DISP_E_UNKNOWNNAME;
4450 return ret;
4453 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4454 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4455 if(cNames) *pMemId=pVDesc->vardesc.memid;
4456 return ret;
4459 /* not found, see if this is and interface with an inheritance */
4460 if(This->TypeAttr.cImplTypes &&
4461 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4462 /* recursive search */
4463 ITypeInfo *pTInfo;
4464 ret=ITypeInfo_GetRefTypeInfo(iface,
4465 This->impltypelist->hRef, &pTInfo);
4466 if(SUCCEEDED(ret)){
4467 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4468 ITypeInfo_Release(pTInfo);
4469 return ret;
4471 WARN("Could not search inherited interface!\n");
4472 } else
4473 WARN("no names found\n");
4474 return DISP_E_UNKNOWNNAME;
4477 /* ITypeInfo::Invoke
4479 * Invokes a method, or accesses a property of an object, that implements the
4480 * interface described by the type description.
4482 DWORD
4483 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4484 DWORD res;
4486 if (TRACE_ON(ole)) {
4487 int i;
4488 TRACE("Calling %p(",func);
4489 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4490 TRACE(")\n");
4493 switch (callconv) {
4494 case CC_STDCALL:
4496 switch (nrargs) {
4497 case 0:
4498 res = func();
4499 break;
4500 case 1:
4501 res = func(args[0]);
4502 break;
4503 case 2:
4504 res = func(args[0],args[1]);
4505 break;
4506 case 3:
4507 res = func(args[0],args[1],args[2]);
4508 break;
4509 case 4:
4510 res = func(args[0],args[1],args[2],args[3]);
4511 break;
4512 case 5:
4513 res = func(args[0],args[1],args[2],args[3],args[4]);
4514 break;
4515 case 6:
4516 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4517 break;
4518 case 7:
4519 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4520 break;
4521 case 8:
4522 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4523 break;
4524 case 9:
4525 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4526 break;
4527 case 10:
4528 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4529 break;
4530 case 11:
4531 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4532 break;
4533 default:
4534 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4535 res = -1;
4536 break;
4538 break;
4539 default:
4540 FIXME("unsupported calling convention %d\n",callconv);
4541 res = -1;
4542 break;
4544 TRACE("returns %08lx\n",res);
4545 return res;
4548 extern int _argsize(DWORD vt);
4550 /****************************************************************************
4551 * Helper functions for Dispcall / Invoke, which copies one variant
4552 * with target type onto the argument stack.
4554 static HRESULT
4555 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4556 DWORD *argpos, VARIANT *arg, VARTYPE vt
4558 UINT arglen = _argsize(vt)*sizeof(DWORD);
4559 VARIANT va;
4561 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4562 memcpy(argpos,&arg,sizeof(void*));
4563 return S_OK;
4566 if (V_VT(arg) == vt) {
4567 memcpy(argpos, &V_I4(arg), arglen);
4568 return S_OK;
4571 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4572 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4573 return S_OK;
4576 if (vt == VT_VARIANT) {
4577 memcpy(argpos, arg, arglen);
4578 return S_OK;
4580 /* Deref BYREF vars if there is need */
4581 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4582 memcpy(argpos,(void*)V_I4(arg), arglen);
4583 return S_OK;
4585 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4586 /* in this context, if the type lib specifies IUnknown*, giving an
4587 IDispatch* is correct; so, don't invoke VariantChangeType */
4588 memcpy(argpos,&V_I4(arg), arglen);
4589 return S_OK;
4591 if ((vt == VT_PTR) && tdesc)
4592 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4594 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4595 ITypeInfo *tinfo2 = NULL;
4596 TYPEATTR *tattr = NULL;
4597 HRESULT hres;
4599 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4600 if (hres) {
4601 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4602 "while coercing from vt 0x%x. Copying 4 byte.\n",
4603 tdesc->u.hreftype,V_VT(arg));
4604 memcpy(argpos, &V_I4(arg), 4);
4605 return S_OK;
4607 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4608 if( hres )
4610 ERR("GetTypeAttr failed\n");
4611 ITypeInfo_Release(tinfo2);
4612 return hres;
4614 switch (tattr->typekind) {
4615 case TKIND_ENUM:
4616 switch ( V_VT( arg ) ) {
4617 case VT_I2:
4618 *argpos = V_I2(arg);
4619 hres = S_OK;
4620 break;
4621 case VT_I4:
4622 memcpy(argpos, &V_I4(arg), 4);
4623 hres = S_OK;
4624 break;
4625 default:
4626 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4627 hres = E_FAIL;
4628 break;
4630 break;
4632 case TKIND_ALIAS:
4633 tdesc = &(tattr->tdescAlias);
4634 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4635 break;
4637 case TKIND_INTERFACE:
4638 if (V_VT(arg) == VT_DISPATCH) {
4639 IDispatch *disp;
4640 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4641 memcpy(argpos, &V_DISPATCH(arg), 4);
4642 hres = S_OK;
4643 break;
4645 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4646 &IID_IDispatch,(LPVOID*)&disp);
4647 if (SUCCEEDED(hres)) {
4648 memcpy(argpos,&disp,4);
4649 IUnknown_Release(V_DISPATCH(arg));
4650 hres = S_OK;
4651 break;
4653 FIXME("Failed to query IDispatch interface from %s while "
4654 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4655 hres = E_FAIL;
4656 break;
4658 if (V_VT(arg) == VT_UNKNOWN) {
4659 memcpy(argpos, &V_UNKNOWN(arg), 4);
4660 hres = S_OK;
4661 break;
4663 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4664 V_VT(arg),debugstr_guid(&(tattr->guid)));
4665 hres = E_FAIL;
4666 break;
4668 case TKIND_DISPATCH:
4669 if (V_VT(arg) == VT_DISPATCH) {
4670 memcpy(argpos, &V_DISPATCH(arg), 4);
4671 hres = S_OK;
4673 else {
4674 hres = E_FAIL;
4675 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4677 break;
4678 case TKIND_RECORD:
4679 FIXME("TKIND_RECORD unhandled.\n");
4680 hres = E_FAIL;
4681 break;
4682 default:
4683 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4684 hres = E_FAIL;
4685 break;
4687 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4688 ITypeInfo_Release(tinfo2);
4689 return hres;
4692 VariantInit(&va);
4693 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4694 memcpy(argpos,&V_I4(&va), arglen);
4695 FIXME("Should not use VariantChangeType here."
4696 " (conversion from 0x%x -> 0x%x) %08lx\n",
4697 V_VT(arg), vt, *argpos
4699 return S_OK;
4701 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4702 return E_FAIL;
4705 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
4707 HRESULT hr = S_OK;
4708 ITypeInfo *tinfo2 = NULL;
4709 TYPEATTR *tattr = NULL;
4711 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4712 if (hr)
4714 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4715 "hr = 0x%08lx\n",
4716 tdesc->u.hreftype, hr);
4717 return hr;
4719 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4720 if (hr)
4722 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4723 ITypeInfo_Release(tinfo2);
4724 return hr;
4727 switch (tattr->typekind)
4729 case TKIND_ENUM:
4730 *vt |= VT_INT;
4731 break;
4733 case TKIND_ALIAS:
4734 tdesc = &tattr->tdescAlias;
4735 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4736 break;
4738 case TKIND_INTERFACE:
4739 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4740 *vt |= VT_DISPATCH;
4741 else
4742 *vt |= VT_UNKNOWN;
4743 break;
4745 case TKIND_DISPATCH:
4746 *vt |= VT_DISPATCH;
4747 break;
4749 case TKIND_RECORD:
4750 FIXME("TKIND_RECORD unhandled.\n");
4751 hr = E_NOTIMPL;
4752 break;
4754 case TKIND_UNION:
4755 FIXME("TKIND_RECORD unhandled.\n");
4756 hr = E_NOTIMPL;
4757 break;
4759 default:
4760 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4761 hr = E_NOTIMPL;
4762 break;
4764 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4765 ITypeInfo_Release(tinfo2);
4766 return hr;
4769 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
4771 HRESULT hr = S_OK;
4773 /* enforce only one level of pointer indirection */
4774 if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
4776 tdesc = tdesc->u.lptdesc;
4778 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4779 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4780 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4781 if ((tdesc->vt == VT_USERDEFINED) ||
4782 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4784 VARTYPE vt_userdefined = 0;
4785 TYPEDESC *tdesc_userdefined = tdesc;
4786 if (tdesc->vt == VT_PTR)
4788 vt_userdefined = VT_BYREF;
4789 tdesc_userdefined = tdesc->u.lptdesc;
4791 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
4792 if (!hr && ((vt_userdefined == VT_UNKNOWN) || (vt_userdefined == VT_DISPATCH)))
4794 *vt |= vt_userdefined;
4795 return S_OK;
4798 *vt = VT_BYREF;
4801 switch (tdesc->vt)
4803 case VT_HRESULT:
4804 *vt |= VT_ERROR;
4805 break;
4806 case VT_USERDEFINED:
4807 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
4808 break;
4809 default:
4810 *vt |= tdesc->vt;
4811 break;
4813 return hr;
4816 /***********************************************************************
4817 * DispCallFunc (OLEAUT32.@)
4819 HRESULT WINAPI
4820 DispCallFunc(
4821 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4822 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4824 int i, argsize, argspos;
4825 DWORD *args;
4826 HRESULT hres;
4828 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4829 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4831 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4832 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4833 argsize = 1;
4834 for (i=0;i<cActuals;i++) {
4835 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4836 dump_Variant(prgpvarg[i]);
4837 argsize += _argsize(prgvt[i]);
4839 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4840 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4841 argspos = 1;
4842 for (i=0;i<cActuals;i++) {
4843 VARIANT *arg = prgpvarg[i];
4844 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4845 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4846 argspos += _argsize(prgvt[i]);
4849 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4851 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4852 hres=S_OK;
4854 else
4856 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4857 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4858 FIXME("Method returned %lx\n",hres);
4860 HeapFree(GetProcessHeap(),0,args);
4861 return hres;
4864 static HRESULT WINAPI ITypeInfo_fnInvoke(
4865 ITypeInfo2 *iface,
4866 VOID *pIUnk,
4867 MEMBERID memid,
4868 UINT16 dwFlags,
4869 DISPPARAMS *pDispParams,
4870 VARIANT *pVarResult,
4871 EXCEPINFO *pExcepInfo,
4872 UINT *pArgErr)
4874 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4875 int i;
4876 unsigned int func_index, var_index;
4877 TYPEKIND type_kind;
4878 HRESULT hres;
4880 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4881 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4883 dump_DispParms(pDispParams);
4885 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4886 if (SUCCEEDED(hres)) {
4887 FUNCDESC *func_desc;
4889 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4890 if(FAILED(hres)) return hres;
4891 if (TRACE_ON(ole))
4893 TRACE("invoking:\n");
4894 dump_FUNCDESC(func_desc);
4897 switch (func_desc->funckind) {
4898 case FUNC_PUREVIRTUAL:
4899 case FUNC_VIRTUAL: {
4900 DWORD res;
4901 int numargs, numargs2, argspos, args2pos;
4902 DWORD *args , *args2;
4903 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4904 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4906 hres = S_OK;
4907 numargs = 1; /* sizeof(thisptr) */
4908 numargs2 = 0;
4909 for (i = 0; i < func_desc->cParams; i++) {
4910 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4912 numargs += _argsize(tdesc->vt);
4913 if (i>=pDispParams->cArgs) { /* arguments to return */
4914 if (tdesc->vt == VT_PTR) {
4915 numargs2 += _argsize(tdesc->u.lptdesc->vt);
4916 } else {
4917 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
4918 numargs2 += _argsize(tdesc->vt);
4923 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4924 args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
4926 args[0] = (DWORD)pIUnk;
4927 argspos = 1; args2pos = 0;
4928 for (i = 0; i < func_desc->cParams; i++) {
4929 ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
4930 TYPEDESC *tdesc = &(elemdesc->tdesc);
4931 USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
4932 int arglen = _argsize(tdesc->vt);
4934 if (i<pDispParams->cArgs) {
4935 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4937 if (paramFlags & PARAMFLAG_FOPT) {
4938 if(i < func_desc->cParams - func_desc->cParamsOpt)
4939 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4940 if(V_VT(arg) == VT_EMPTY
4941 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
4942 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4943 How to determine it? */
4945 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4946 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4947 V_VT(arg) = VT_ERROR;
4948 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4949 arglen = _argsize(VT_ERROR);
4952 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4953 if (FAILED(hres)) goto func_fail;
4954 argspos += arglen;
4955 } else if (paramFlags & PARAMFLAG_FOPT) {
4956 VARIANT *arg = &rgvarg[i];
4958 if (i < func_desc->cParams - func_desc->cParamsOpt)
4959 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4960 if (paramFlags & PARAMFLAG_FHASDEFAULT)
4961 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4963 V_VT(arg) = VT_ERROR;
4964 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4965 arglen = _argsize(VT_ERROR);
4966 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4967 if (FAILED(hres)) goto func_fail;
4968 argspos += arglen;
4969 } else {
4970 if (tdesc->vt == VT_PTR)
4971 arglen = _argsize(tdesc->u.lptdesc->vt);
4972 else
4973 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4975 /* Supply pointers for the rest, so propertyget works*/
4976 args[argspos] = (DWORD)&args2[args2pos];
4978 /* If pointer to variant, pass reference it. */
4979 if ((tdesc->vt == VT_PTR) &&
4980 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4981 pVarResult
4983 args[argspos]= (DWORD)pVarResult;
4984 argspos += 1;
4985 args2pos += arglen;
4988 if (func_desc->cParamsOpt < 0)
4989 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
4991 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
4992 func_desc->callconv,
4993 numargs,
4994 args
4997 if (pVarResult) {
4998 for (i = 0; i < func_desc->cParams; i++) {
4999 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5000 if (wParamFlags & PARAMFLAG_FRETVAL) {
5001 ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
5002 TYPEDESC *tdesc = &elemdesc->tdesc;
5003 VARIANTARG varresult;
5004 V_VT(&varresult) = 0;
5005 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
5006 if (hres)
5007 break;
5008 /* FIXME: this is really messy - we should keep the
5009 * args in VARIANTARGs rather than a DWORD array */
5010 memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
5011 hres = VariantCopyInd(pVarResult, &varresult);
5012 break;
5016 func_fail:
5017 HeapFree(GetProcessHeap(), 0, rgvarg);
5018 HeapFree(GetProcessHeap(),0,args2);
5019 HeapFree(GetProcessHeap(),0,args);
5020 break;
5022 case FUNC_DISPATCH: {
5023 IDispatch *disp;
5025 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5026 if (SUCCEEDED(hres)) {
5027 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5028 hres = IDispatch_Invoke(
5029 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
5030 pVarResult,pExcepInfo,pArgErr
5032 if (FAILED(hres))
5033 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5034 IDispatch_Release(disp);
5035 } else
5036 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5037 break;
5039 default:
5040 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5041 hres = E_FAIL;
5042 break;
5045 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
5046 return hres;
5048 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5049 VARDESC *var_desc;
5051 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5052 if(FAILED(hres)) return hres;
5054 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5055 dump_VARDESC(var_desc);
5056 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5057 return E_NOTIMPL;
5060 /* not found, look for it in inherited interfaces */
5061 ITypeInfo2_GetTypeKind(iface, &type_kind);
5062 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5063 HREFTYPE ref_type;
5064 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5065 /* recursive search */
5066 ITypeInfo *pTInfo;
5067 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5068 if(SUCCEEDED(hres)){
5069 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5070 ITypeInfo_Release(pTInfo);
5071 return hres;
5073 WARN("Could not search inherited interface!\n");
5076 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
5077 return DISP_E_MEMBERNOTFOUND;
5080 /* ITypeInfo::GetDocumentation
5082 * Retrieves the documentation string, the complete Help file name and path,
5083 * and the context ID for the Help topic for a specified type description.
5085 * (Can be tested by the Visual Basic Editor in Word for instance.)
5087 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5088 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5089 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5091 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5092 TLBFuncDesc * pFDesc;
5093 TLBVarDesc * pVDesc;
5094 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5095 " HelpContext(%p) HelpFile(%p)\n",
5096 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5097 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5098 if(pBstrName)
5099 *pBstrName=SysAllocString(This->Name);
5100 if(pBstrDocString)
5101 *pBstrDocString=SysAllocString(This->DocString);
5102 if(pdwHelpContext)
5103 *pdwHelpContext=This->dwHelpContext;
5104 if(pBstrHelpFile)
5105 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5106 return S_OK;
5107 }else {/* for a member */
5108 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5109 if(pFDesc->funcdesc.memid==memid){
5110 if(pBstrName)
5111 *pBstrName = SysAllocString(pFDesc->Name);
5112 if(pBstrDocString)
5113 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5114 if(pdwHelpContext)
5115 *pdwHelpContext=pFDesc->helpcontext;
5116 return S_OK;
5118 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5119 if(pVDesc->vardesc.memid==memid){
5120 if(pBstrName)
5121 *pBstrName = SysAllocString(pVDesc->Name);
5122 if(pBstrDocString)
5123 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5124 if(pdwHelpContext)
5125 *pdwHelpContext=pVDesc->HelpContext;
5126 return S_OK;
5129 return TYPE_E_ELEMENTNOTFOUND;
5132 /* ITypeInfo::GetDllEntry
5134 * Retrieves a description or specification of an entry point for a function
5135 * in a DLL.
5137 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5138 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5139 WORD *pwOrdinal)
5141 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5142 TLBFuncDesc *pFDesc;
5144 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5146 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5147 if(pFDesc->funcdesc.memid==memid){
5148 dump_TypeInfo(This);
5149 dump_TLBFuncDescOne(pFDesc);
5151 /* FIXME: This is wrong, but how do you find that out? */
5152 if (pBstrDllName) {
5153 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5154 *pBstrDllName = SysAllocString(oleaut32W);
5157 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5158 if (pBstrName)
5159 *pBstrName = SysAllocString(pFDesc->Entry);
5160 if (pwOrdinal)
5161 *pwOrdinal = -1;
5162 return S_OK;
5164 if (pBstrName)
5165 *pBstrName = NULL;
5166 if (pwOrdinal)
5167 *pwOrdinal = (DWORD)pFDesc->Entry;
5168 return S_OK;
5170 return E_FAIL;
5173 /* ITypeInfo::GetRefTypeInfo
5175 * If a type description references other type descriptions, it retrieves
5176 * the referenced type descriptions.
5178 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5179 ITypeInfo2 *iface,
5180 HREFTYPE hRefType,
5181 ITypeInfo **ppTInfo)
5183 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5184 HRESULT result = E_FAIL;
5186 if (hRefType == -1 &&
5187 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5188 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5190 /* when we meet a DUAL dispinterface, we must create the interface
5191 * version of it.
5193 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5196 /* the interface version contains the same information as the dispinterface
5197 * copy the contents of the structs.
5199 *pTypeInfoImpl = *This;
5200 pTypeInfoImpl->ref = 1;
5202 /* change the type to interface */
5203 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5205 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5207 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5209 result = S_OK;
5211 } else {
5212 TLBRefType *pRefType;
5213 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5214 if(pRefType->reference == hRefType)
5215 break;
5217 if(!pRefType)
5218 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5219 if(pRefType && hRefType != -1) {
5220 ITypeLib *pTLib = NULL;
5222 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5223 int Index;
5224 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5225 } else {
5226 if(pRefType->pImpTLInfo->pImpTypeLib) {
5227 TRACE("typeinfo in imported typelib that is already loaded\n");
5228 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5229 ITypeLib2_AddRef((ITypeLib*) pTLib);
5230 result = S_OK;
5231 } else {
5232 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5233 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5234 pRefType->pImpTLInfo->wVersionMajor,
5235 pRefType->pImpTLInfo->wVersionMinor,
5236 pRefType->pImpTLInfo->lcid,
5237 &pTLib);
5239 if(!SUCCEEDED(result)) {
5240 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5241 result=LoadTypeLib(libnam, &pTLib);
5242 SysFreeString(libnam);
5244 if(SUCCEEDED(result)) {
5245 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5246 ITypeLib2_AddRef(pTLib);
5250 if(SUCCEEDED(result)) {
5251 if(pRefType->index == TLB_REF_USE_GUID)
5252 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5253 &pRefType->guid,
5254 ppTInfo);
5255 else
5256 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5257 ppTInfo);
5259 if (pTLib != NULL)
5260 ITypeLib2_Release(pTLib);
5264 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5265 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5266 return result;
5269 /* ITypeInfo::AddressOfMember
5271 * Retrieves the addresses of static functions or variables, such as those
5272 * defined in a DLL.
5274 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5275 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5277 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5278 FIXME("(%p) stub!\n", This);
5279 return S_OK;
5282 /* ITypeInfo::CreateInstance
5284 * Creates a new instance of a type that describes a component object class
5285 * (coclass).
5287 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5288 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5290 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5291 FIXME("(%p) stub!\n", This);
5292 return S_OK;
5295 /* ITypeInfo::GetMops
5297 * Retrieves marshalling information.
5299 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5300 BSTR *pBstrMops)
5302 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5303 FIXME("(%p) stub!\n", This);
5304 return S_OK;
5307 /* ITypeInfo::GetContainingTypeLib
5309 * Retrieves the containing type library and the index of the type description
5310 * within that type library.
5312 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5313 ITypeLib * *ppTLib, UINT *pIndex)
5315 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5317 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5318 if (pIndex) {
5319 *pIndex=This->index;
5320 TRACE("returning pIndex=%d\n", *pIndex);
5323 if (ppTLib) {
5324 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5325 ITypeLib2_AddRef(*ppTLib);
5326 TRACE("returning ppTLib=%p\n", *ppTLib);
5329 return S_OK;
5332 /* ITypeInfo::ReleaseTypeAttr
5334 * Releases a TYPEATTR previously returned by GetTypeAttr.
5337 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5338 TYPEATTR* pTypeAttr)
5340 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5341 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5342 if(This->TypeAttr.typekind == TKIND_ALIAS)
5343 free_deep_typedesc(&pTypeAttr->tdescAlias);
5344 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5347 /* ITypeInfo::ReleaseFuncDesc
5349 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5351 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5352 ITypeInfo2 *iface,
5353 FUNCDESC *pFuncDesc)
5355 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5356 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5359 /* ITypeInfo::ReleaseVarDesc
5361 * Releases a VARDESC previously returned by GetVarDesc.
5363 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5364 VARDESC *pVarDesc)
5366 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5367 TRACE("(%p)->(%p)\n", This, pVarDesc);
5370 /* ITypeInfo2::GetTypeKind
5372 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5375 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5376 TYPEKIND *pTypeKind)
5378 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5379 *pTypeKind=This->TypeAttr.typekind;
5380 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5381 return S_OK;
5384 /* ITypeInfo2::GetTypeFlags
5386 * Returns the type flags without any allocations. This returns a DWORD type
5387 * flag, which expands the type flags without growing the TYPEATTR (type
5388 * attribute).
5391 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5393 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5394 *pTypeFlags=This->TypeAttr.wTypeFlags;
5395 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5396 return S_OK;
5399 /* ITypeInfo2::GetFuncIndexOfMemId
5400 * Binds to a specific member based on a known DISPID, where the member name
5401 * is not known (for example, when binding to a default member).
5404 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5405 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5407 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5408 TLBFuncDesc *pFuncInfo;
5409 int i;
5410 HRESULT result;
5412 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5413 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5414 break;
5415 if(pFuncInfo) {
5416 *pFuncIndex = i;
5417 result = S_OK;
5418 } else
5419 result = TYPE_E_ELEMENTNOTFOUND;
5421 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5422 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5423 return result;
5426 /* TypeInfo2::GetVarIndexOfMemId
5428 * Binds to a specific member based on a known DISPID, where the member name
5429 * is not known (for example, when binding to a default member).
5432 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5433 MEMBERID memid, UINT *pVarIndex)
5435 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5436 TLBVarDesc *pVarInfo;
5437 int i;
5438 HRESULT result;
5439 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5440 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5442 if(pVarInfo) {
5443 *pVarIndex = i;
5444 result = S_OK;
5445 } else
5446 result = TYPE_E_ELEMENTNOTFOUND;
5448 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5449 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5450 return result;
5453 /* ITypeInfo2::GetCustData
5455 * Gets the custom data
5457 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5458 ITypeInfo2 * iface,
5459 REFGUID guid,
5460 VARIANT *pVarVal)
5462 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5463 TLBCustData *pCData;
5465 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5466 if( IsEqualIID(guid, &pCData->guid)) break;
5468 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5470 if(pCData)
5472 VariantInit( pVarVal);
5473 VariantCopy( pVarVal, &pCData->data);
5474 return S_OK;
5476 return E_INVALIDARG; /* FIXME: correct? */
5479 /* ITypeInfo2::GetFuncCustData
5481 * Gets the custom data
5483 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5484 ITypeInfo2 * iface,
5485 UINT index,
5486 REFGUID guid,
5487 VARIANT *pVarVal)
5489 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5490 TLBCustData *pCData=NULL;
5491 TLBFuncDesc * pFDesc;
5492 int i;
5493 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5494 pFDesc=pFDesc->next);
5496 if(pFDesc)
5497 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5498 if( IsEqualIID(guid, &pCData->guid)) break;
5500 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5502 if(pCData){
5503 VariantInit( pVarVal);
5504 VariantCopy( pVarVal, &pCData->data);
5505 return S_OK;
5507 return E_INVALIDARG; /* FIXME: correct? */
5510 /* ITypeInfo2::GetParamCustData
5512 * Gets the custom data
5514 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5515 ITypeInfo2 * iface,
5516 UINT indexFunc,
5517 UINT indexParam,
5518 REFGUID guid,
5519 VARIANT *pVarVal)
5521 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5522 TLBCustData *pCData=NULL;
5523 TLBFuncDesc * pFDesc;
5524 int i;
5526 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5528 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5529 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5530 pCData = pCData->next)
5531 if( IsEqualIID(guid, &pCData->guid)) break;
5533 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5535 if(pCData)
5537 VariantInit( pVarVal);
5538 VariantCopy( pVarVal, &pCData->data);
5539 return S_OK;
5541 return E_INVALIDARG; /* FIXME: correct? */
5544 /* ITypeInfo2::GetVarCustData
5546 * Gets the custom data
5548 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5549 ITypeInfo2 * iface,
5550 UINT index,
5551 REFGUID guid,
5552 VARIANT *pVarVal)
5554 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5555 TLBCustData *pCData=NULL;
5556 TLBVarDesc * pVDesc;
5557 int i;
5559 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5561 if(pVDesc)
5563 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5565 if( IsEqualIID(guid, &pCData->guid)) break;
5569 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5571 if(pCData)
5573 VariantInit( pVarVal);
5574 VariantCopy( pVarVal, &pCData->data);
5575 return S_OK;
5577 return E_INVALIDARG; /* FIXME: correct? */
5580 /* ITypeInfo2::GetImplCustData
5582 * Gets the custom data
5584 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5585 ITypeInfo2 * iface,
5586 UINT index,
5587 REFGUID guid,
5588 VARIANT *pVarVal)
5590 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5591 TLBCustData *pCData=NULL;
5592 TLBImplType * pRDesc;
5593 int i;
5595 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5597 if(pRDesc)
5599 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5601 if( IsEqualIID(guid, &pCData->guid)) break;
5605 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5607 if(pCData)
5609 VariantInit( pVarVal);
5610 VariantCopy( pVarVal, &pCData->data);
5611 return S_OK;
5613 return E_INVALIDARG; /* FIXME: correct? */
5616 /* ITypeInfo2::GetDocumentation2
5618 * Retrieves the documentation string, the complete Help file name and path,
5619 * the localization context to use, and the context ID for the library Help
5620 * topic in the Help file.
5623 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5624 ITypeInfo2 * iface,
5625 MEMBERID memid,
5626 LCID lcid,
5627 BSTR *pbstrHelpString,
5628 DWORD *pdwHelpStringContext,
5629 BSTR *pbstrHelpStringDll)
5631 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5632 TLBFuncDesc * pFDesc;
5633 TLBVarDesc * pVDesc;
5634 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5635 "HelpStringContext(%p) HelpStringDll(%p)\n",
5636 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5637 pbstrHelpStringDll );
5638 /* the help string should be obtained from the helpstringdll,
5639 * using the _DLLGetDocumentation function, based on the supplied
5640 * lcid. Nice to do sometime...
5642 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5643 if(pbstrHelpString)
5644 *pbstrHelpString=SysAllocString(This->Name);
5645 if(pdwHelpStringContext)
5646 *pdwHelpStringContext=This->dwHelpStringContext;
5647 if(pbstrHelpStringDll)
5648 *pbstrHelpStringDll=
5649 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5650 return S_OK;
5651 }else {/* for a member */
5652 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5653 if(pFDesc->funcdesc.memid==memid){
5654 if(pbstrHelpString)
5655 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5656 if(pdwHelpStringContext)
5657 *pdwHelpStringContext=pFDesc->HelpStringContext;
5658 if(pbstrHelpStringDll)
5659 *pbstrHelpStringDll=
5660 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5661 return S_OK;
5663 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5664 if(pVDesc->vardesc.memid==memid){
5665 if(pbstrHelpString)
5666 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5667 if(pdwHelpStringContext)
5668 *pdwHelpStringContext=pVDesc->HelpStringContext;
5669 if(pbstrHelpStringDll)
5670 *pbstrHelpStringDll=
5671 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5672 return S_OK;
5675 return TYPE_E_ELEMENTNOTFOUND;
5678 /* ITypeInfo2::GetAllCustData
5680 * Gets all custom data items for the Type info.
5683 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5684 ITypeInfo2 * iface,
5685 CUSTDATA *pCustData)
5687 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5688 TLBCustData *pCData;
5689 int i;
5691 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5693 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5694 if(pCustData->prgCustData ){
5695 pCustData->cCustData=This->ctCustData;
5696 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5697 pCustData->prgCustData[i].guid=pCData->guid;
5698 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5700 }else{
5701 ERR(" OUT OF MEMORY! \n");
5702 return E_OUTOFMEMORY;
5704 return S_OK;
5707 /* ITypeInfo2::GetAllFuncCustData
5709 * Gets all custom data items for the specified Function
5712 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5713 ITypeInfo2 * iface,
5714 UINT index,
5715 CUSTDATA *pCustData)
5717 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5718 TLBCustData *pCData;
5719 TLBFuncDesc * pFDesc;
5720 int i;
5721 TRACE("(%p) index %d\n", This, index);
5722 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5723 pFDesc=pFDesc->next)
5725 if(pFDesc){
5726 pCustData->prgCustData =
5727 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5728 if(pCustData->prgCustData ){
5729 pCustData->cCustData=pFDesc->ctCustData;
5730 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5731 pCData = pCData->next){
5732 pCustData->prgCustData[i].guid=pCData->guid;
5733 VariantCopy(& pCustData->prgCustData[i].varValue,
5734 & pCData->data);
5736 }else{
5737 ERR(" OUT OF MEMORY! \n");
5738 return E_OUTOFMEMORY;
5740 return S_OK;
5742 return TYPE_E_ELEMENTNOTFOUND;
5745 /* ITypeInfo2::GetAllParamCustData
5747 * Gets all custom data items for the Functions
5750 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5751 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5753 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5754 TLBCustData *pCData=NULL;
5755 TLBFuncDesc * pFDesc;
5756 int i;
5757 TRACE("(%p) index %d\n", This, indexFunc);
5758 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5759 pFDesc=pFDesc->next)
5761 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5762 pCustData->prgCustData =
5763 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5764 sizeof(CUSTDATAITEM));
5765 if(pCustData->prgCustData ){
5766 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5767 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5768 pCData; i++, pCData = pCData->next){
5769 pCustData->prgCustData[i].guid=pCData->guid;
5770 VariantCopy(& pCustData->prgCustData[i].varValue,
5771 & pCData->data);
5773 }else{
5774 ERR(" OUT OF MEMORY! \n");
5775 return E_OUTOFMEMORY;
5777 return S_OK;
5779 return TYPE_E_ELEMENTNOTFOUND;
5782 /* ITypeInfo2::GetAllVarCustData
5784 * Gets all custom data items for the specified Variable
5787 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5788 UINT index, CUSTDATA *pCustData)
5790 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5791 TLBCustData *pCData;
5792 TLBVarDesc * pVDesc;
5793 int i;
5794 TRACE("(%p) index %d\n", This, index);
5795 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5796 pVDesc=pVDesc->next)
5798 if(pVDesc){
5799 pCustData->prgCustData =
5800 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5801 if(pCustData->prgCustData ){
5802 pCustData->cCustData=pVDesc->ctCustData;
5803 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5804 pCData = pCData->next){
5805 pCustData->prgCustData[i].guid=pCData->guid;
5806 VariantCopy(& pCustData->prgCustData[i].varValue,
5807 & pCData->data);
5809 }else{
5810 ERR(" OUT OF MEMORY! \n");
5811 return E_OUTOFMEMORY;
5813 return S_OK;
5815 return TYPE_E_ELEMENTNOTFOUND;
5818 /* ITypeInfo2::GetAllImplCustData
5820 * Gets all custom data items for the specified implementation type
5823 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5824 ITypeInfo2 * iface,
5825 UINT index,
5826 CUSTDATA *pCustData)
5828 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5829 TLBCustData *pCData;
5830 TLBImplType * pRDesc;
5831 int i;
5832 TRACE("(%p) index %d\n", This, index);
5833 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5834 pRDesc=pRDesc->next)
5836 if(pRDesc){
5837 pCustData->prgCustData =
5838 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5839 if(pCustData->prgCustData ){
5840 pCustData->cCustData=pRDesc->ctCustData;
5841 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5842 pCData = pCData->next){
5843 pCustData->prgCustData[i].guid=pCData->guid;
5844 VariantCopy(& pCustData->prgCustData[i].varValue,
5845 & pCData->data);
5847 }else{
5848 ERR(" OUT OF MEMORY! \n");
5849 return E_OUTOFMEMORY;
5851 return S_OK;
5853 return TYPE_E_ELEMENTNOTFOUND;
5856 static const ITypeInfo2Vtbl tinfvt =
5859 ITypeInfo_fnQueryInterface,
5860 ITypeInfo_fnAddRef,
5861 ITypeInfo_fnRelease,
5863 ITypeInfo_fnGetTypeAttr,
5864 ITypeInfo_fnGetTypeComp,
5865 ITypeInfo_fnGetFuncDesc,
5866 ITypeInfo_fnGetVarDesc,
5867 ITypeInfo_fnGetNames,
5868 ITypeInfo_fnGetRefTypeOfImplType,
5869 ITypeInfo_fnGetImplTypeFlags,
5870 ITypeInfo_fnGetIDsOfNames,
5871 ITypeInfo_fnInvoke,
5872 ITypeInfo_fnGetDocumentation,
5873 ITypeInfo_fnGetDllEntry,
5874 ITypeInfo_fnGetRefTypeInfo,
5875 ITypeInfo_fnAddressOfMember,
5876 ITypeInfo_fnCreateInstance,
5877 ITypeInfo_fnGetMops,
5878 ITypeInfo_fnGetContainingTypeLib,
5879 ITypeInfo_fnReleaseTypeAttr,
5880 ITypeInfo_fnReleaseFuncDesc,
5881 ITypeInfo_fnReleaseVarDesc,
5883 ITypeInfo2_fnGetTypeKind,
5884 ITypeInfo2_fnGetTypeFlags,
5885 ITypeInfo2_fnGetFuncIndexOfMemId,
5886 ITypeInfo2_fnGetVarIndexOfMemId,
5887 ITypeInfo2_fnGetCustData,
5888 ITypeInfo2_fnGetFuncCustData,
5889 ITypeInfo2_fnGetParamCustData,
5890 ITypeInfo2_fnGetVarCustData,
5891 ITypeInfo2_fnGetImplTypeCustData,
5892 ITypeInfo2_fnGetDocumentation2,
5893 ITypeInfo2_fnGetAllCustData,
5894 ITypeInfo2_fnGetAllFuncCustData,
5895 ITypeInfo2_fnGetAllParamCustData,
5896 ITypeInfo2_fnGetAllVarCustData,
5897 ITypeInfo2_fnGetAllImplTypeCustData,
5900 /******************************************************************************
5901 * CreateDispTypeInfo [OLEAUT32.31]
5903 * Build type information for an object so it can be called through an
5904 * IDispatch interface.
5906 * RETURNS
5907 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5908 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5910 * NOTES
5911 * This call allows an objects methods to be accessed through IDispatch, by
5912 * building an ITypeInfo object that IDispatch can use to call through.
5914 HRESULT WINAPI CreateDispTypeInfo(
5915 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5916 LCID lcid, /* [I] Locale Id */
5917 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5919 ITypeInfoImpl *pTIImpl;
5920 int param, func;
5921 TLBFuncDesc **ppFuncDesc;
5923 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5924 pTIImpl->pTypeLib = NULL;
5925 pTIImpl->index = 0;
5926 pTIImpl->Name = NULL;
5927 pTIImpl->dwHelpContext = -1;
5928 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
5929 pTIImpl->TypeAttr.lcid = lcid;
5930 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
5931 pTIImpl->TypeAttr.wMajorVerNum = 0;
5932 pTIImpl->TypeAttr.wMinorVerNum = 0;
5933 pTIImpl->TypeAttr.cbAlignment = 2;
5934 pTIImpl->TypeAttr.cbSizeInstance = -1;
5935 pTIImpl->TypeAttr.cbSizeVft = -1;
5936 pTIImpl->TypeAttr.cFuncs = 0;
5937 pTIImpl->TypeAttr.cImplTypes = 1;
5938 pTIImpl->TypeAttr.cVars = 0;
5939 pTIImpl->TypeAttr.wTypeFlags = 0;
5941 ppFuncDesc = &pTIImpl->funclist;
5942 for(func = 0; func < pidata->cMembers; func++) {
5943 METHODDATA *md = pidata->pmethdata + func;
5944 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
5945 (*ppFuncDesc)->Name = SysAllocString(md->szName);
5946 (*ppFuncDesc)->funcdesc.memid = md->dispid;
5947 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
5948 (*ppFuncDesc)->funcdesc.callconv = md->cc;
5949 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
5950 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
5951 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
5952 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
5953 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
5954 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5955 md->cArgs * sizeof(ELEMDESC));
5956 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5957 md->cArgs * sizeof(TLBParDesc));
5958 for(param = 0; param < md->cArgs; param++) {
5959 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
5960 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
5962 ppFuncDesc = &(*ppFuncDesc)->next;
5964 *pptinfo = (ITypeInfo*)pTIImpl;
5965 return S_OK;
5969 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5971 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5973 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5976 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5978 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5980 return ITypeInfo_AddRef((ITypeInfo *)This);
5983 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5985 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5987 return ITypeInfo_Release((ITypeInfo *)This);
5990 static HRESULT WINAPI ITypeComp_fnBind(
5991 ITypeComp * iface,
5992 OLECHAR * szName,
5993 ULONG lHash,
5994 WORD wFlags,
5995 ITypeInfo ** ppTInfo,
5996 DESCKIND * pDescKind,
5997 BINDPTR * pBindPtr)
5999 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
6000 TLBFuncDesc * pFDesc;
6001 TLBVarDesc * pVDesc;
6003 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6005 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6006 if (pFDesc->funcdesc.invkind & wFlags)
6007 if (!strcmpW(pFDesc->Name, szName)) {
6008 break;
6011 if (pFDesc)
6013 *pDescKind = DESCKIND_FUNCDESC;
6014 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
6015 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6016 return S_OK;
6017 } else {
6018 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
6020 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6021 if (!strcmpW(pVDesc->Name, szName)) {
6022 *pDescKind = DESCKIND_VARDESC;
6023 pBindPtr->lpvardesc = &pVDesc->vardesc;
6024 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6025 return S_OK;
6030 /* not found, look for it in inherited interfaces */
6031 if (This->TypeAttr.cImplTypes &&
6032 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
6033 /* recursive search */
6034 ITypeInfo *pTInfo;
6035 ITypeComp *pTComp;
6036 HRESULT hr;
6037 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6038 if (SUCCEEDED(hr))
6040 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6041 ITypeInfo_Release(pTInfo);
6043 if (SUCCEEDED(hr))
6045 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6046 ITypeComp_Release(pTComp);
6047 return hr;
6049 WARN("Could not search inherited interface!\n");
6051 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6052 *pDescKind = DESCKIND_NONE;
6053 pBindPtr->lpfuncdesc = NULL;
6054 *ppTInfo = NULL;
6055 return DISP_E_MEMBERNOTFOUND;
6058 static HRESULT WINAPI ITypeComp_fnBindType(
6059 ITypeComp * iface,
6060 OLECHAR * szName,
6061 ULONG lHash,
6062 ITypeInfo ** ppTInfo,
6063 ITypeComp ** ppTComp)
6065 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6067 /* strange behaviour (does nothing) but like the
6068 * original */
6070 if (!ppTInfo || !ppTComp)
6071 return E_POINTER;
6073 *ppTInfo = NULL;
6074 *ppTComp = NULL;
6076 return S_OK;
6079 static const ITypeCompVtbl tcompvt =
6082 ITypeComp_fnQueryInterface,
6083 ITypeComp_fnAddRef,
6084 ITypeComp_fnRelease,
6086 ITypeComp_fnBind,
6087 ITypeComp_fnBindType