- Read DLL name from modules in MSFT typelibs.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob17d929ef014de469e2f9ad0c9279223210325015
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 LONG 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");
622 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
624 /* register interface<->typelib coupling */
625 get_interface_key( &tattr->guid, keyName );
626 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
627 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
629 if (name)
630 RegSetValueExW(key, NULL, 0, REG_SZ,
631 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
633 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
634 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
635 RegSetValueExW(subKey, NULL, 0, REG_SZ,
636 (BYTE*)PSOA, sizeof PSOA);
637 RegCloseKey(subKey);
640 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
641 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
642 RegSetValueExW(subKey, NULL, 0, REG_SZ,
643 (BYTE*)PSOA, sizeof PSOA);
644 RegCloseKey(subKey);
647 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
648 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
650 WCHAR buffer[40];
651 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
652 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
654 StringFromGUID2(&attr->guid, buffer, 40);
655 RegSetValueExW(subKey, NULL, 0, REG_SZ,
656 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
657 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
658 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
659 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
660 RegCloseKey(subKey);
663 RegCloseKey(key);
667 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
670 ITypeInfo_Release(tinfo);
673 SysFreeString(name);
677 ITypeLib_ReleaseTLibAttr(ptlib, attr);
679 return res;
683 /******************************************************************************
684 * UnRegisterTypeLib [OLEAUT32.186]
685 * Removes information about a type library from the System Registry
686 * NOTES
688 * RETURNS
689 * Success: S_OK
690 * Failure: Status
692 HRESULT WINAPI UnRegisterTypeLib(
693 REFGUID libid, /* [in] Guid of the library */
694 WORD wVerMajor, /* [in] major version */
695 WORD wVerMinor, /* [in] minor version */
696 LCID lcid, /* [in] locale id */
697 SYSKIND syskind)
699 BSTR tlibPath = NULL;
700 DWORD tmpLength;
701 WCHAR keyName[60];
702 WCHAR subKeyName[50];
703 int result = S_OK;
704 DWORD i = 0;
705 BOOL deleteOtherStuff;
706 HKEY key = NULL;
707 HKEY subKey = NULL;
708 TYPEATTR* typeAttr = NULL;
709 TYPEKIND kind;
710 ITypeInfo* typeInfo = NULL;
711 ITypeLib* typeLib = NULL;
712 int numTypes;
714 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
716 /* Create the path to the key */
717 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
719 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
721 TRACE("Unsupported syskind %i\n", syskind);
722 result = E_INVALIDARG;
723 goto end;
726 /* get the path to the typelib on disk */
727 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
728 result = E_INVALIDARG;
729 goto end;
732 /* Try and open the key to the type library. */
733 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
734 result = E_INVALIDARG;
735 goto end;
738 /* Try and load the type library */
739 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
740 result = TYPE_E_INVALIDSTATE;
741 goto end;
744 /* remove any types registered with this typelib */
745 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
746 for (i=0; i<numTypes; i++) {
747 /* get the kind of type */
748 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
749 goto enddeleteloop;
752 /* skip non-interfaces, and get type info for the type */
753 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
754 goto enddeleteloop;
756 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
757 goto enddeleteloop;
759 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
760 goto enddeleteloop;
763 /* the path to the type */
764 get_interface_key( &typeAttr->guid, subKeyName );
766 /* Delete its bits */
767 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
768 goto enddeleteloop;
770 RegDeleteKeyW(subKey, ProxyStubClsidW);
771 RegDeleteKeyW(subKey, ProxyStubClsid32W);
772 RegDeleteKeyW(subKey, TypeLibW);
773 RegCloseKey(subKey);
774 subKey = NULL;
775 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
777 enddeleteloop:
778 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
779 typeAttr = NULL;
780 if (typeInfo) ITypeInfo_Release(typeInfo);
781 typeInfo = NULL;
784 /* Now, delete the type library path subkey */
785 get_lcid_subkey( lcid, syskind, subKeyName );
786 RegDeleteKeyW(key, subKeyName);
787 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
788 RegDeleteKeyW(key, subKeyName);
790 /* check if there is anything besides the FLAGS/HELPDIR keys.
791 If there is, we don't delete them */
792 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
793 deleteOtherStuff = TRUE;
794 i = 0;
795 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
796 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
798 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
799 if (!strcmpW(subKeyName, FLAGSW)) continue;
800 if (!strcmpW(subKeyName, HELPDIRW)) continue;
801 deleteOtherStuff = FALSE;
802 break;
805 /* only delete the other parts of the key if we're absolutely sure */
806 if (deleteOtherStuff) {
807 RegDeleteKeyW(key, FLAGSW);
808 RegDeleteKeyW(key, HELPDIRW);
809 RegCloseKey(key);
810 key = NULL;
812 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
813 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
814 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
817 end:
818 if (tlibPath) SysFreeString(tlibPath);
819 if (typeLib) ITypeLib_Release(typeLib);
820 if (subKey) RegCloseKey(subKey);
821 if (key) RegCloseKey(key);
822 return result;
825 /*======================= ITypeLib implementation =======================*/
827 typedef struct tagTLBCustData
829 GUID guid;
830 VARIANT data;
831 struct tagTLBCustData* next;
832 } TLBCustData;
834 /* data structure for import typelibs */
835 typedef struct tagTLBImpLib
837 int offset; /* offset in the file (MSFT)
838 offset in nametable (SLTG)
839 just used to identify library while reading
840 data from file */
841 GUID guid; /* libid */
842 BSTR name; /* name */
844 LCID lcid; /* lcid of imported typelib */
846 WORD wVersionMajor; /* major version number */
847 WORD wVersionMinor; /* minor version number */
849 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
850 NULL if not yet loaded */
851 struct tagTLBImpLib * next;
852 } TLBImpLib;
854 /* internal ITypeLib data */
855 typedef struct tagITypeLibImpl
857 const ITypeLib2Vtbl *lpVtbl;
858 const ITypeCompVtbl *lpVtblTypeComp;
859 LONG ref;
860 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
862 /* strings can be stored in tlb as multibyte strings BUT they are *always*
863 * exported to the application as a UNICODE string.
865 BSTR Name;
866 BSTR DocString;
867 BSTR HelpFile;
868 BSTR HelpStringDll;
869 unsigned long dwHelpContext;
870 int TypeInfoCount; /* nr of typeinfo's in librarry */
871 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
872 int ctCustData; /* number of items in cust data list */
873 TLBCustData * pCustData; /* linked list to cust data */
874 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
875 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
876 libary. Only used while read MSFT
877 typelibs */
879 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
880 struct tagITypeLibImpl *next, *prev;
881 WCHAR *path;
882 INT index;
883 } ITypeLibImpl;
885 static const ITypeLib2Vtbl tlbvt;
886 static const ITypeCompVtbl tlbtcvt;
888 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
890 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
893 /* ITypeLib methods */
894 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
895 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
897 /*======================= ITypeInfo implementation =======================*/
899 /* data for referenced types */
900 typedef struct tagTLBRefType
902 INT index; /* Type index for internal ref or for external ref
903 it the format is SLTG. -2 indicates to
904 use guid */
906 GUID guid; /* guid of the referenced type */
907 /* if index == TLB_REF_USE_GUID */
909 HREFTYPE reference; /* The href of this ref */
910 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
911 TLB_REF_INTERNAL for internal refs
912 TLB_REF_NOT_FOUND for broken refs */
914 struct tagTLBRefType * next;
915 } TLBRefType;
917 #define TLB_REF_USE_GUID -2
919 #define TLB_REF_INTERNAL (void*)-2
920 #define TLB_REF_NOT_FOUND (void*)-1
922 /* internal Parameter data */
923 typedef struct tagTLBParDesc
925 BSTR Name;
926 int ctCustData;
927 TLBCustData * pCustData; /* linked list to cust data */
928 } TLBParDesc;
930 /* internal Function data */
931 typedef struct tagTLBFuncDesc
933 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
934 BSTR Name; /* the name of this function */
935 TLBParDesc *pParamDesc; /* array with param names and custom data */
936 int helpcontext;
937 int HelpStringContext;
938 BSTR HelpString;
939 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
940 int ctCustData;
941 TLBCustData * pCustData; /* linked list to cust data; */
942 struct tagTLBFuncDesc * next;
943 } TLBFuncDesc;
945 /* internal Variable data */
946 typedef struct tagTLBVarDesc
948 VARDESC vardesc; /* lots of info on the variable and its attributes. */
949 BSTR Name; /* the name of this variable */
950 int HelpContext;
951 int HelpStringContext; /* FIXME: where? */
952 BSTR HelpString;
953 int ctCustData;
954 TLBCustData * pCustData;/* linked list to cust data; */
955 struct tagTLBVarDesc * next;
956 } TLBVarDesc;
958 /* internal implemented interface data */
959 typedef struct tagTLBImplType
961 HREFTYPE hRef; /* hRef of interface */
962 int implflags; /* IMPLFLAG_*s */
963 int ctCustData;
964 TLBCustData * pCustData;/* linked list to custom data; */
965 struct tagTLBImplType *next;
966 } TLBImplType;
968 /* internal TypeInfo data */
969 typedef struct tagITypeInfoImpl
971 const ITypeInfo2Vtbl *lpVtbl;
972 const ITypeCompVtbl *lpVtblTypeComp;
973 LONG ref;
974 TYPEATTR TypeAttr ; /* _lots_ of type information. */
975 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
976 int index; /* index in this typelib; */
977 /* type libs seem to store the doc strings in ascii
978 * so why should we do it in unicode?
980 BSTR Name;
981 BSTR DocString;
982 BSTR DllName;
983 unsigned long dwHelpContext;
984 unsigned long dwHelpStringContext;
986 /* functions */
987 TLBFuncDesc * funclist; /* linked list with function descriptions */
989 /* variables */
990 TLBVarDesc * varlist; /* linked list with variable descriptions */
992 /* Implemented Interfaces */
993 TLBImplType * impltypelist;
995 TLBRefType * reflist;
996 int ctCustData;
997 TLBCustData * pCustData; /* linked list to cust data; */
998 struct tagITypeInfoImpl * next;
999 } ITypeInfoImpl;
1001 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1003 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1006 static const ITypeInfo2Vtbl tinfvt;
1007 static const ITypeCompVtbl tcompvt;
1009 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1011 typedef struct tagTLBContext
1013 unsigned int oStart; /* start of TLB in file */
1014 unsigned int pos; /* current pos */
1015 unsigned int length; /* total length */
1016 void *mapping; /* memory mapping */
1017 MSFT_SegDir * pTblDir;
1018 ITypeLibImpl* pLibInfo;
1019 } TLBContext;
1022 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1025 debug
1027 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1028 if (pTD->vt & VT_RESERVED)
1029 szVarType += strlen(strcpy(szVarType, "reserved | "));
1030 if (pTD->vt & VT_BYREF)
1031 szVarType += strlen(strcpy(szVarType, "ref to "));
1032 if (pTD->vt & VT_ARRAY)
1033 szVarType += strlen(strcpy(szVarType, "array of "));
1034 if (pTD->vt & VT_VECTOR)
1035 szVarType += strlen(strcpy(szVarType, "vector of "));
1036 switch(pTD->vt & VT_TYPEMASK) {
1037 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1038 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1039 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1040 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1041 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1042 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1043 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1044 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1045 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1046 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1047 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1048 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1049 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1050 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1051 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1052 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1053 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1054 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1055 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1056 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1057 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1058 pTD->u.hreftype); break;
1059 case VT_PTR: sprintf(szVarType, "ptr to ");
1060 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1061 break;
1062 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1063 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1064 break;
1065 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1066 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1067 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1068 break;
1070 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1074 static void dump_ELEMDESC(ELEMDESC *edesc) {
1075 char buf[200];
1076 dump_TypeDesc(&edesc->tdesc,buf);
1077 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1078 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
1079 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1081 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
1082 int i;
1083 MESSAGE("memid is %08lx\n",funcdesc->memid);
1084 for (i=0;i<funcdesc->cParams;i++) {
1085 MESSAGE("Param %d:\n",i);
1086 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1088 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1089 switch (funcdesc->funckind) {
1090 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1091 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1092 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1093 case FUNC_STATIC: MESSAGE("static");break;
1094 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1095 default: MESSAGE("unknown");break;
1097 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1098 switch (funcdesc->invkind) {
1099 case INVOKE_FUNC: MESSAGE("func");break;
1100 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1101 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1102 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1104 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1105 switch (funcdesc->callconv) {
1106 case CC_CDECL: MESSAGE("cdecl");break;
1107 case CC_PASCAL: MESSAGE("pascal");break;
1108 case CC_STDCALL: MESSAGE("stdcall");break;
1109 case CC_SYSCALL: MESSAGE("syscall");break;
1110 default:break;
1112 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1113 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1114 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1116 MESSAGE("\telemdescFunc (return value type):\n");
1117 dump_ELEMDESC(&funcdesc->elemdescFunc);
1120 static const char * typekind_desc[] =
1122 "TKIND_ENUM",
1123 "TKIND_RECORD",
1124 "TKIND_MODULE",
1125 "TKIND_INTERFACE",
1126 "TKIND_DISPATCH",
1127 "TKIND_COCLASS",
1128 "TKIND_ALIAS",
1129 "TKIND_UNION",
1130 "TKIND_MAX"
1133 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1135 int i;
1136 if (!TRACE_ON(typelib))
1137 return;
1138 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1139 for (i=0;i<pfd->funcdesc.cParams;i++)
1140 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1143 dump_FUNCDESC(&(pfd->funcdesc));
1145 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1146 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1148 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1150 while (pfd)
1152 dump_TLBFuncDescOne(pfd);
1153 pfd = pfd->next;
1156 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1158 while (pvd)
1160 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1161 pvd = pvd->next;
1165 static void dump_TLBImpLib(TLBImpLib *import)
1167 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1168 debugstr_w(import->name));
1169 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1170 import->wVersionMinor, import->lcid, import->offset);
1173 static void dump_TLBRefType(TLBRefType * prt)
1175 while (prt)
1177 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1178 if(prt->index == -1)
1179 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1180 else
1181 TRACE_(typelib)("type no: %d\n", prt->index);
1183 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1184 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1185 TRACE_(typelib)("in lib\n");
1186 dump_TLBImpLib(prt->pImpTLInfo);
1188 prt = prt->next;
1192 static void dump_TLBImplType(TLBImplType * impl)
1194 while (impl) {
1195 TRACE_(typelib)(
1196 "implementing/inheriting interface hRef = %lx implflags %x\n",
1197 impl->hRef, impl->implflags);
1198 impl = impl->next;
1202 void dump_Variant(VARIANT * pvar)
1204 SYSTEMTIME st;
1206 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1208 if (pvar)
1210 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1211 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1213 TRACE(",%p", V_BYREF(pvar));
1215 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1217 TRACE(",FIXME");
1219 else switch (V_TYPE(pvar))
1221 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1222 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1223 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1224 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1225 case VT_INT:
1226 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1227 case VT_UINT:
1228 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1229 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1230 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1231 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1232 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1233 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1234 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1235 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1236 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1237 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1238 V_CY(pvar).s.Lo); break;
1239 case VT_DATE:
1240 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1241 TRACE(",<invalid>");
1242 else
1243 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1244 st.wHour, st.wMinute, st.wSecond);
1245 break;
1246 case VT_ERROR:
1247 case VT_VOID:
1248 case VT_USERDEFINED:
1249 case VT_EMPTY:
1250 case VT_NULL: break;
1251 default: TRACE(",?"); break;
1254 TRACE("}\n");
1257 static void dump_DispParms(DISPPARAMS * pdp)
1259 int index = 0;
1261 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1263 while (index < pdp->cArgs)
1265 dump_Variant( &pdp->rgvarg[index] );
1266 ++index;
1270 static void dump_TypeInfo(ITypeInfoImpl * pty)
1272 TRACE("%p ref=%lu\n", pty, pty->ref);
1273 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1274 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1275 TRACE("fct:%u var:%u impl:%u\n",
1276 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1277 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1278 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1279 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1280 dump_TLBFuncDesc(pty->funclist);
1281 dump_TLBVarDesc(pty->varlist);
1282 dump_TLBImplType(pty->impltypelist);
1285 static void dump_VARDESC(VARDESC *v)
1287 MESSAGE("memid %ld\n",v->memid);
1288 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1289 MESSAGE("oInst %ld\n",v->u.oInst);
1290 dump_ELEMDESC(&(v->elemdescVar));
1291 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1292 MESSAGE("varkind %d\n",v->varkind);
1295 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1297 /* VT_LPWSTR is largest type that */
1298 /* may appear in type description*/
1299 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1300 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1301 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1302 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1303 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1304 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1305 {{0},30},{{0},31}
1308 static void TLB_abort(void)
1310 DebugBreak();
1312 static void * TLB_Alloc(unsigned size)
1314 void * ret;
1315 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1316 /* FIXME */
1317 ERR("cannot allocate memory\n");
1319 return ret;
1322 static void TLB_Free(void * ptr)
1324 HeapFree(GetProcessHeap(), 0, ptr);
1327 /* deep copy a typedesc */
1328 static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in)
1330 out->vt = in->vt;
1331 switch(in->vt) {
1332 case VT_PTR:
1333 out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC));
1334 copy_typedesc(out->u.lptdesc, in->u.lptdesc);
1335 break;
1336 case VT_USERDEFINED:
1337 out->u.hreftype = in->u.hreftype;
1338 break;
1339 case VT_CARRAY:
1340 out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) +
1341 (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND));
1342 copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem);
1343 out->u.lpadesc->cDims = in->u.lpadesc->cDims;
1344 memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND));
1345 break;
1346 default:
1347 break;
1351 /* free()s any allocated memory pointed to by the tdesc. NB does not
1352 free the tdesc itself - this is because the tdesc is typically part
1353 of a larger structure */
1354 static void free_deep_typedesc(TYPEDESC *tdesc)
1356 switch(tdesc->vt) {
1357 case VT_PTR:
1358 free_deep_typedesc(tdesc->u.lptdesc);
1359 HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc);
1360 tdesc->u.lptdesc = NULL;
1361 break;
1362 case VT_CARRAY:
1363 free_deep_typedesc(&tdesc->u.lpadesc->tdescElem);
1364 HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc);
1365 tdesc->u.lpadesc = NULL;
1366 break;
1367 default:
1368 break;
1372 /**********************************************************************
1374 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1376 /* read function */
1377 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1379 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1380 pcx->pos, count, pcx->oStart, pcx->length, where);
1382 if (where != DO_NOT_SEEK)
1384 where += pcx->oStart;
1385 if (where > pcx->length)
1387 /* FIXME */
1388 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1389 TLB_abort();
1391 pcx->pos = where;
1393 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1394 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1395 pcx->pos += count;
1396 return count;
1399 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1400 long where )
1402 DWORD ret;
1404 ret = MSFT_Read(buffer, count, pcx, where);
1405 FromLEDWords(buffer, ret);
1407 return ret;
1410 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1411 long where )
1413 DWORD ret;
1415 ret = MSFT_Read(buffer, count, pcx, where);
1416 FromLEWords(buffer, ret);
1418 return ret;
1421 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1423 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1424 memset(pGuid,0, sizeof(GUID));
1425 return;
1427 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1428 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1429 pGuid->Data2 = FromLEWord(pGuid->Data2);
1430 pGuid->Data3 = FromLEWord(pGuid->Data3);
1431 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1434 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1436 char * name;
1437 MSFT_NameIntro niName;
1438 int lengthInChars;
1439 WCHAR* pwstring = NULL;
1440 BSTR bstrName = NULL;
1442 if (offset < 0)
1444 ERR_(typelib)("bad offset %d\n", offset);
1445 return NULL;
1447 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1448 pcx->pTblDir->pNametab.offset+offset);
1449 niName.namelen &= 0xFF; /* FIXME: correct ? */
1450 name=TLB_Alloc((niName.namelen & 0xff) +1);
1451 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1452 name[niName.namelen & 0xff]='\0';
1454 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1455 name, -1, NULL, 0);
1457 /* no invalid characters in string */
1458 if (lengthInChars)
1460 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1462 /* don't check for invalid character since this has been done previously */
1463 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1465 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1466 lengthInChars = SysStringLen(bstrName);
1467 HeapFree(GetProcessHeap(), 0, pwstring);
1470 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1471 return bstrName;
1474 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1476 char * string;
1477 INT16 length;
1478 int lengthInChars;
1479 BSTR bstr = NULL;
1481 if(offset<0) return NULL;
1482 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1483 if(length <= 0) return 0;
1484 string=TLB_Alloc(length +1);
1485 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1486 string[length]='\0';
1488 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1489 string, -1, NULL, 0);
1491 /* no invalid characters in string */
1492 if (lengthInChars)
1494 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1496 /* don't check for invalid character since this has been done previously */
1497 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1499 bstr = SysAllocStringLen(pwstring, lengthInChars);
1500 lengthInChars = SysStringLen(bstr);
1501 HeapFree(GetProcessHeap(), 0, pwstring);
1504 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1505 return bstr;
1508 * read a value and fill a VARIANT structure
1510 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1512 int size;
1514 TRACE_(typelib)("\n");
1516 if(offset <0) { /* data are packed in here */
1517 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1518 V_I2(pVar) = offset & 0x3ffffff;
1519 return;
1521 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1522 pcx->pTblDir->pCustData.offset + offset );
1523 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1524 switch (V_VT(pVar)){
1525 case VT_EMPTY: /* FIXME: is this right? */
1526 case VT_NULL: /* FIXME: is this right? */
1527 case VT_I2 : /* this should not happen */
1528 case VT_I4 :
1529 case VT_R4 :
1530 case VT_ERROR :
1531 case VT_BOOL :
1532 case VT_I1 :
1533 case VT_UI1 :
1534 case VT_UI2 :
1535 case VT_UI4 :
1536 case VT_INT :
1537 case VT_UINT :
1538 case VT_VOID : /* FIXME: is this right? */
1539 case VT_HRESULT :
1540 size=4; break;
1541 case VT_R8 :
1542 case VT_CY :
1543 case VT_DATE :
1544 case VT_I8 :
1545 case VT_UI8 :
1546 case VT_DECIMAL : /* FIXME: is this right? */
1547 case VT_FILETIME :
1548 size=8;break;
1549 /* pointer types with known behaviour */
1550 case VT_BSTR :{
1551 char * ptr;
1552 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1553 if(size < 0) {
1554 FIXME("BSTR length = %d?\n", size);
1555 } else {
1556 ptr=TLB_Alloc(size);/* allocate temp buffer */
1557 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1558 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1559 /* FIXME: do we need a AtoW conversion here? */
1560 V_UNION(pVar, bstrVal[size])=L'\0';
1561 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1562 TLB_Free(ptr);
1565 size=-4; break;
1566 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1567 case VT_DISPATCH :
1568 case VT_VARIANT :
1569 case VT_UNKNOWN :
1570 case VT_PTR :
1571 case VT_SAFEARRAY :
1572 case VT_CARRAY :
1573 case VT_USERDEFINED :
1574 case VT_LPSTR :
1575 case VT_LPWSTR :
1576 case VT_BLOB :
1577 case VT_STREAM :
1578 case VT_STORAGE :
1579 case VT_STREAMED_OBJECT :
1580 case VT_STORED_OBJECT :
1581 case VT_BLOB_OBJECT :
1582 case VT_CF :
1583 case VT_CLSID :
1584 default:
1585 size=0;
1586 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1587 V_VT(pVar));
1590 if(size>0) /* (big|small) endian correct? */
1591 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1592 return;
1595 * create a linked list with custom data
1597 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1599 MSFT_CDGuid entry;
1600 TLBCustData* pNew;
1601 int count=0;
1603 TRACE_(typelib)("\n");
1605 while(offset >=0){
1606 count++;
1607 pNew=TLB_Alloc(sizeof(TLBCustData));
1608 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1609 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1610 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1611 /* add new custom data at head of the list */
1612 pNew->next=*ppCustData;
1613 *ppCustData=pNew;
1614 offset = entry.next;
1616 return count;
1619 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1620 ITypeInfoImpl *pTI)
1622 if(type <0)
1623 pTd->vt=type & VT_TYPEMASK;
1624 else
1625 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1627 if(pTd->vt == VT_USERDEFINED)
1628 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1630 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1633 static void
1634 MSFT_DoFuncs(TLBContext* pcx,
1635 ITypeInfoImpl* pTI,
1636 int cFuncs,
1637 int cVars,
1638 int offset,
1639 TLBFuncDesc** pptfd)
1642 * member information is stored in a data structure at offset
1643 * indicated by the memoffset field of the typeinfo structure
1644 * There are several distinctive parts.
1645 * The first part starts with a field that holds the total length
1646 * of this (first) part excluding this field. Then follow the records,
1647 * for each member there is one record.
1649 * The first entry is always the length of the record (including this
1650 * length word).
1651 * The rest of the record depends on the type of the member. If there is
1652 * a field indicating the member type (function, variable, interface, etc)
1653 * I have not found it yet. At this time we depend on the information
1654 * in the type info and the usual order how things are stored.
1656 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1657 * for each member;
1659 * Third is an equal sized array with file offsets to the name entry
1660 * of each member.
1662 * The fourth and last (?) part is an array with offsets to the records
1663 * in the first part of this file segment.
1666 int infolen, nameoffset, reclength, nrattributes, i;
1667 int recoffset = offset + sizeof(INT);
1669 char recbuf[512];
1670 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1672 TRACE_(typelib)("\n");
1674 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1676 for ( i = 0; i < cFuncs ; i++ )
1678 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1680 /* name, eventually add to a hash table */
1681 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1682 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1684 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1686 /* read the function information record */
1687 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1689 reclength &= 0x1ff;
1691 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1693 /* do the attributes */
1694 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1695 / sizeof(int);
1697 if ( nrattributes > 0 )
1699 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1701 if ( nrattributes > 1 )
1703 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1704 pFuncRec->OptAttr[1]) ;
1706 if ( nrattributes > 2 )
1708 if ( pFuncRec->FKCCIC & 0x2000 )
1710 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1712 else
1714 (*pptfd)->Entry = MSFT_ReadString(pcx,
1715 pFuncRec->OptAttr[2]);
1717 if( nrattributes > 5 )
1719 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1721 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1723 MSFT_CustData(pcx,
1724 pFuncRec->OptAttr[6],
1725 &(*pptfd)->pCustData);
1732 /* fill the FuncDesc Structure */
1733 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1734 offset + infolen + ( i + 1) * sizeof(INT));
1736 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1737 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1738 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1739 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1740 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1741 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1742 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1744 MSFT_GetTdesc(pcx,
1745 pFuncRec->DataType,
1746 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1747 pTI);
1749 /* do the parameters/arguments */
1750 if(pFuncRec->nrargs)
1752 int j = 0;
1753 MSFT_ParameterInfo paraminfo;
1755 (*pptfd)->funcdesc.lprgelemdescParam =
1756 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1758 (*pptfd)->pParamDesc =
1759 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1761 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1762 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1764 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1766 TYPEDESC* lpArgTypeDesc = 0;
1768 MSFT_GetTdesc(pcx,
1769 paraminfo.DataType,
1770 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1771 pTI);
1773 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1775 /* name */
1776 if (paraminfo.oName == -1)
1777 /* this occurs for [propput] or [propget] methods, so
1778 * we should just set the name of the parameter to the
1779 * name of the method. */
1780 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1781 else
1782 (*pptfd)->pParamDesc[j].Name =
1783 MSFT_ReadName( pcx, paraminfo.oName );
1784 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1786 /* SEEK value = jump to offset,
1787 * from there jump to the end of record,
1788 * go back by (j-1) arguments
1790 MSFT_ReadLEDWords( &paraminfo ,
1791 sizeof(MSFT_ParameterInfo), pcx,
1792 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1793 * sizeof(MSFT_ParameterInfo)));
1794 lpArgTypeDesc =
1795 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1797 while ( lpArgTypeDesc != NULL )
1799 switch ( lpArgTypeDesc->vt )
1801 case VT_PTR:
1802 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1803 break;
1805 case VT_CARRAY:
1806 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1807 break;
1809 case VT_USERDEFINED:
1810 MSFT_DoRefType(pcx, pTI,
1811 lpArgTypeDesc->u.hreftype);
1813 lpArgTypeDesc = NULL;
1814 break;
1816 default:
1817 lpArgTypeDesc = NULL;
1823 /* parameter is the return value! */
1824 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1826 TYPEDESC* lpArgTypeDesc;
1828 (*pptfd)->funcdesc.elemdescFunc =
1829 (*pptfd)->funcdesc.lprgelemdescParam[j];
1831 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1833 while ( lpArgTypeDesc != NULL )
1835 switch ( lpArgTypeDesc->vt )
1837 case VT_PTR:
1838 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1839 break;
1840 case VT_CARRAY:
1841 lpArgTypeDesc =
1842 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1844 break;
1846 case VT_USERDEFINED:
1847 MSFT_DoRefType(pcx,
1848 pTI,
1849 lpArgTypeDesc->u.hreftype);
1851 lpArgTypeDesc = NULL;
1852 break;
1854 default:
1855 lpArgTypeDesc = NULL;
1860 /* second time around */
1861 for(j=0;j<pFuncRec->nrargs;j++)
1863 /* default value */
1864 if ( (PARAMFLAG_FHASDEFAULT &
1865 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1866 ((pFuncRec->FKCCIC) & 0x1000) )
1868 INT* pInt = (INT *)((char *)pFuncRec +
1869 reclength -
1870 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1872 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1874 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1875 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1877 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1878 pInt[j], pcx);
1880 /* custom info */
1881 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1883 MSFT_CustData(pcx,
1884 pFuncRec->OptAttr[7+j],
1885 &(*pptfd)->pParamDesc[j].pCustData);
1890 /* scode is not used: archaic win16 stuff FIXME: right? */
1891 (*pptfd)->funcdesc.cScodes = 0 ;
1892 (*pptfd)->funcdesc.lprgscode = NULL ;
1894 pptfd = & ((*pptfd)->next);
1895 recoffset += reclength;
1899 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1900 int cVars, int offset, TLBVarDesc ** pptvd)
1902 int infolen, nameoffset, reclength;
1903 char recbuf[256];
1904 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1905 int i;
1906 int recoffset;
1908 TRACE_(typelib)("\n");
1910 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1911 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1912 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1913 recoffset += offset+sizeof(INT);
1914 for(i=0;i<cVars;i++){
1915 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1916 /* name, eventually add to a hash table */
1917 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1918 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1919 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1920 /* read the variable information record */
1921 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1922 reclength &=0xff;
1923 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1924 /* Optional data */
1925 if(reclength >(6*sizeof(INT)) )
1926 (*pptvd)->HelpContext=pVarRec->HelpContext;
1927 if(reclength >(7*sizeof(INT)) )
1928 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1929 if(reclength >(8*sizeof(INT)) )
1930 if(reclength >(9*sizeof(INT)) )
1931 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1932 /* fill the VarDesc Structure */
1933 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1934 offset + infolen + ( i + 1) * sizeof(INT));
1935 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1936 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1937 MSFT_GetTdesc(pcx, pVarRec->DataType,
1938 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1939 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1940 if(pVarRec->VarKind == VAR_CONST ){
1941 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1942 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1943 pVarRec->OffsValue, pcx);
1944 } else
1945 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1946 pptvd=&((*pptvd)->next);
1947 recoffset += reclength;
1950 /* fill in data for a hreftype (offset). When the referenced type is contained
1951 * in the typelib, it's just an (file) offset in the type info base dir.
1952 * If comes from import, it's an offset+1 in the ImpInfo table
1953 * */
1954 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1955 int offset)
1957 int j;
1958 TLBRefType **ppRefType = &pTI->reflist;
1960 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1962 while(*ppRefType) {
1963 if((*ppRefType)->reference == offset)
1964 return;
1965 ppRefType = &(*ppRefType)->next;
1968 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1969 sizeof(**ppRefType));
1971 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1972 /* external typelib */
1973 MSFT_ImpInfo impinfo;
1974 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1976 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1978 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1979 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1980 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1981 if(pImpLib->offset==impinfo.oImpFile) break;
1982 pImpLib=pImpLib->next;
1984 if(pImpLib){
1985 (*ppRefType)->reference=offset;
1986 (*ppRefType)->pImpTLInfo = pImpLib;
1987 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1988 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1989 (*ppRefType)->index = TLB_REF_USE_GUID;
1990 } else
1991 (*ppRefType)->index = impinfo.oGuid;
1992 }else{
1993 ERR("Cannot find a reference\n");
1994 (*ppRefType)->reference=-1;
1995 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1997 }else{
1998 /* in this typelib */
1999 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2000 (*ppRefType)->reference=offset;
2001 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2005 /* process Implemented Interfaces of a com class */
2006 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2007 int offset)
2009 int i;
2010 MSFT_RefRecord refrec;
2011 TLBImplType **ppImpl = &pTI->impltypelist;
2013 TRACE_(typelib)("\n");
2015 for(i=0;i<count;i++){
2016 if(offset<0) break; /* paranoia */
2017 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2018 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2019 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2020 (*ppImpl)->hRef = refrec.reftype;
2021 (*ppImpl)->implflags=refrec.flags;
2022 (*ppImpl)->ctCustData=
2023 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2024 offset=refrec.onext;
2025 ppImpl=&((*ppImpl)->next);
2029 * process a typeinfo record
2031 static ITypeInfoImpl * MSFT_DoTypeInfo(
2032 TLBContext *pcx,
2033 int count,
2034 ITypeLibImpl * pLibInfo)
2036 MSFT_TypeInfoBase tiBase;
2037 ITypeInfoImpl *ptiRet;
2039 TRACE_(typelib)("count=%u\n", count);
2041 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2042 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2043 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2045 /* this is where we are coming from */
2046 ptiRet->pTypeLib = pLibInfo;
2047 ptiRet->index=count;
2048 /* fill in the typeattr fields */
2049 WARN("Assign constructor/destructor memid\n");
2051 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2052 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2053 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2054 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2055 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2056 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2057 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2058 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2059 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2060 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2061 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2062 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2063 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2064 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2065 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2066 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2067 MSFT_GetTdesc(pcx, tiBase.datatype1,
2068 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2070 /* FIXME: */
2071 /* IDLDESC idldescType; *//* never saw this one != zero */
2073 /* name, eventually add to a hash table */
2074 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2075 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2076 /* help info */
2077 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2078 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2079 ptiRet->dwHelpContext=tiBase.helpcontext;
2081 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2082 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2084 /* note: InfoType's Help file and HelpStringDll come from the containing
2085 * library. Further HelpString and Docstring appear to be the same thing :(
2087 /* functions */
2088 if(ptiRet->TypeAttr.cFuncs >0 )
2089 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2090 ptiRet->TypeAttr.cVars,
2091 tiBase.memoffset, & ptiRet->funclist);
2092 /* variables */
2093 if(ptiRet->TypeAttr.cVars >0 )
2094 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2095 ptiRet->TypeAttr.cVars,
2096 tiBase.memoffset, & ptiRet->varlist);
2097 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2098 switch(ptiRet->TypeAttr.typekind)
2100 case TKIND_COCLASS:
2101 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2102 tiBase.datatype1);
2103 break;
2104 case TKIND_DISPATCH:
2105 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2107 if (tiBase.datatype1 != -1)
2109 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2110 ptiRet->impltypelist->hRef = tiBase.datatype1;
2112 else
2113 { /* FIXME: This is a really bad hack to add IDispatch */
2114 const char* szStdOle = "stdole2.tlb\0";
2115 int nStdOleLen = strlen(szStdOle);
2116 TLBRefType **ppRef = &ptiRet->reflist;
2118 while(*ppRef) {
2119 if((*ppRef)->reference == -1)
2120 break;
2121 ppRef = &(*ppRef)->next;
2123 if(!*ppRef) {
2124 *ppRef = TLB_Alloc(sizeof(**ppRef));
2125 (*ppRef)->guid = IID_IDispatch;
2126 (*ppRef)->reference = -1;
2127 (*ppRef)->index = TLB_REF_USE_GUID;
2128 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2129 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2130 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2131 nStdOleLen + 1);
2133 MultiByteToWideChar(CP_ACP,
2134 MB_PRECOMPOSED,
2135 szStdOle,
2137 (*ppRef)->pImpTLInfo->name,
2138 SysStringLen((*ppRef)->pImpTLInfo->name));
2140 (*ppRef)->pImpTLInfo->lcid = 0;
2141 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2142 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2145 break;
2146 default:
2147 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2148 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2149 ptiRet->impltypelist->hRef = tiBase.datatype1;
2150 break;
2153 ptiRet->ctCustData=
2154 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2156 TRACE_(typelib)("%s guid: %s kind:%s\n",
2157 debugstr_w(ptiRet->Name),
2158 debugstr_guid(&ptiRet->TypeAttr.guid),
2159 typekind_desc[ptiRet->TypeAttr.typekind]);
2161 return ptiRet;
2164 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2165 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2166 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2167 * tradeoff here.
2169 static ITypeLibImpl *tlb_cache_first;
2170 static CRITICAL_SECTION cache_section;
2171 static CRITICAL_SECTION_DEBUG cache_section_debug =
2173 0, 0, &cache_section,
2174 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2175 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2177 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2180 /****************************************************************************
2181 * TLB_ReadTypeLib
2183 * find the type of the typelib file and map the typelib resource into
2184 * the memory
2186 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2187 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2188 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2190 ITypeLibImpl *entry;
2191 int ret = TYPE_E_CANTLOADLIBRARY;
2192 DWORD dwSignature = 0;
2193 HANDLE hFile;
2195 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2197 *ppTypeLib = NULL;
2199 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2200 EnterCriticalSection(&cache_section);
2201 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2203 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2205 TRACE("cache hit\n");
2206 *ppTypeLib = (ITypeLib2*)entry;
2207 ITypeLib_AddRef(*ppTypeLib);
2208 LeaveCriticalSection(&cache_section);
2209 return S_OK;
2212 LeaveCriticalSection(&cache_section);
2214 /* check the signature of the file */
2215 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2216 if (INVALID_HANDLE_VALUE != hFile)
2218 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2219 if (hMapping)
2221 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2222 if(pBase)
2224 /* retrieve file size */
2225 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2227 /* first try to load as *.tlb */
2228 dwSignature = FromLEDWord(*((DWORD*) pBase));
2229 if ( dwSignature == MSFT_SIGNATURE)
2231 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2233 else if ( dwSignature == SLTG_SIGNATURE)
2235 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2237 UnmapViewOfFile(pBase);
2239 CloseHandle(hMapping);
2241 CloseHandle(hFile);
2243 else
2245 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2248 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2249 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2251 /* find the typelibrary resource*/
2252 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2253 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2254 if (hinstDLL)
2256 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2257 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2258 if (hrsrc)
2260 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2261 if (hGlobal)
2263 LPVOID pBase = LockResource(hGlobal);
2264 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2266 if (pBase)
2268 /* try to load as incore resource */
2269 dwSignature = FromLEDWord(*((DWORD*) pBase));
2270 if ( dwSignature == MSFT_SIGNATURE)
2272 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2274 else if ( dwSignature == SLTG_SIGNATURE)
2276 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2278 else
2280 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2283 FreeResource( hGlobal );
2286 FreeLibrary(hinstDLL);
2290 if(*ppTypeLib) {
2291 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2293 TRACE("adding to cache\n");
2294 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2295 lstrcpyW(impl->path, pszFileName);
2296 /* We should really canonicalise the path here. */
2297 impl->index = index;
2299 /* FIXME: check if it has added already in the meantime */
2300 EnterCriticalSection(&cache_section);
2301 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2302 impl->prev = NULL;
2303 tlb_cache_first = impl;
2304 LeaveCriticalSection(&cache_section);
2305 ret = S_OK;
2306 } else
2307 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2309 return ret;
2312 /*================== ITypeLib(2) Methods ===================================*/
2314 /****************************************************************************
2315 * ITypeLib2_Constructor_MSFT
2317 * loading an MSFT typelib from an in-memory image
2319 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2321 TLBContext cx;
2322 long lPSegDir;
2323 MSFT_Header tlbHeader;
2324 MSFT_SegDir tlbSegDir;
2325 ITypeLibImpl * pTypeLibImpl;
2327 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2329 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2330 if (!pTypeLibImpl) return NULL;
2332 pTypeLibImpl->lpVtbl = &tlbvt;
2333 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2334 pTypeLibImpl->ref = 1;
2336 /* get pointer to beginning of typelib data */
2337 cx.pos = 0;
2338 cx.oStart=0;
2339 cx.mapping = pLib;
2340 cx.pLibInfo = pTypeLibImpl;
2341 cx.length = dwTLBLength;
2343 /* read header */
2344 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2345 TRACE("header:\n");
2346 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2347 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2348 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2349 return NULL;
2351 /* there is a small amount of information here until the next important
2352 * part:
2353 * the segment directory . Try to calculate the amount of data */
2354 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2356 /* now read the segment directory */
2357 TRACE("read segment directory (at %ld)\n",lPSegDir);
2358 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2359 cx.pTblDir = &tlbSegDir;
2361 /* just check two entries */
2362 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2364 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2365 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2366 return NULL;
2369 /* now fill our internal data */
2370 /* TLIBATTR fields */
2371 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2373 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2374 /* Windows seems to have zero here, is this correct? */
2375 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2376 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2377 else
2378 pTypeLibImpl->LibAttr.lcid = 0;
2380 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2381 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2382 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2383 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2385 /* name, eventually add to a hash table */
2386 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2388 /* help info */
2389 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2390 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2392 if( tlbHeader.varflags & HELPDLLFLAG)
2394 int offset;
2395 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2396 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2399 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2401 /* custom data */
2402 if(tlbHeader.CustomDataOffset >= 0)
2404 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2407 /* fill in typedescriptions */
2408 if(tlbSegDir.pTypdescTab.length > 0)
2410 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2411 INT16 td[4];
2412 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2413 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2414 for(i=0; i<cTD; )
2416 /* FIXME: add several sanity checks here */
2417 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2418 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2420 /* FIXME: check safearray */
2421 if(td[3] < 0)
2422 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2423 else
2424 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2426 else if(td[0] == VT_CARRAY)
2428 /* array descr table here */
2429 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2431 else if(td[0] == VT_USERDEFINED)
2433 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2435 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2438 /* second time around to fill the array subscript info */
2439 for(i=0;i<cTD;i++)
2441 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2442 if(tlbSegDir.pArrayDescriptions.offset>0)
2444 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2445 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2447 if(td[1]<0)
2448 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2449 else
2450 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2452 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2454 for(j = 0; j<td[2]; j++)
2456 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2457 sizeof(INT), &cx, DO_NOT_SEEK);
2458 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2459 sizeof(INT), &cx, DO_NOT_SEEK);
2462 else
2464 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2465 ERR("didn't find array description data\n");
2470 /* imported type libs */
2471 if(tlbSegDir.pImpFiles.offset>0)
2473 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2474 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2475 UINT16 size;
2477 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2479 char *name;
2480 DWORD len;
2482 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2483 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2484 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2486 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2487 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2488 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2489 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2491 size >>= 2;
2492 name = TLB_Alloc(size+1);
2493 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2494 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2495 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2496 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2497 TLB_Free(name);
2499 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2500 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2502 ppImpLib = &(*ppImpLib)->next;
2506 /* type info's */
2507 if(tlbHeader.nrtypeinfos >= 0 )
2509 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2510 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2511 int i;
2513 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2515 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2517 ppTI = &((*ppTI)->next);
2518 (pTypeLibImpl->TypeInfoCount)++;
2522 TRACE("(%p)\n", pTypeLibImpl);
2523 return (ITypeLib2*) pTypeLibImpl;
2527 static BSTR TLB_MultiByteToBSTR(char *ptr)
2529 DWORD len;
2530 WCHAR *nameW;
2531 BSTR ret;
2533 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2534 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2535 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2536 ret = SysAllocString(nameW);
2537 HeapFree(GetProcessHeap(), 0, nameW);
2538 return ret;
2541 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2543 char b[3];
2544 int i;
2545 short s;
2547 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2548 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2549 return FALSE;
2552 guid->Data4[0] = s >> 8;
2553 guid->Data4[1] = s & 0xff;
2555 b[2] = '\0';
2556 for(i = 0; i < 6; i++) {
2557 memcpy(b, str + 24 + 2 * i, 2);
2558 guid->Data4[i + 2] = strtol(b, NULL, 16);
2560 return TRUE;
2563 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2565 WORD bytelen;
2566 DWORD len;
2567 WCHAR *nameW;
2569 *pBstr = NULL;
2570 bytelen = *(WORD*)ptr;
2571 if(bytelen == 0xffff) return 2;
2572 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2573 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2574 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2575 *pBstr = SysAllocStringLen(nameW, len);
2576 HeapFree(GetProcessHeap(), 0, nameW);
2577 return bytelen + 2;
2580 static WORD SLTG_ReadStringA(char *ptr, char **str)
2582 WORD bytelen;
2584 *str = NULL;
2585 bytelen = *(WORD*)ptr;
2586 if(bytelen == 0xffff) return 2;
2587 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2588 memcpy(*str, ptr + 2, bytelen);
2589 (*str)[bytelen] = '\0';
2590 return bytelen + 2;
2593 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2595 char *ptr = pLibBlk;
2596 WORD w;
2598 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2599 FIXME("libblk magic = %04x\n", w);
2600 return 0;
2603 ptr += 6;
2604 if((w = *(WORD*)ptr) != 0xffff) {
2605 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2606 ptr += w;
2608 ptr += 2;
2610 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2612 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2614 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2615 ptr += 4;
2617 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2618 ptr += 2;
2620 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2621 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2622 else
2623 pTypeLibImpl->LibAttr.lcid = 0;
2624 ptr += 2;
2626 ptr += 4; /* skip res12 */
2628 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2629 ptr += 2;
2631 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2632 ptr += 2;
2634 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2635 ptr += 2;
2637 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2638 ptr += sizeof(GUID);
2640 return ptr - (char*)pLibBlk;
2643 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2645 BOOL done = FALSE;
2646 TYPEDESC *pTD = &pElem->tdesc;
2648 /* Handle [in/out] first */
2649 if((*pType & 0xc000) == 0xc000)
2650 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2651 else if(*pType & 0x8000)
2652 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2653 else if(*pType & 0x4000)
2654 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2655 else
2656 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2658 if(*pType & 0x2000)
2659 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2661 if(*pType & 0x80)
2662 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2664 while(!done) {
2665 if((*pType & 0xe00) == 0xe00) {
2666 pTD->vt = VT_PTR;
2667 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2668 sizeof(TYPEDESC));
2669 pTD = pTD->u.lptdesc;
2671 switch(*pType & 0x7f) {
2672 case VT_PTR:
2673 pTD->vt = VT_PTR;
2674 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2675 sizeof(TYPEDESC));
2676 pTD = pTD->u.lptdesc;
2677 break;
2679 case VT_USERDEFINED:
2680 pTD->vt = VT_USERDEFINED;
2681 pTD->u.hreftype = *(++pType) / 4;
2682 done = TRUE;
2683 break;
2685 case VT_CARRAY:
2687 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2688 array */
2690 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2692 pTD->vt = VT_CARRAY;
2693 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2694 sizeof(ARRAYDESC) +
2695 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2696 pTD->u.lpadesc->cDims = pSA->cDims;
2697 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2698 pSA->cDims * sizeof(SAFEARRAYBOUND));
2700 pTD = &pTD->u.lpadesc->tdescElem;
2701 break;
2704 case VT_SAFEARRAY:
2706 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2707 useful? */
2709 pType++;
2710 pTD->vt = VT_SAFEARRAY;
2711 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2712 sizeof(TYPEDESC));
2713 pTD = pTD->u.lptdesc;
2714 break;
2716 default:
2717 pTD->vt = *pType & 0x7f;
2718 done = TRUE;
2719 break;
2721 pType++;
2723 return pType;
2727 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2728 char *pNameTable)
2730 int ref;
2731 char *name;
2732 TLBRefType **ppRefType;
2734 if(pRef->magic != SLTG_REF_MAGIC) {
2735 FIXME("Ref magic = %x\n", pRef->magic);
2736 return;
2738 name = ( (char*)(&pRef->names) + pRef->number);
2740 ppRefType = &pTI->reflist;
2741 for(ref = 0; ref < pRef->number >> 3; ref++) {
2742 char *refname;
2743 unsigned int lib_offs, type_num;
2745 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2746 sizeof(**ppRefType));
2748 name += SLTG_ReadStringA(name, &refname);
2749 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2750 FIXME("Can't sscanf ref\n");
2751 if(lib_offs != 0xffff) {
2752 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2754 while(*import) {
2755 if((*import)->offset == lib_offs)
2756 break;
2757 import = &(*import)->next;
2759 if(!*import) {
2760 char fname[MAX_PATH+1];
2761 int len;
2763 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2764 sizeof(**import));
2765 (*import)->offset = lib_offs;
2766 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2767 &(*import)->guid);
2768 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2769 &(*import)->wVersionMajor,
2770 &(*import)->wVersionMinor,
2771 &(*import)->lcid, fname) != 4) {
2772 FIXME("can't sscanf ref %s\n",
2773 pNameTable + lib_offs + 40);
2775 len = strlen(fname);
2776 if(fname[len-1] != '#')
2777 FIXME("fname = %s\n", fname);
2778 fname[len-1] = '\0';
2779 (*import)->name = TLB_MultiByteToBSTR(fname);
2781 (*ppRefType)->pImpTLInfo = *import;
2782 } else { /* internal ref */
2783 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2785 (*ppRefType)->reference = ref;
2786 (*ppRefType)->index = type_num;
2788 HeapFree(GetProcessHeap(), 0, refname);
2789 ppRefType = &(*ppRefType)->next;
2791 if((BYTE)*name != SLTG_REF_MAGIC)
2792 FIXME("End of ref block magic = %x\n", *name);
2793 dump_TLBRefType(pTI->reflist);
2796 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2797 BOOL OneOnly)
2799 SLTG_ImplInfo *info;
2800 TLBImplType **ppImplType = &pTI->impltypelist;
2801 /* I don't really get this structure, usually it's 0x16 bytes
2802 long, but iuser.tlb contains some that are 0x18 bytes long.
2803 That's ok because we can use the next ptr to jump to the next
2804 one. But how do we know the length of the last one? The WORD
2805 at offs 0x8 might be the clue. For now I'm just assuming that
2806 the last one is the regular 0x16 bytes. */
2808 info = (SLTG_ImplInfo*)pBlk;
2809 while(1) {
2810 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2811 sizeof(**ppImplType));
2812 (*ppImplType)->hRef = info->ref;
2813 (*ppImplType)->implflags = info->impltypeflags;
2814 pTI->TypeAttr.cImplTypes++;
2815 ppImplType = &(*ppImplType)->next;
2817 if(info->next == 0xffff)
2818 break;
2819 if(OneOnly)
2820 FIXME("Interface inheriting more than one interface\n");
2821 info = (SLTG_ImplInfo*)(pBlk + info->next);
2823 info++; /* see comment at top of function */
2824 return (char*)info;
2827 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2828 char *pNameTable)
2830 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2831 SLTG_MemberHeader *pMemHeader;
2832 char *pFirstItem, *pNextItem;
2834 if(pTIHeader->href_table != 0xffffffff) {
2835 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2836 pNameTable);
2840 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2842 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2844 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2845 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2848 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2852 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2853 char *pNameTable)
2855 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2856 SLTG_MemberHeader *pMemHeader;
2857 SLTG_Function *pFunc;
2858 char *pFirstItem, *pNextItem;
2859 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2860 int num = 0;
2862 if(pTIHeader->href_table != 0xffffffff) {
2863 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2864 pNameTable);
2867 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2869 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2871 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2872 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2875 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2876 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2878 int param;
2879 WORD *pType, *pArg;
2881 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2882 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2883 FIXME("func magic = %02x\n", pFunc->magic);
2884 return NULL;
2886 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2887 sizeof(**ppFuncDesc));
2888 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2890 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2891 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2892 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2893 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2894 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2895 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2897 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2898 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2900 if(pFunc->retnextopt & 0x80)
2901 pType = &pFunc->rettype;
2902 else
2903 pType = (WORD*)(pFirstItem + pFunc->rettype);
2906 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2908 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2909 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2910 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2911 (*ppFuncDesc)->pParamDesc =
2912 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2913 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2915 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2917 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2918 char *paramName = pNameTable + *pArg;
2919 BOOL HaveOffs;
2920 /* If arg type follows then paramName points to the 2nd
2921 letter of the name, else the next WORD is an offset to
2922 the arg type and paramName points to the first letter.
2923 So let's take one char off paramName and see if we're
2924 pointing at an alpha-numeric char. However if *pArg is
2925 0xffff or 0xfffe then the param has no name, the former
2926 meaning that the next WORD is the type, the latter
2927 meaning the the next WORD is an offset to the type. */
2929 HaveOffs = FALSE;
2930 if(*pArg == 0xffff)
2931 paramName = NULL;
2932 else if(*pArg == 0xfffe) {
2933 paramName = NULL;
2934 HaveOffs = TRUE;
2936 else if(paramName[-1] && !isalnum(paramName[-1]))
2937 HaveOffs = TRUE;
2939 pArg++;
2941 if(HaveOffs) { /* the next word is an offset to type */
2942 pType = (WORD*)(pFirstItem + *pArg);
2943 SLTG_DoType(pType, pFirstItem,
2944 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2945 pArg++;
2946 } else {
2947 if(paramName)
2948 paramName--;
2949 pArg = SLTG_DoType(pArg, pFirstItem,
2950 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2953 /* Are we an optional param ? */
2954 if((*ppFuncDesc)->funcdesc.cParams - param <=
2955 (*ppFuncDesc)->funcdesc.cParamsOpt)
2956 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2958 if(paramName) {
2959 (*ppFuncDesc)->pParamDesc[param].Name =
2960 TLB_MultiByteToBSTR(paramName);
2964 ppFuncDesc = &((*ppFuncDesc)->next);
2965 if(pFunc->next == 0xffff) break;
2967 pTI->TypeAttr.cFuncs = num;
2968 dump_TLBFuncDesc(pTI->funclist);
2969 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2972 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2973 char *pNameTable)
2975 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2976 SLTG_MemberHeader *pMemHeader;
2977 SLTG_RecordItem *pItem;
2978 char *pFirstItem;
2979 TLBVarDesc **ppVarDesc = &pTI->varlist;
2980 int num = 0;
2981 WORD *pType;
2982 char buf[300];
2984 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2986 pFirstItem = (char*)(pMemHeader + 1);
2987 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2988 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2989 if(pItem->magic != SLTG_RECORD_MAGIC) {
2990 FIXME("record magic = %02x\n", pItem->magic);
2991 return NULL;
2993 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2994 sizeof(**ppVarDesc));
2995 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2996 (*ppVarDesc)->vardesc.memid = pItem->memid;
2997 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2998 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3000 if(pItem->typepos == 0x02)
3001 pType = &pItem->type;
3002 else if(pItem->typepos == 0x00)
3003 pType = (WORD*)(pFirstItem + pItem->type);
3004 else {
3005 FIXME("typepos = %02x\n", pItem->typepos);
3006 break;
3009 SLTG_DoType(pType, pFirstItem,
3010 &(*ppVarDesc)->vardesc.elemdescVar);
3012 /* FIXME("helpcontext, helpstring\n"); */
3014 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3016 ppVarDesc = &((*ppVarDesc)->next);
3017 if(pItem->next == 0xffff) break;
3019 pTI->TypeAttr.cVars = num;
3020 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3023 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3024 char *pNameTable)
3026 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3027 SLTG_MemberHeader *pMemHeader;
3028 SLTG_AliasItem *pItem;
3029 int i, mustbelast;
3031 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3032 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3034 mustbelast = 0;
3035 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3036 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3037 if (pItem->vt == 0xffff) {
3038 if (i<(pMemHeader->cbExtra/4-1))
3039 FIXME("Endmarker too early in process alias data!\n");
3040 break;
3042 if (mustbelast) {
3043 FIXME("Chain extends over last entry?\n");
3044 break;
3046 if (pItem->vt == VT_USERDEFINED) {
3047 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3048 /* guessing here ... */
3049 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3050 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3051 mustbelast = 1;
3052 } else {
3053 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3054 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3056 pItem++;
3058 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3061 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3062 char *pNameTable)
3064 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3065 SLTG_MemberHeader *pMemHeader;
3066 SLTG_AliasItem *pItem;
3068 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3069 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3070 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3071 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3072 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3075 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3076 char *pNameTable)
3078 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3079 SLTG_MemberHeader *pMemHeader;
3080 SLTG_EnumItem *pItem;
3081 char *pFirstItem;
3082 TLBVarDesc **ppVarDesc = &pTI->varlist;
3083 int num = 0;
3085 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3087 pFirstItem = (char*)(pMemHeader + 1);
3088 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3089 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3090 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3091 FIXME("enumitem magic = %04x\n", pItem->magic);
3092 return NULL;
3094 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3095 sizeof(**ppVarDesc));
3096 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3097 (*ppVarDesc)->vardesc.memid = pItem->memid;
3098 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3099 sizeof(VARIANT));
3100 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3101 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3102 *(INT*)(pItem->value + pFirstItem);
3103 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3104 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3105 /* FIXME("helpcontext, helpstring\n"); */
3107 ppVarDesc = &((*ppVarDesc)->next);
3108 if(pItem->next == 0xffff) break;
3110 pTI->TypeAttr.cVars = num;
3111 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3114 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3115 managable copy of it into this */
3116 typedef struct {
3117 WORD small_no;
3118 char *index_name;
3119 char *other_name;
3120 WORD res1a;
3121 WORD name_offs;
3122 WORD more_bytes;
3123 char *extra;
3124 WORD res20;
3125 DWORD helpcontext;
3126 WORD res26;
3127 GUID uuid;
3128 } SLTG_InternalOtherTypeInfo;
3130 /****************************************************************************
3131 * ITypeLib2_Constructor_SLTG
3133 * loading a SLTG typelib from an in-memory image
3135 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3137 ITypeLibImpl *pTypeLibImpl;
3138 SLTG_Header *pHeader;
3139 SLTG_BlkEntry *pBlkEntry;
3140 SLTG_Magic *pMagic;
3141 SLTG_Index *pIndex;
3142 SLTG_Pad9 *pPad9;
3143 LPVOID pBlk, pFirstBlk;
3144 SLTG_LibBlk *pLibBlk;
3145 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3146 char *pAfterOTIBlks = NULL;
3147 char *pNameTable, *ptr;
3148 int i;
3149 DWORD len, order;
3150 ITypeInfoImpl **ppTypeInfoImpl;
3152 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3154 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3155 if (!pTypeLibImpl) return NULL;
3157 pTypeLibImpl->lpVtbl = &tlbvt;
3158 pTypeLibImpl->ref = 1;
3160 pHeader = pLib;
3162 TRACE_(typelib)("header:\n");
3163 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3164 pHeader->nrOfFileBlks );
3165 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3166 FIXME("Header type magic 0x%08lx not supported.\n",
3167 pHeader->SLTG_magic);
3168 return NULL;
3171 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3172 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3174 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3175 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3177 /* Next we have a magic block */
3178 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3180 /* Let's see if we're still in sync */
3181 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3182 sizeof(SLTG_COMPOBJ_MAGIC))) {
3183 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3184 return NULL;
3186 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3187 sizeof(SLTG_DIR_MAGIC))) {
3188 FIXME("dir magic = %s\n", pMagic->dir_magic);
3189 return NULL;
3192 pIndex = (SLTG_Index*)(pMagic+1);
3194 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3196 pFirstBlk = (LPVOID)(pPad9 + 1);
3198 /* We'll set up a ptr to the main library block, which is the last one. */
3200 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3201 pBlkEntry[order].next != 0;
3202 order = pBlkEntry[order].next - 1, i++) {
3203 pBlk = (char*)pBlk + pBlkEntry[order].len;
3205 pLibBlk = pBlk;
3207 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3209 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3210 interspersed */
3212 len += 0x40;
3214 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3216 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3217 sizeof(*pOtherTypeInfoBlks) *
3218 pTypeLibImpl->TypeInfoCount);
3221 ptr = (char*)pLibBlk + len;
3223 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3224 WORD w, extra;
3225 len = 0;
3227 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3229 w = *(WORD*)(ptr + 2);
3230 if(w != 0xffff) {
3231 len += w;
3232 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3233 w+1);
3234 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3235 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3237 w = *(WORD*)(ptr + 4 + len);
3238 if(w != 0xffff) {
3239 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3240 len += w;
3241 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3242 w+1);
3243 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3244 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3246 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3247 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3248 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3249 if(extra) {
3250 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3251 extra);
3252 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3253 len += extra;
3255 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3256 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3257 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3258 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3259 len += sizeof(SLTG_OtherTypeInfo);
3260 ptr += len;
3263 pAfterOTIBlks = ptr;
3265 /* Skip this WORD and get the next DWORD */
3266 len = *(DWORD*)(pAfterOTIBlks + 2);
3268 /* Now add this to pLibBLk look at what we're pointing at and
3269 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3270 dust and we should be pointing at the beginning of the name
3271 table */
3273 pNameTable = (char*)pLibBlk + len;
3275 switch(*(WORD*)pNameTable) {
3276 case 0xffff:
3277 break;
3278 case 0x0200:
3279 pNameTable += 0x20;
3280 break;
3281 default:
3282 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3283 break;
3286 pNameTable += 0x216;
3288 pNameTable += 2;
3290 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3292 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3295 /* Hopefully we now have enough ptrs set up to actually read in
3296 some TypeInfos. It's not clear which order to do them in, so
3297 I'll just follow the links along the BlkEntry chain and read
3298 them in in the order in which they're in the file */
3300 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3302 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3303 pBlkEntry[order].next != 0;
3304 order = pBlkEntry[order].next - 1, i++) {
3306 SLTG_TypeInfoHeader *pTIHeader;
3307 SLTG_TypeInfoTail *pTITail;
3309 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3310 pOtherTypeInfoBlks[i].index_name)) {
3311 FIXME("Index strings don't match\n");
3312 return NULL;
3315 pTIHeader = pBlk;
3316 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3317 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3318 return NULL;
3320 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3321 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3322 (*ppTypeInfoImpl)->index = i;
3323 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3324 pOtherTypeInfoBlks[i].name_offs +
3325 pNameTable);
3326 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3327 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3328 sizeof(GUID));
3329 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3330 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3331 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3332 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3333 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3335 if((pTIHeader->typeflags1 & 7) != 2)
3336 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3337 if(pTIHeader->typeflags3 != 2)
3338 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3340 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3341 debugstr_w((*ppTypeInfoImpl)->Name),
3342 typekind_desc[pTIHeader->typekind],
3343 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3344 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3346 switch(pTIHeader->typekind) {
3347 case TKIND_ENUM:
3348 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3349 break;
3351 case TKIND_RECORD:
3352 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3353 break;
3355 case TKIND_INTERFACE:
3356 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3357 break;
3359 case TKIND_COCLASS:
3360 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3361 break;
3363 case TKIND_ALIAS:
3364 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3365 if (pTITail->tdescalias_vt)
3366 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3367 break;
3369 case TKIND_DISPATCH:
3370 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3371 break;
3373 default:
3374 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3375 pTITail = NULL;
3376 break;
3380 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3381 but we've already set those */
3382 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3383 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3384 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3386 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3387 X(06);
3388 X(08);
3389 X(0a);
3390 X(0c);
3391 X(0e);
3392 X(10);
3393 X(12);
3394 X(16);
3395 X(18);
3396 X(1a);
3397 X(1c);
3398 X(1e);
3399 X(24);
3400 X(26);
3401 X(2a);
3402 X(2c);
3403 X(2e);
3404 X(30);
3405 X(32);
3406 X(34);
3408 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3409 pBlk = (char*)pBlk + pBlkEntry[order].len;
3412 if(i != pTypeLibImpl->TypeInfoCount) {
3413 FIXME("Somehow processed %d TypeInfos\n", i);
3414 return NULL;
3417 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3418 return (ITypeLib2*)pTypeLibImpl;
3421 /* ITypeLib::QueryInterface
3423 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3424 ITypeLib2 * iface,
3425 REFIID riid,
3426 VOID **ppvObject)
3428 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3430 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3432 *ppvObject=NULL;
3433 if(IsEqualIID(riid, &IID_IUnknown) ||
3434 IsEqualIID(riid,&IID_ITypeLib)||
3435 IsEqualIID(riid,&IID_ITypeLib2))
3437 *ppvObject = This;
3440 if(*ppvObject)
3442 ITypeLib2_AddRef(iface);
3443 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3444 return S_OK;
3446 TRACE("-- Interface: E_NOINTERFACE\n");
3447 return E_NOINTERFACE;
3450 /* ITypeLib::AddRef
3452 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3454 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3455 ULONG ref = InterlockedIncrement(&This->ref);
3457 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3459 return ref;
3462 /* ITypeLib::Release
3464 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3466 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3467 ULONG ref = InterlockedDecrement(&This->ref);
3469 TRACE("(%p)->(%lu)\n",This, ref);
3471 if (!ref)
3473 /* remove cache entry */
3474 TRACE("removing from cache list\n");
3475 EnterCriticalSection(&cache_section);
3476 if (This->next) This->next->prev = This->prev;
3477 if (This->prev) This->prev->next = This->next;
3478 else tlb_cache_first = This->next;
3479 LeaveCriticalSection(&cache_section);
3481 /* FIXME destroy child objects */
3482 TRACE(" destroying ITypeLib(%p)\n",This);
3484 if (This->Name)
3486 SysFreeString(This->Name);
3487 This->Name = NULL;
3490 if (This->DocString)
3492 SysFreeString(This->DocString);
3493 This->DocString = NULL;
3496 if (This->HelpFile)
3498 SysFreeString(This->HelpFile);
3499 This->HelpFile = NULL;
3502 if (This->HelpStringDll)
3504 SysFreeString(This->HelpStringDll);
3505 This->HelpStringDll = NULL;
3508 if (This->pTypeInfo) /* can be NULL */
3509 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3510 HeapFree(GetProcessHeap(),0,This);
3511 return 0;
3514 return ref;
3517 /* ITypeLib::GetTypeInfoCount
3519 * Returns the number of type descriptions in the type library
3521 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3523 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3524 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3525 return This->TypeInfoCount;
3528 /* ITypeLib::GetTypeInfo
3530 * retrieves the specified type description in the library.
3532 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3533 ITypeLib2 *iface,
3534 UINT index,
3535 ITypeInfo **ppTInfo)
3537 int i;
3539 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3540 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3542 TRACE("(%p)->(index=%d) \n", This, index);
3544 if (!ppTInfo) return E_INVALIDARG;
3546 /* search element n in list */
3547 for(i=0; i < index; i++)
3549 pTypeInfo = pTypeInfo->next;
3550 if (!pTypeInfo)
3552 TRACE("-- element not found\n");
3553 return TYPE_E_ELEMENTNOTFOUND;
3557 *ppTInfo = (ITypeInfo *) pTypeInfo;
3559 ITypeInfo_AddRef(*ppTInfo);
3560 TRACE("-- found (%p)\n",*ppTInfo);
3561 return S_OK;
3565 /* ITypeLibs::GetTypeInfoType
3567 * Retrieves the type of a type description.
3569 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3570 ITypeLib2 *iface,
3571 UINT index,
3572 TYPEKIND *pTKind)
3574 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3575 int i;
3576 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3578 TRACE("(%p) index %d \n",This, index);
3580 if(!pTKind) return E_INVALIDARG;
3582 /* search element n in list */
3583 for(i=0; i < index; i++)
3585 if(!pTInfo)
3587 TRACE("-- element not found\n");
3588 return TYPE_E_ELEMENTNOTFOUND;
3590 pTInfo = pTInfo->next;
3593 *pTKind = pTInfo->TypeAttr.typekind;
3594 TRACE("-- found Type (%d)\n", *pTKind);
3595 return S_OK;
3598 /* ITypeLib::GetTypeInfoOfGuid
3600 * Retrieves the type description that corresponds to the specified GUID.
3603 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3604 ITypeLib2 *iface,
3605 REFGUID guid,
3606 ITypeInfo **ppTInfo)
3608 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3609 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3611 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3613 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3615 /* search linked list for guid */
3616 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3618 pTypeInfo = pTypeInfo->next;
3620 if (!pTypeInfo)
3622 /* end of list reached */
3623 TRACE("-- element not found\n");
3624 return TYPE_E_ELEMENTNOTFOUND;
3628 TRACE("-- found (%p, %s)\n",
3629 pTypeInfo,
3630 debugstr_w(pTypeInfo->Name));
3632 *ppTInfo = (ITypeInfo*)pTypeInfo;
3633 ITypeInfo_AddRef(*ppTInfo);
3634 return S_OK;
3637 /* ITypeLib::GetLibAttr
3639 * Retrieves the structure that contains the library's attributes.
3642 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3643 ITypeLib2 *iface,
3644 LPTLIBATTR *ppTLibAttr)
3646 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3647 TRACE("(%p)\n",This);
3648 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3649 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3650 return S_OK;
3653 /* ITypeLib::GetTypeComp
3655 * Enables a client compiler to bind to a library's types, variables,
3656 * constants, and global functions.
3659 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3660 ITypeLib2 *iface,
3661 ITypeComp **ppTComp)
3663 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3665 TRACE("(%p)->(%p)\n",This,ppTComp);
3666 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3667 ITypeComp_AddRef(*ppTComp);
3669 return S_OK;
3672 /* ITypeLib::GetDocumentation
3674 * Retrieves the library's documentation string, the complete Help file name
3675 * and path, and the context identifier for the library Help topic in the Help
3676 * file.
3678 * On a successful return all non-null BSTR pointers will have been set,
3679 * possibly to NULL.
3681 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3682 ITypeLib2 *iface,
3683 INT index,
3684 BSTR *pBstrName,
3685 BSTR *pBstrDocString,
3686 DWORD *pdwHelpContext,
3687 BSTR *pBstrHelpFile)
3689 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3691 HRESULT result = E_INVALIDARG;
3693 ITypeInfo *pTInfo;
3696 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3697 This, index,
3698 pBstrName, pBstrDocString,
3699 pdwHelpContext, pBstrHelpFile);
3701 if(index<0)
3703 /* documentation for the typelib */
3704 if(pBstrName)
3706 if (This->Name)
3708 if(!(*pBstrName = SysAllocString(This->Name)))
3709 goto memerr1;
3711 else
3712 *pBstrName = NULL;
3714 if(pBstrDocString)
3716 if (This->DocString)
3718 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3719 goto memerr2;
3721 else if (This->Name)
3723 if(!(*pBstrDocString = SysAllocString(This->Name)))
3724 goto memerr2;
3726 else
3727 *pBstrDocString = NULL;
3729 if(pdwHelpContext)
3731 *pdwHelpContext = This->dwHelpContext;
3733 if(pBstrHelpFile)
3735 if (This->HelpFile)
3737 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3738 goto memerr3;
3740 else
3741 *pBstrHelpFile = NULL;
3744 result = S_OK;
3746 else
3748 /* for a typeinfo */
3749 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3751 if(SUCCEEDED(result))
3753 result = ITypeInfo_GetDocumentation(pTInfo,
3754 MEMBERID_NIL,
3755 pBstrName,
3756 pBstrDocString,
3757 pdwHelpContext, pBstrHelpFile);
3759 ITypeInfo_Release(pTInfo);
3762 return result;
3763 memerr3:
3764 if (pBstrDocString) SysFreeString (*pBstrDocString);
3765 memerr2:
3766 if (pBstrName) SysFreeString (*pBstrName);
3767 memerr1:
3768 return STG_E_INSUFFICIENTMEMORY;
3771 /* ITypeLib::IsName
3773 * Indicates whether a passed-in string contains the name of a type or member
3774 * described in the library.
3777 static HRESULT WINAPI ITypeLib2_fnIsName(
3778 ITypeLib2 *iface,
3779 LPOLESTR szNameBuf,
3780 ULONG lHashVal,
3781 BOOL *pfName)
3783 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3784 ITypeInfoImpl *pTInfo;
3785 TLBFuncDesc *pFInfo;
3786 TLBVarDesc *pVInfo;
3787 int i;
3788 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3790 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3791 pfName);
3793 *pfName=TRUE;
3794 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3795 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3796 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3797 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3798 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3799 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3800 goto ITypeLib2_fnIsName_exit;
3802 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3803 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3806 *pfName=FALSE;
3808 ITypeLib2_fnIsName_exit:
3809 TRACE("(%p)slow! search for %s: %s found!\n", This,
3810 debugstr_w(szNameBuf), *pfName?"NOT":"");
3812 return S_OK;
3815 /* ITypeLib::FindName
3817 * Finds occurrences of a type description in a type library. This may be used
3818 * to quickly verify that a name exists in a type library.
3821 static HRESULT WINAPI ITypeLib2_fnFindName(
3822 ITypeLib2 *iface,
3823 LPOLESTR szNameBuf,
3824 ULONG lHashVal,
3825 ITypeInfo **ppTInfo,
3826 MEMBERID *rgMemId,
3827 UINT16 *pcFound)
3829 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3830 ITypeInfoImpl *pTInfo;
3831 TLBFuncDesc *pFInfo;
3832 TLBVarDesc *pVInfo;
3833 int i,j = 0;
3834 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3836 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3837 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3838 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3839 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3840 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3841 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3842 goto ITypeLib2_fnFindName_exit;
3845 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3846 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3847 continue;
3848 ITypeLib2_fnFindName_exit:
3849 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3850 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3851 j++;
3853 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3854 This, *pcFound, debugstr_w(szNameBuf), j);
3856 *pcFound=j;
3858 return S_OK;
3861 /* ITypeLib::ReleaseTLibAttr
3863 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3866 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3867 ITypeLib2 *iface,
3868 TLIBATTR *pTLibAttr)
3870 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3871 TRACE("freeing (%p)\n",This);
3872 HeapFree(GetProcessHeap(),0,pTLibAttr);
3876 /* ITypeLib2::GetCustData
3878 * gets the custom data
3880 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3881 ITypeLib2 * iface,
3882 REFGUID guid,
3883 VARIANT *pVarVal)
3885 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3886 TLBCustData *pCData;
3888 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3890 if( IsEqualIID(guid, &pCData->guid)) break;
3893 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3895 if(pCData)
3897 VariantInit( pVarVal);
3898 VariantCopy( pVarVal, &pCData->data);
3899 return S_OK;
3901 return E_INVALIDARG; /* FIXME: correct? */
3904 /* ITypeLib2::GetLibStatistics
3906 * Returns statistics about a type library that are required for efficient
3907 * sizing of hash tables.
3910 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3911 ITypeLib2 * iface,
3912 ULONG *pcUniqueNames,
3913 ULONG *pcchUniqueNames)
3915 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3917 FIXME("(%p): stub!\n", This);
3919 if(pcUniqueNames) *pcUniqueNames=1;
3920 if(pcchUniqueNames) *pcchUniqueNames=1;
3921 return S_OK;
3924 /* ITypeLib2::GetDocumentation2
3926 * Retrieves the library's documentation string, the complete Help file name
3927 * and path, the localization context to use, and the context ID for the
3928 * library Help topic in the Help file.
3931 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3932 ITypeLib2 * iface,
3933 INT index,
3934 LCID lcid,
3935 BSTR *pbstrHelpString,
3936 DWORD *pdwHelpStringContext,
3937 BSTR *pbstrHelpStringDll)
3939 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3940 HRESULT result;
3941 ITypeInfo *pTInfo;
3943 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3945 /* the help string should be obtained from the helpstringdll,
3946 * using the _DLLGetDocumentation function, based on the supplied
3947 * lcid. Nice to do sometime...
3949 if(index<0)
3951 /* documentation for the typelib */
3952 if(pbstrHelpString)
3953 *pbstrHelpString=SysAllocString(This->DocString);
3954 if(pdwHelpStringContext)
3955 *pdwHelpStringContext=This->dwHelpContext;
3956 if(pbstrHelpStringDll)
3957 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3959 result = S_OK;
3961 else
3963 /* for a typeinfo */
3964 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3966 if(SUCCEEDED(result))
3968 ITypeInfo2 * pTInfo2;
3969 result = ITypeInfo_QueryInterface(pTInfo,
3970 &IID_ITypeInfo2,
3971 (LPVOID*) &pTInfo2);
3973 if(SUCCEEDED(result))
3975 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3976 MEMBERID_NIL,
3977 lcid,
3978 pbstrHelpString,
3979 pdwHelpStringContext,
3980 pbstrHelpStringDll);
3982 ITypeInfo2_Release(pTInfo2);
3985 ITypeInfo_Release(pTInfo);
3988 return result;
3991 /* ITypeLib2::GetAllCustData
3993 * Gets all custom data items for the library.
3996 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3997 ITypeLib2 * iface,
3998 CUSTDATA *pCustData)
4000 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4001 TLBCustData *pCData;
4002 int i;
4003 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4004 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4005 if(pCustData->prgCustData ){
4006 pCustData->cCustData=This->ctCustData;
4007 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4008 pCustData->prgCustData[i].guid=pCData->guid;
4009 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4011 }else{
4012 ERR(" OUT OF MEMORY! \n");
4013 return E_OUTOFMEMORY;
4015 return S_OK;
4018 static const ITypeLib2Vtbl tlbvt = {
4019 ITypeLib2_fnQueryInterface,
4020 ITypeLib2_fnAddRef,
4021 ITypeLib2_fnRelease,
4022 ITypeLib2_fnGetTypeInfoCount,
4023 ITypeLib2_fnGetTypeInfo,
4024 ITypeLib2_fnGetTypeInfoType,
4025 ITypeLib2_fnGetTypeInfoOfGuid,
4026 ITypeLib2_fnGetLibAttr,
4027 ITypeLib2_fnGetTypeComp,
4028 ITypeLib2_fnGetDocumentation,
4029 ITypeLib2_fnIsName,
4030 ITypeLib2_fnFindName,
4031 ITypeLib2_fnReleaseTLibAttr,
4033 ITypeLib2_fnGetCustData,
4034 ITypeLib2_fnGetLibStatistics,
4035 ITypeLib2_fnGetDocumentation2,
4036 ITypeLib2_fnGetAllCustData
4040 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4042 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4044 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4047 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4049 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4051 return ITypeLib2_AddRef((ITypeLib2 *)This);
4054 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4056 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4058 return ITypeLib2_Release((ITypeLib2 *)This);
4061 static HRESULT WINAPI ITypeLibComp_fnBind(
4062 ITypeComp * iface,
4063 OLECHAR * szName,
4064 ULONG lHash,
4065 WORD wFlags,
4066 ITypeInfo ** ppTInfo,
4067 DESCKIND * pDescKind,
4068 BINDPTR * pBindPtr)
4070 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4071 return E_NOTIMPL;
4074 static HRESULT WINAPI ITypeLibComp_fnBindType(
4075 ITypeComp * iface,
4076 OLECHAR * szName,
4077 ULONG lHash,
4078 ITypeInfo ** ppTInfo,
4079 ITypeComp ** ppTComp)
4081 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4082 return E_NOTIMPL;
4085 static const ITypeCompVtbl tlbtcvt =
4088 ITypeLibComp_fnQueryInterface,
4089 ITypeLibComp_fnAddRef,
4090 ITypeLibComp_fnRelease,
4092 ITypeLibComp_fnBind,
4093 ITypeLibComp_fnBindType
4096 /*================== ITypeInfo(2) Methods ===================================*/
4097 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4099 ITypeInfoImpl * pTypeInfoImpl;
4101 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4102 if (pTypeInfoImpl)
4104 pTypeInfoImpl->lpVtbl = &tinfvt;
4105 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4106 pTypeInfoImpl->ref=1;
4108 TRACE("(%p)\n", pTypeInfoImpl);
4109 return (ITypeInfo2*) pTypeInfoImpl;
4112 /* ITypeInfo::QueryInterface
4114 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4115 ITypeInfo2 *iface,
4116 REFIID riid,
4117 VOID **ppvObject)
4119 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4121 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4123 *ppvObject=NULL;
4124 if(IsEqualIID(riid, &IID_IUnknown) ||
4125 IsEqualIID(riid,&IID_ITypeInfo)||
4126 IsEqualIID(riid,&IID_ITypeInfo2))
4127 *ppvObject = This;
4129 if(*ppvObject){
4130 ITypeInfo_AddRef(iface);
4131 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4132 return S_OK;
4134 TRACE("-- Interface: E_NOINTERFACE\n");
4135 return E_NOINTERFACE;
4138 /* ITypeInfo::AddRef
4140 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4142 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4143 ULONG ref = InterlockedIncrement(&This->ref);
4145 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4147 TRACE("(%p)->ref is %lu\n",This, ref);
4148 return ref;
4151 /* ITypeInfo::Release
4153 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4155 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4156 ULONG ref = InterlockedDecrement(&This->ref);
4158 TRACE("(%p)->(%lu)\n",This, ref);
4160 if (ref) {
4161 /* We don't release ITypeLib when ref=0 because
4162 it means that function is called by ITypeLib2_Release */
4163 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4164 } else {
4165 FIXME("destroy child objects\n");
4167 TRACE("destroying ITypeInfo(%p)\n",This);
4168 if (This->Name)
4170 SysFreeString(This->Name);
4171 This->Name = 0;
4174 if (This->DocString)
4176 SysFreeString(This->DocString);
4177 This->DocString = 0;
4180 if (This->DllName)
4182 SysFreeString(This->DllName);
4183 This->DllName = 0;
4186 if (This->next)
4188 ITypeInfo_Release((ITypeInfo*)This->next);
4191 HeapFree(GetProcessHeap(),0,This);
4192 return 0;
4194 return ref;
4197 /* ITypeInfo::GetTypeAttr
4199 * Retrieves a TYPEATTR structure that contains the attributes of the type
4200 * description.
4203 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4204 LPTYPEATTR *ppTypeAttr)
4206 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4207 TRACE("(%p)\n",This);
4208 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr));
4209 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4211 if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */
4212 copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias);
4214 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4215 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4216 funcs */
4217 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4218 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4220 return S_OK;
4223 /* ITypeInfo::GetTypeComp
4225 * Retrieves the ITypeComp interface for the type description, which enables a
4226 * client compiler to bind to the type description's members.
4229 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4230 ITypeComp * *ppTComp)
4232 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4234 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4236 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4237 ITypeComp_AddRef(*ppTComp);
4238 return S_OK;
4241 /* ITypeInfo::GetFuncDesc
4243 * Retrieves the FUNCDESC structure that contains information about a
4244 * specified function.
4247 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4248 LPFUNCDESC *ppFuncDesc)
4250 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4251 int i;
4252 TLBFuncDesc * pFDesc;
4253 TRACE("(%p) index %d\n", This, index);
4254 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4256 if(pFDesc){
4257 /* FIXME: must do a copy here */
4258 *ppFuncDesc=&pFDesc->funcdesc;
4259 return S_OK;
4261 return E_INVALIDARG;
4264 /* ITypeInfo::GetVarDesc
4266 * Retrieves a VARDESC structure that describes the specified variable.
4269 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4270 LPVARDESC *ppVarDesc)
4272 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4273 int i;
4274 TLBVarDesc * pVDesc;
4275 TRACE("(%p) index %d\n", This, index);
4276 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4278 if(pVDesc){
4279 /* FIXME: must do a copy here */
4280 *ppVarDesc=&pVDesc->vardesc;
4281 return S_OK;
4283 return E_INVALIDARG;
4286 /* ITypeInfo_GetNames
4288 * Retrieves the variable with the specified member ID (or the name of the
4289 * property or method and its parameters) that correspond to the specified
4290 * function ID.
4292 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4293 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4295 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4296 TLBFuncDesc * pFDesc;
4297 TLBVarDesc * pVDesc;
4298 int i;
4299 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4300 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4301 if(pFDesc)
4303 /* function found, now return function and parameter names */
4304 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4306 if(!i)
4307 *rgBstrNames=SysAllocString(pFDesc->Name);
4308 else
4309 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4311 *pcNames=i;
4313 else
4315 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4316 if(pVDesc)
4318 *rgBstrNames=SysAllocString(pVDesc->Name);
4319 *pcNames=1;
4321 else
4323 if(This->TypeAttr.cImplTypes &&
4324 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4325 /* recursive search */
4326 ITypeInfo *pTInfo;
4327 HRESULT result;
4328 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4329 &pTInfo);
4330 if(SUCCEEDED(result))
4332 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4333 ITypeInfo_Release(pTInfo);
4334 return result;
4336 WARN("Could not search inherited interface!\n");
4338 else
4340 WARN("no names found\n");
4342 *pcNames=0;
4343 return TYPE_E_ELEMENTNOTFOUND;
4346 return S_OK;
4350 /* ITypeInfo::GetRefTypeOfImplType
4352 * If a type description describes a COM class, it retrieves the type
4353 * description of the implemented interface types. For an interface,
4354 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4355 * if any exist.
4358 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4359 ITypeInfo2 *iface,
4360 UINT index,
4361 HREFTYPE *pRefType)
4363 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4364 int i;
4365 HRESULT hr = S_OK;
4366 TLBImplType *pImpl = This->impltypelist;
4368 TRACE("(%p) index %d\n", This, index);
4369 if (TRACE_ON(ole)) dump_TypeInfo(This);
4371 if(index==(UINT)-1)
4373 /* only valid on dual interfaces;
4374 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4376 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4378 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4379 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4381 *pRefType = -1;
4383 else
4385 hr = TYPE_E_ELEMENTNOTFOUND;
4388 else
4390 /* get element n from linked list */
4391 for(i=0; pImpl && i<index; i++)
4393 pImpl = pImpl->next;
4396 if (pImpl)
4397 *pRefType = pImpl->hRef;
4398 else
4399 hr = TYPE_E_ELEMENTNOTFOUND;
4402 if(TRACE_ON(ole))
4404 if(SUCCEEDED(hr))
4405 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4406 else
4407 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4410 return hr;
4413 /* ITypeInfo::GetImplTypeFlags
4415 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4416 * or base interface in a type description.
4418 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4419 UINT index, INT *pImplTypeFlags)
4421 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4422 int i;
4423 TLBImplType *pImpl;
4425 TRACE("(%p) index %d\n", This, index);
4426 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4427 i++, pImpl=pImpl->next)
4429 if(i==index && pImpl){
4430 *pImplTypeFlags=pImpl->implflags;
4431 return S_OK;
4433 *pImplTypeFlags=0;
4434 return TYPE_E_ELEMENTNOTFOUND;
4437 /* GetIDsOfNames
4438 * Maps between member names and member IDs, and parameter names and
4439 * parameter IDs.
4441 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4442 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4444 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4445 TLBFuncDesc * pFDesc;
4446 TLBVarDesc * pVDesc;
4447 HRESULT ret=S_OK;
4449 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4450 cNames);
4451 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4452 int i, j;
4453 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4454 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4455 for(i=1; i < cNames; i++){
4456 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4457 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4458 break;
4459 if( j<pFDesc->funcdesc.cParams)
4460 pMemId[i]=j;
4461 else
4462 ret=DISP_E_UNKNOWNNAME;
4464 return ret;
4467 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4468 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4469 if(cNames) *pMemId=pVDesc->vardesc.memid;
4470 return ret;
4473 /* not found, see if this is and interface with an inheritance */
4474 if(This->TypeAttr.cImplTypes &&
4475 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4476 /* recursive search */
4477 ITypeInfo *pTInfo;
4478 ret=ITypeInfo_GetRefTypeInfo(iface,
4479 This->impltypelist->hRef, &pTInfo);
4480 if(SUCCEEDED(ret)){
4481 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4482 ITypeInfo_Release(pTInfo);
4483 return ret;
4485 WARN("Could not search inherited interface!\n");
4486 } else
4487 WARN("no names found\n");
4488 return DISP_E_UNKNOWNNAME;
4491 /* ITypeInfo::Invoke
4493 * Invokes a method, or accesses a property of an object, that implements the
4494 * interface described by the type description.
4496 DWORD
4497 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4498 DWORD res;
4500 if (TRACE_ON(ole)) {
4501 int i;
4502 TRACE("Calling %p(",func);
4503 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4504 TRACE(")\n");
4507 switch (callconv) {
4508 case CC_STDCALL:
4510 switch (nrargs) {
4511 case 0:
4512 res = func();
4513 break;
4514 case 1:
4515 res = func(args[0]);
4516 break;
4517 case 2:
4518 res = func(args[0],args[1]);
4519 break;
4520 case 3:
4521 res = func(args[0],args[1],args[2]);
4522 break;
4523 case 4:
4524 res = func(args[0],args[1],args[2],args[3]);
4525 break;
4526 case 5:
4527 res = func(args[0],args[1],args[2],args[3],args[4]);
4528 break;
4529 case 6:
4530 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4531 break;
4532 case 7:
4533 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4534 break;
4535 case 8:
4536 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4537 break;
4538 case 9:
4539 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4540 break;
4541 case 10:
4542 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4543 break;
4544 case 11:
4545 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4546 break;
4547 case 12:
4548 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
4549 break;
4550 case 13:
4551 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
4552 break;
4553 case 14:
4554 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
4555 break;
4556 default:
4557 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4558 res = -1;
4559 break;
4561 break;
4562 default:
4563 FIXME("unsupported calling convention %d\n",callconv);
4564 res = -1;
4565 break;
4567 TRACE("returns %08lx\n",res);
4568 return res;
4571 extern int _argsize(DWORD vt);
4573 /****************************************************************************
4574 * Helper functions for Dispcall / Invoke, which copies one variant
4575 * with target type onto the argument stack.
4577 static HRESULT
4578 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4579 DWORD *argpos, VARIANT *arg, VARTYPE vt
4581 UINT arglen = _argsize(vt)*sizeof(DWORD);
4582 VARIANT va;
4584 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4585 memcpy(argpos,&arg,sizeof(void*));
4586 return S_OK;
4589 if (V_VT(arg) == vt) {
4590 memcpy(argpos, &V_I4(arg), arglen);
4591 return S_OK;
4594 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4595 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4596 return S_OK;
4599 if (vt == VT_VARIANT) {
4600 memcpy(argpos, arg, arglen);
4601 return S_OK;
4603 /* Deref BYREF vars if there is need */
4604 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4605 memcpy(argpos,(void*)V_I4(arg), arglen);
4606 return S_OK;
4608 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4609 /* in this context, if the type lib specifies IUnknown*, giving an
4610 IDispatch* is correct; so, don't invoke VariantChangeType */
4611 memcpy(argpos,&V_I4(arg), arglen);
4612 return S_OK;
4614 if ((vt == VT_PTR) && tdesc)
4615 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4617 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4618 ITypeInfo *tinfo2 = NULL;
4619 TYPEATTR *tattr = NULL;
4620 HRESULT hres;
4622 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4623 if (hres) {
4624 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4625 "while coercing from vt 0x%x. Copying 4 byte.\n",
4626 tdesc->u.hreftype,V_VT(arg));
4627 memcpy(argpos, &V_I4(arg), 4);
4628 return S_OK;
4630 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4631 if( hres )
4633 ERR("GetTypeAttr failed\n");
4634 ITypeInfo_Release(tinfo2);
4635 return hres;
4637 switch (tattr->typekind) {
4638 case TKIND_ENUM:
4639 switch ( V_VT( arg ) ) {
4640 case VT_I2:
4641 *argpos = V_I2(arg);
4642 hres = S_OK;
4643 break;
4644 case VT_I4:
4645 memcpy(argpos, &V_I4(arg), 4);
4646 hres = S_OK;
4647 break;
4648 case VT_BYREF|VT_I4:
4649 memcpy(argpos, V_I4REF(arg), 4);
4650 hres = S_OK;
4651 break;
4652 default:
4653 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4654 hres = E_FAIL;
4655 break;
4657 break;
4659 case TKIND_ALIAS:
4660 tdesc = &(tattr->tdescAlias);
4661 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4662 break;
4664 case TKIND_INTERFACE:
4665 if (V_VT(arg) == VT_DISPATCH) {
4666 IDispatch *disp;
4667 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4668 memcpy(argpos, &V_DISPATCH(arg), 4);
4669 hres = S_OK;
4670 break;
4672 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4673 &IID_IDispatch,(LPVOID*)&disp);
4674 if (SUCCEEDED(hres)) {
4675 memcpy(argpos,&disp,4);
4676 IUnknown_Release(V_DISPATCH(arg));
4677 hres = S_OK;
4678 break;
4680 FIXME("Failed to query IDispatch interface from %s while "
4681 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4682 hres = E_FAIL;
4683 break;
4685 if (V_VT(arg) == VT_UNKNOWN) {
4686 memcpy(argpos, &V_UNKNOWN(arg), 4);
4687 hres = S_OK;
4688 break;
4690 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4691 V_VT(arg),debugstr_guid(&(tattr->guid)));
4692 hres = E_FAIL;
4693 break;
4695 case TKIND_DISPATCH:
4696 if (V_VT(arg) == VT_DISPATCH) {
4697 memcpy(argpos, &V_DISPATCH(arg), 4);
4698 hres = S_OK;
4700 else {
4701 hres = E_FAIL;
4702 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4704 break;
4705 case TKIND_RECORD:
4706 FIXME("TKIND_RECORD unhandled.\n");
4707 hres = E_FAIL;
4708 break;
4709 default:
4710 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4711 hres = E_FAIL;
4712 break;
4714 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4715 ITypeInfo_Release(tinfo2);
4716 return hres;
4719 VariantInit(&va);
4720 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4721 memcpy(argpos,&V_I4(&va), arglen);
4722 FIXME("Should not use VariantChangeType here."
4723 " (conversion from 0x%x -> 0x%x) %08lx\n",
4724 V_VT(arg), vt, *argpos
4726 return S_OK;
4728 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4729 return E_FAIL;
4732 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
4734 HRESULT hr = S_OK;
4735 ITypeInfo *tinfo2 = NULL;
4736 TYPEATTR *tattr = NULL;
4738 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4739 if (hr)
4741 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4742 "hr = 0x%08lx\n",
4743 tdesc->u.hreftype, hr);
4744 return hr;
4746 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4747 if (hr)
4749 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4750 ITypeInfo_Release(tinfo2);
4751 return hr;
4754 switch (tattr->typekind)
4756 case TKIND_ENUM:
4757 *vt |= VT_INT;
4758 break;
4760 case TKIND_ALIAS:
4761 tdesc = &tattr->tdescAlias;
4762 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4763 break;
4765 case TKIND_INTERFACE:
4766 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4767 *vt |= VT_DISPATCH;
4768 else
4769 *vt |= VT_UNKNOWN;
4770 break;
4772 case TKIND_DISPATCH:
4773 *vt |= VT_DISPATCH;
4774 break;
4776 case TKIND_RECORD:
4777 FIXME("TKIND_RECORD unhandled.\n");
4778 hr = E_NOTIMPL;
4779 break;
4781 case TKIND_UNION:
4782 FIXME("TKIND_RECORD unhandled.\n");
4783 hr = E_NOTIMPL;
4784 break;
4786 default:
4787 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4788 hr = E_NOTIMPL;
4789 break;
4791 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4792 ITypeInfo_Release(tinfo2);
4793 return hr;
4796 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
4798 HRESULT hr = S_OK;
4800 /* enforce only one level of pointer indirection */
4801 if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
4803 tdesc = tdesc->u.lptdesc;
4805 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4806 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4807 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4808 if ((tdesc->vt == VT_USERDEFINED) ||
4809 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4811 VARTYPE vt_userdefined = 0;
4812 TYPEDESC *tdesc_userdefined = tdesc;
4813 if (tdesc->vt == VT_PTR)
4815 vt_userdefined = VT_BYREF;
4816 tdesc_userdefined = tdesc->u.lptdesc;
4818 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
4819 if ((hr == S_OK) &&
4820 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
4821 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
4823 *vt |= vt_userdefined;
4824 return S_OK;
4827 *vt = VT_BYREF;
4830 switch (tdesc->vt)
4832 case VT_HRESULT:
4833 *vt |= VT_ERROR;
4834 break;
4835 case VT_USERDEFINED:
4836 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
4837 break;
4838 case VT_PTR:
4839 ERR("cannot convert VT_PTR into variant VT\n");
4840 hr = E_FAIL;
4841 break;
4842 default:
4843 *vt |= tdesc->vt;
4844 break;
4846 return hr;
4849 /***********************************************************************
4850 * DispCallFunc (OLEAUT32.@)
4852 HRESULT WINAPI
4853 DispCallFunc(
4854 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4855 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4857 int i, argsize, argspos;
4858 DWORD *args;
4859 HRESULT hres;
4861 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4862 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4864 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4865 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4866 argsize = 1;
4867 for (i=0;i<cActuals;i++) {
4868 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4869 dump_Variant(prgpvarg[i]);
4870 argsize += _argsize(prgvt[i]);
4872 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4873 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4874 argspos = 1;
4875 for (i=0;i<cActuals;i++) {
4876 VARIANT *arg = prgpvarg[i];
4877 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4878 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4879 argspos += _argsize(prgvt[i]);
4882 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4884 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4885 hres=S_OK;
4887 else
4889 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4890 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4891 FIXME("Method returned %lx\n",hres);
4893 HeapFree(GetProcessHeap(),0,args);
4894 return hres;
4897 static HRESULT WINAPI ITypeInfo_fnInvoke(
4898 ITypeInfo2 *iface,
4899 VOID *pIUnk,
4900 MEMBERID memid,
4901 UINT16 dwFlags,
4902 DISPPARAMS *pDispParams,
4903 VARIANT *pVarResult,
4904 EXCEPINFO *pExcepInfo,
4905 UINT *pArgErr)
4907 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4908 int i;
4909 unsigned int func_index, var_index;
4910 TYPEKIND type_kind;
4911 HRESULT hres;
4913 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4914 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4916 dump_DispParms(pDispParams);
4918 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4919 if (SUCCEEDED(hres)) {
4920 FUNCDESC *func_desc;
4922 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4923 if(FAILED(hres)) return hres;
4924 if (TRACE_ON(ole))
4926 TRACE("invoking:\n");
4927 dump_FUNCDESC(func_desc);
4930 switch (func_desc->funckind) {
4931 case FUNC_PUREVIRTUAL:
4932 case FUNC_VIRTUAL: {
4933 DWORD res;
4934 int numargs, numargs2, argspos, args2pos;
4935 DWORD *args , *args2;
4936 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4937 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4939 hres = S_OK;
4940 numargs = 1; /* sizeof(thisptr) */
4941 numargs2 = 0;
4942 for (i = 0; i < func_desc->cParams; i++) {
4943 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4945 numargs += _argsize(tdesc->vt);
4946 if (i>=pDispParams->cArgs) { /* arguments to return */
4947 if (tdesc->vt == VT_PTR) {
4948 numargs2 += _argsize(tdesc->u.lptdesc->vt);
4949 } else {
4950 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
4951 numargs2 += _argsize(tdesc->vt);
4956 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4957 args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
4959 args[0] = (DWORD)pIUnk;
4960 argspos = 1; args2pos = 0;
4961 for (i = 0; i < func_desc->cParams; i++) {
4962 ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
4963 TYPEDESC *tdesc = &(elemdesc->tdesc);
4964 USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
4965 int arglen = _argsize(tdesc->vt);
4967 if (i<pDispParams->cArgs) {
4968 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4970 if (paramFlags & PARAMFLAG_FOPT) {
4971 if(i < func_desc->cParams - func_desc->cParamsOpt)
4972 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4973 if(V_VT(arg) == VT_EMPTY
4974 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
4975 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4976 How to determine it? */
4978 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4979 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4980 V_VT(arg) = VT_ERROR;
4981 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4982 arglen = _argsize(VT_ERROR);
4985 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4986 if (FAILED(hres)) goto func_fail;
4987 argspos += arglen;
4988 } else if (paramFlags & PARAMFLAG_FOPT) {
4989 VARIANT *arg = &rgvarg[i];
4991 if (i < func_desc->cParams - func_desc->cParamsOpt)
4992 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4993 if (paramFlags & PARAMFLAG_FHASDEFAULT)
4994 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4996 V_VT(arg) = VT_ERROR;
4997 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4998 arglen = _argsize(VT_ERROR);
4999 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5000 if (FAILED(hres)) goto func_fail;
5001 argspos += arglen;
5002 } else {
5003 if (tdesc->vt == VT_PTR)
5004 arglen = _argsize(tdesc->u.lptdesc->vt);
5005 else
5006 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
5008 /* Supply pointers for the rest, so propertyget works*/
5009 args[argspos] = (DWORD)&args2[args2pos];
5011 /* If pointer to variant, pass reference it. */
5012 if ((tdesc->vt == VT_PTR) &&
5013 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
5014 pVarResult
5016 args[argspos]= (DWORD)pVarResult;
5017 argspos += 1;
5018 args2pos += arglen;
5021 if (func_desc->cParamsOpt < 0)
5022 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
5024 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
5025 func_desc->callconv,
5026 numargs,
5027 args
5030 if (pVarResult) {
5031 for (i = 0; i < func_desc->cParams; i++) {
5032 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5033 if (wParamFlags & PARAMFLAG_FRETVAL) {
5034 ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
5035 TYPEDESC *tdesc = &elemdesc->tdesc;
5036 VARIANTARG varresult;
5037 V_VT(&varresult) = 0;
5038 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
5039 if (hres)
5040 break;
5041 /* FIXME: this is really messy - we should keep the
5042 * args in VARIANTARGs rather than a DWORD array */
5043 memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
5044 if (TRACE_ON(ole))
5046 TRACE("varresult: ");
5047 dump_Variant(&varresult);
5049 hres = VariantCopyInd(pVarResult, &varresult);
5050 /* free data stored in varresult. Note that
5051 * VariantClear doesn't do what we want because we are
5052 * working with byref types. */
5053 /* FIXME: clear safearrays, bstrs, records and
5054 * variants here too */
5055 if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) ||
5056 (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF)))
5057 IUnknown_Release(*V_UNKNOWNREF(&varresult));
5058 break;
5063 if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
5064 WARN("invoked function failed with error 0x%08lx\n", res);
5065 hres = DISP_E_EXCEPTION;
5066 if (pExcepInfo) pExcepInfo->scode = res;
5068 func_fail:
5069 HeapFree(GetProcessHeap(), 0, rgvarg);
5070 HeapFree(GetProcessHeap(),0,args2);
5071 HeapFree(GetProcessHeap(),0,args);
5072 break;
5074 case FUNC_DISPATCH: {
5075 IDispatch *disp;
5077 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5078 if (SUCCEEDED(hres)) {
5079 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5080 hres = IDispatch_Invoke(
5081 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
5082 pVarResult,pExcepInfo,pArgErr
5084 if (FAILED(hres))
5085 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5086 IDispatch_Release(disp);
5087 } else
5088 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5089 break;
5091 default:
5092 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5093 hres = E_FAIL;
5094 break;
5097 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
5098 return hres;
5100 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5101 VARDESC *var_desc;
5103 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5104 if(FAILED(hres)) return hres;
5106 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5107 dump_VARDESC(var_desc);
5108 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5109 return E_NOTIMPL;
5112 /* not found, look for it in inherited interfaces */
5113 ITypeInfo2_GetTypeKind(iface, &type_kind);
5114 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5115 HREFTYPE ref_type;
5116 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5117 /* recursive search */
5118 ITypeInfo *pTInfo;
5119 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5120 if(SUCCEEDED(hres)){
5121 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5122 ITypeInfo_Release(pTInfo);
5123 return hres;
5125 WARN("Could not search inherited interface!\n");
5128 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
5129 return DISP_E_MEMBERNOTFOUND;
5132 /* ITypeInfo::GetDocumentation
5134 * Retrieves the documentation string, the complete Help file name and path,
5135 * and the context ID for the Help topic for a specified type description.
5137 * (Can be tested by the Visual Basic Editor in Word for instance.)
5139 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5140 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5141 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5143 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5144 TLBFuncDesc * pFDesc;
5145 TLBVarDesc * pVDesc;
5146 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5147 " HelpContext(%p) HelpFile(%p)\n",
5148 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5149 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5150 if(pBstrName)
5151 *pBstrName=SysAllocString(This->Name);
5152 if(pBstrDocString)
5153 *pBstrDocString=SysAllocString(This->DocString);
5154 if(pdwHelpContext)
5155 *pdwHelpContext=This->dwHelpContext;
5156 if(pBstrHelpFile)
5157 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5158 return S_OK;
5159 }else {/* for a member */
5160 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5161 if(pFDesc->funcdesc.memid==memid){
5162 if(pBstrName)
5163 *pBstrName = SysAllocString(pFDesc->Name);
5164 if(pBstrDocString)
5165 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5166 if(pdwHelpContext)
5167 *pdwHelpContext=pFDesc->helpcontext;
5168 return S_OK;
5170 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5171 if(pVDesc->vardesc.memid==memid){
5172 if(pBstrName)
5173 *pBstrName = SysAllocString(pVDesc->Name);
5174 if(pBstrDocString)
5175 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5176 if(pdwHelpContext)
5177 *pdwHelpContext=pVDesc->HelpContext;
5178 return S_OK;
5181 WARN("member %ld not found\n", memid);
5182 return TYPE_E_ELEMENTNOTFOUND;
5185 /* ITypeInfo::GetDllEntry
5187 * Retrieves a description or specification of an entry point for a function
5188 * in a DLL.
5190 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5191 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5192 WORD *pwOrdinal)
5194 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5195 TLBFuncDesc *pFDesc;
5197 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5199 if (pBstrDllName) *pBstrDllName = NULL;
5200 if (pBstrName) *pBstrName = NULL;
5201 if (pwOrdinal) *pwOrdinal = 0;
5203 if (This->TypeAttr.typekind != TKIND_MODULE)
5204 return TYPE_E_BADMODULEKIND;
5206 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5207 if(pFDesc->funcdesc.memid==memid){
5208 dump_TypeInfo(This);
5209 dump_TLBFuncDescOne(pFDesc);
5211 if (pBstrDllName)
5212 *pBstrDllName = SysAllocString(This->DllName);
5214 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5215 if (pBstrName)
5216 *pBstrName = SysAllocString(pFDesc->Entry);
5217 if (pwOrdinal)
5218 *pwOrdinal = -1;
5219 return S_OK;
5221 if (pBstrName)
5222 *pBstrName = NULL;
5223 if (pwOrdinal)
5224 *pwOrdinal = (DWORD)pFDesc->Entry;
5225 return S_OK;
5227 return TYPE_E_ELEMENTNOTFOUND;
5230 /* ITypeInfo::GetRefTypeInfo
5232 * If a type description references other type descriptions, it retrieves
5233 * the referenced type descriptions.
5235 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5236 ITypeInfo2 *iface,
5237 HREFTYPE hRefType,
5238 ITypeInfo **ppTInfo)
5240 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5241 HRESULT result = E_FAIL;
5243 if (hRefType == -1 &&
5244 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5245 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5247 /* when we meet a DUAL dispinterface, we must create the interface
5248 * version of it.
5250 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5253 /* the interface version contains the same information as the dispinterface
5254 * copy the contents of the structs.
5256 *pTypeInfoImpl = *This;
5257 pTypeInfoImpl->ref = 1;
5259 /* change the type to interface */
5260 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5262 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5264 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5266 result = S_OK;
5268 } else {
5269 TLBRefType *pRefType;
5270 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5271 if(pRefType->reference == hRefType)
5272 break;
5274 if(!pRefType)
5275 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5276 if(pRefType && hRefType != -1) {
5277 ITypeLib *pTLib = NULL;
5279 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5280 UINT Index;
5281 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5282 } else {
5283 if(pRefType->pImpTLInfo->pImpTypeLib) {
5284 TRACE("typeinfo in imported typelib that is already loaded\n");
5285 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5286 ITypeLib2_AddRef((ITypeLib*) pTLib);
5287 result = S_OK;
5288 } else {
5289 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5290 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5291 pRefType->pImpTLInfo->wVersionMajor,
5292 pRefType->pImpTLInfo->wVersionMinor,
5293 pRefType->pImpTLInfo->lcid,
5294 &pTLib);
5296 if(!SUCCEEDED(result)) {
5297 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5298 result=LoadTypeLib(libnam, &pTLib);
5299 SysFreeString(libnam);
5301 if(SUCCEEDED(result)) {
5302 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5303 ITypeLib2_AddRef(pTLib);
5307 if(SUCCEEDED(result)) {
5308 if(pRefType->index == TLB_REF_USE_GUID)
5309 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5310 &pRefType->guid,
5311 ppTInfo);
5312 else
5313 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5314 ppTInfo);
5316 if (pTLib != NULL)
5317 ITypeLib2_Release(pTLib);
5321 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5322 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5323 return result;
5326 /* ITypeInfo::AddressOfMember
5328 * Retrieves the addresses of static functions or variables, such as those
5329 * defined in a DLL.
5331 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5332 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5334 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5335 FIXME("(%p) stub!\n", This);
5336 return S_OK;
5339 /* ITypeInfo::CreateInstance
5341 * Creates a new instance of a type that describes a component object class
5342 * (coclass).
5344 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5345 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5347 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5348 FIXME("(%p) stub!\n", This);
5349 return S_OK;
5352 /* ITypeInfo::GetMops
5354 * Retrieves marshalling information.
5356 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5357 BSTR *pBstrMops)
5359 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5360 FIXME("(%p) stub!\n", This);
5361 return S_OK;
5364 /* ITypeInfo::GetContainingTypeLib
5366 * Retrieves the containing type library and the index of the type description
5367 * within that type library.
5369 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5370 ITypeLib * *ppTLib, UINT *pIndex)
5372 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5374 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5375 if (pIndex) {
5376 *pIndex=This->index;
5377 TRACE("returning pIndex=%d\n", *pIndex);
5380 if (ppTLib) {
5381 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5382 ITypeLib2_AddRef(*ppTLib);
5383 TRACE("returning ppTLib=%p\n", *ppTLib);
5386 return S_OK;
5389 /* ITypeInfo::ReleaseTypeAttr
5391 * Releases a TYPEATTR previously returned by GetTypeAttr.
5394 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5395 TYPEATTR* pTypeAttr)
5397 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5398 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5399 if(This->TypeAttr.typekind == TKIND_ALIAS)
5400 free_deep_typedesc(&pTypeAttr->tdescAlias);
5401 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5404 /* ITypeInfo::ReleaseFuncDesc
5406 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5408 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5409 ITypeInfo2 *iface,
5410 FUNCDESC *pFuncDesc)
5412 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5413 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5416 /* ITypeInfo::ReleaseVarDesc
5418 * Releases a VARDESC previously returned by GetVarDesc.
5420 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5421 VARDESC *pVarDesc)
5423 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5424 TRACE("(%p)->(%p)\n", This, pVarDesc);
5427 /* ITypeInfo2::GetTypeKind
5429 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5432 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5433 TYPEKIND *pTypeKind)
5435 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5436 *pTypeKind=This->TypeAttr.typekind;
5437 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5438 return S_OK;
5441 /* ITypeInfo2::GetTypeFlags
5443 * Returns the type flags without any allocations. This returns a DWORD type
5444 * flag, which expands the type flags without growing the TYPEATTR (type
5445 * attribute).
5448 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5450 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5451 *pTypeFlags=This->TypeAttr.wTypeFlags;
5452 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5453 return S_OK;
5456 /* ITypeInfo2::GetFuncIndexOfMemId
5457 * Binds to a specific member based on a known DISPID, where the member name
5458 * is not known (for example, when binding to a default member).
5461 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5462 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5464 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5465 TLBFuncDesc *pFuncInfo;
5466 int i;
5467 HRESULT result;
5469 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5470 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5471 break;
5472 if(pFuncInfo) {
5473 *pFuncIndex = i;
5474 result = S_OK;
5475 } else
5476 result = TYPE_E_ELEMENTNOTFOUND;
5478 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5479 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5480 return result;
5483 /* TypeInfo2::GetVarIndexOfMemId
5485 * Binds to a specific member based on a known DISPID, where the member name
5486 * is not known (for example, when binding to a default member).
5489 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5490 MEMBERID memid, UINT *pVarIndex)
5492 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5493 TLBVarDesc *pVarInfo;
5494 int i;
5495 HRESULT result;
5496 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5497 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5499 if(pVarInfo) {
5500 *pVarIndex = i;
5501 result = S_OK;
5502 } else
5503 result = TYPE_E_ELEMENTNOTFOUND;
5505 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5506 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5507 return result;
5510 /* ITypeInfo2::GetCustData
5512 * Gets the custom data
5514 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5515 ITypeInfo2 * iface,
5516 REFGUID guid,
5517 VARIANT *pVarVal)
5519 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5520 TLBCustData *pCData;
5522 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5523 if( IsEqualIID(guid, &pCData->guid)) break;
5525 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5527 if(pCData)
5529 VariantInit( pVarVal);
5530 VariantCopy( pVarVal, &pCData->data);
5531 return S_OK;
5533 return E_INVALIDARG; /* FIXME: correct? */
5536 /* ITypeInfo2::GetFuncCustData
5538 * Gets the custom data
5540 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5541 ITypeInfo2 * iface,
5542 UINT index,
5543 REFGUID guid,
5544 VARIANT *pVarVal)
5546 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5547 TLBCustData *pCData=NULL;
5548 TLBFuncDesc * pFDesc;
5549 int i;
5550 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5551 pFDesc=pFDesc->next);
5553 if(pFDesc)
5554 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5555 if( IsEqualIID(guid, &pCData->guid)) break;
5557 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5559 if(pCData){
5560 VariantInit( pVarVal);
5561 VariantCopy( pVarVal, &pCData->data);
5562 return S_OK;
5564 return E_INVALIDARG; /* FIXME: correct? */
5567 /* ITypeInfo2::GetParamCustData
5569 * Gets the custom data
5571 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5572 ITypeInfo2 * iface,
5573 UINT indexFunc,
5574 UINT indexParam,
5575 REFGUID guid,
5576 VARIANT *pVarVal)
5578 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5579 TLBCustData *pCData=NULL;
5580 TLBFuncDesc * pFDesc;
5581 int i;
5583 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5585 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5586 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5587 pCData = pCData->next)
5588 if( IsEqualIID(guid, &pCData->guid)) break;
5590 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5592 if(pCData)
5594 VariantInit( pVarVal);
5595 VariantCopy( pVarVal, &pCData->data);
5596 return S_OK;
5598 return E_INVALIDARG; /* FIXME: correct? */
5601 /* ITypeInfo2::GetVarCustData
5603 * Gets the custom data
5605 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5606 ITypeInfo2 * iface,
5607 UINT index,
5608 REFGUID guid,
5609 VARIANT *pVarVal)
5611 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5612 TLBCustData *pCData=NULL;
5613 TLBVarDesc * pVDesc;
5614 int i;
5616 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5618 if(pVDesc)
5620 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5622 if( IsEqualIID(guid, &pCData->guid)) break;
5626 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5628 if(pCData)
5630 VariantInit( pVarVal);
5631 VariantCopy( pVarVal, &pCData->data);
5632 return S_OK;
5634 return E_INVALIDARG; /* FIXME: correct? */
5637 /* ITypeInfo2::GetImplCustData
5639 * Gets the custom data
5641 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5642 ITypeInfo2 * iface,
5643 UINT index,
5644 REFGUID guid,
5645 VARIANT *pVarVal)
5647 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5648 TLBCustData *pCData=NULL;
5649 TLBImplType * pRDesc;
5650 int i;
5652 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5654 if(pRDesc)
5656 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5658 if( IsEqualIID(guid, &pCData->guid)) break;
5662 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5664 if(pCData)
5666 VariantInit( pVarVal);
5667 VariantCopy( pVarVal, &pCData->data);
5668 return S_OK;
5670 return E_INVALIDARG; /* FIXME: correct? */
5673 /* ITypeInfo2::GetDocumentation2
5675 * Retrieves the documentation string, the complete Help file name and path,
5676 * the localization context to use, and the context ID for the library Help
5677 * topic in the Help file.
5680 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5681 ITypeInfo2 * iface,
5682 MEMBERID memid,
5683 LCID lcid,
5684 BSTR *pbstrHelpString,
5685 DWORD *pdwHelpStringContext,
5686 BSTR *pbstrHelpStringDll)
5688 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5689 TLBFuncDesc * pFDesc;
5690 TLBVarDesc * pVDesc;
5691 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5692 "HelpStringContext(%p) HelpStringDll(%p)\n",
5693 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5694 pbstrHelpStringDll );
5695 /* the help string should be obtained from the helpstringdll,
5696 * using the _DLLGetDocumentation function, based on the supplied
5697 * lcid. Nice to do sometime...
5699 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5700 if(pbstrHelpString)
5701 *pbstrHelpString=SysAllocString(This->Name);
5702 if(pdwHelpStringContext)
5703 *pdwHelpStringContext=This->dwHelpStringContext;
5704 if(pbstrHelpStringDll)
5705 *pbstrHelpStringDll=
5706 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5707 return S_OK;
5708 }else {/* for a member */
5709 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5710 if(pFDesc->funcdesc.memid==memid){
5711 if(pbstrHelpString)
5712 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5713 if(pdwHelpStringContext)
5714 *pdwHelpStringContext=pFDesc->HelpStringContext;
5715 if(pbstrHelpStringDll)
5716 *pbstrHelpStringDll=
5717 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5718 return S_OK;
5720 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5721 if(pVDesc->vardesc.memid==memid){
5722 if(pbstrHelpString)
5723 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5724 if(pdwHelpStringContext)
5725 *pdwHelpStringContext=pVDesc->HelpStringContext;
5726 if(pbstrHelpStringDll)
5727 *pbstrHelpStringDll=
5728 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5729 return S_OK;
5732 return TYPE_E_ELEMENTNOTFOUND;
5735 /* ITypeInfo2::GetAllCustData
5737 * Gets all custom data items for the Type info.
5740 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5741 ITypeInfo2 * iface,
5742 CUSTDATA *pCustData)
5744 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5745 TLBCustData *pCData;
5746 int i;
5748 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5750 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5751 if(pCustData->prgCustData ){
5752 pCustData->cCustData=This->ctCustData;
5753 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5754 pCustData->prgCustData[i].guid=pCData->guid;
5755 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5757 }else{
5758 ERR(" OUT OF MEMORY! \n");
5759 return E_OUTOFMEMORY;
5761 return S_OK;
5764 /* ITypeInfo2::GetAllFuncCustData
5766 * Gets all custom data items for the specified Function
5769 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5770 ITypeInfo2 * iface,
5771 UINT index,
5772 CUSTDATA *pCustData)
5774 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5775 TLBCustData *pCData;
5776 TLBFuncDesc * pFDesc;
5777 int i;
5778 TRACE("(%p) index %d\n", This, index);
5779 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5780 pFDesc=pFDesc->next)
5782 if(pFDesc){
5783 pCustData->prgCustData =
5784 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5785 if(pCustData->prgCustData ){
5786 pCustData->cCustData=pFDesc->ctCustData;
5787 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5788 pCData = pCData->next){
5789 pCustData->prgCustData[i].guid=pCData->guid;
5790 VariantCopy(& pCustData->prgCustData[i].varValue,
5791 & pCData->data);
5793 }else{
5794 ERR(" OUT OF MEMORY! \n");
5795 return E_OUTOFMEMORY;
5797 return S_OK;
5799 return TYPE_E_ELEMENTNOTFOUND;
5802 /* ITypeInfo2::GetAllParamCustData
5804 * Gets all custom data items for the Functions
5807 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5808 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5810 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5811 TLBCustData *pCData=NULL;
5812 TLBFuncDesc * pFDesc;
5813 int i;
5814 TRACE("(%p) index %d\n", This, indexFunc);
5815 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5816 pFDesc=pFDesc->next)
5818 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5819 pCustData->prgCustData =
5820 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5821 sizeof(CUSTDATAITEM));
5822 if(pCustData->prgCustData ){
5823 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5824 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5825 pCData; i++, pCData = pCData->next){
5826 pCustData->prgCustData[i].guid=pCData->guid;
5827 VariantCopy(& pCustData->prgCustData[i].varValue,
5828 & pCData->data);
5830 }else{
5831 ERR(" OUT OF MEMORY! \n");
5832 return E_OUTOFMEMORY;
5834 return S_OK;
5836 return TYPE_E_ELEMENTNOTFOUND;
5839 /* ITypeInfo2::GetAllVarCustData
5841 * Gets all custom data items for the specified Variable
5844 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5845 UINT index, CUSTDATA *pCustData)
5847 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5848 TLBCustData *pCData;
5849 TLBVarDesc * pVDesc;
5850 int i;
5851 TRACE("(%p) index %d\n", This, index);
5852 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5853 pVDesc=pVDesc->next)
5855 if(pVDesc){
5856 pCustData->prgCustData =
5857 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5858 if(pCustData->prgCustData ){
5859 pCustData->cCustData=pVDesc->ctCustData;
5860 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5861 pCData = pCData->next){
5862 pCustData->prgCustData[i].guid=pCData->guid;
5863 VariantCopy(& pCustData->prgCustData[i].varValue,
5864 & pCData->data);
5866 }else{
5867 ERR(" OUT OF MEMORY! \n");
5868 return E_OUTOFMEMORY;
5870 return S_OK;
5872 return TYPE_E_ELEMENTNOTFOUND;
5875 /* ITypeInfo2::GetAllImplCustData
5877 * Gets all custom data items for the specified implementation type
5880 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5881 ITypeInfo2 * iface,
5882 UINT index,
5883 CUSTDATA *pCustData)
5885 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5886 TLBCustData *pCData;
5887 TLBImplType * pRDesc;
5888 int i;
5889 TRACE("(%p) index %d\n", This, index);
5890 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5891 pRDesc=pRDesc->next)
5893 if(pRDesc){
5894 pCustData->prgCustData =
5895 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5896 if(pCustData->prgCustData ){
5897 pCustData->cCustData=pRDesc->ctCustData;
5898 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5899 pCData = pCData->next){
5900 pCustData->prgCustData[i].guid=pCData->guid;
5901 VariantCopy(& pCustData->prgCustData[i].varValue,
5902 & pCData->data);
5904 }else{
5905 ERR(" OUT OF MEMORY! \n");
5906 return E_OUTOFMEMORY;
5908 return S_OK;
5910 return TYPE_E_ELEMENTNOTFOUND;
5913 static const ITypeInfo2Vtbl tinfvt =
5916 ITypeInfo_fnQueryInterface,
5917 ITypeInfo_fnAddRef,
5918 ITypeInfo_fnRelease,
5920 ITypeInfo_fnGetTypeAttr,
5921 ITypeInfo_fnGetTypeComp,
5922 ITypeInfo_fnGetFuncDesc,
5923 ITypeInfo_fnGetVarDesc,
5924 ITypeInfo_fnGetNames,
5925 ITypeInfo_fnGetRefTypeOfImplType,
5926 ITypeInfo_fnGetImplTypeFlags,
5927 ITypeInfo_fnGetIDsOfNames,
5928 ITypeInfo_fnInvoke,
5929 ITypeInfo_fnGetDocumentation,
5930 ITypeInfo_fnGetDllEntry,
5931 ITypeInfo_fnGetRefTypeInfo,
5932 ITypeInfo_fnAddressOfMember,
5933 ITypeInfo_fnCreateInstance,
5934 ITypeInfo_fnGetMops,
5935 ITypeInfo_fnGetContainingTypeLib,
5936 ITypeInfo_fnReleaseTypeAttr,
5937 ITypeInfo_fnReleaseFuncDesc,
5938 ITypeInfo_fnReleaseVarDesc,
5940 ITypeInfo2_fnGetTypeKind,
5941 ITypeInfo2_fnGetTypeFlags,
5942 ITypeInfo2_fnGetFuncIndexOfMemId,
5943 ITypeInfo2_fnGetVarIndexOfMemId,
5944 ITypeInfo2_fnGetCustData,
5945 ITypeInfo2_fnGetFuncCustData,
5946 ITypeInfo2_fnGetParamCustData,
5947 ITypeInfo2_fnGetVarCustData,
5948 ITypeInfo2_fnGetImplTypeCustData,
5949 ITypeInfo2_fnGetDocumentation2,
5950 ITypeInfo2_fnGetAllCustData,
5951 ITypeInfo2_fnGetAllFuncCustData,
5952 ITypeInfo2_fnGetAllParamCustData,
5953 ITypeInfo2_fnGetAllVarCustData,
5954 ITypeInfo2_fnGetAllImplTypeCustData,
5957 /******************************************************************************
5958 * CreateDispTypeInfo [OLEAUT32.31]
5960 * Build type information for an object so it can be called through an
5961 * IDispatch interface.
5963 * RETURNS
5964 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5965 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5967 * NOTES
5968 * This call allows an objects methods to be accessed through IDispatch, by
5969 * building an ITypeInfo object that IDispatch can use to call through.
5971 HRESULT WINAPI CreateDispTypeInfo(
5972 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5973 LCID lcid, /* [I] Locale Id */
5974 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5976 ITypeInfoImpl *pTIImpl;
5977 int param, func;
5978 TLBFuncDesc **ppFuncDesc;
5980 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5981 pTIImpl->pTypeLib = NULL;
5982 pTIImpl->index = 0;
5983 pTIImpl->Name = NULL;
5984 pTIImpl->dwHelpContext = -1;
5985 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
5986 pTIImpl->TypeAttr.lcid = lcid;
5987 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
5988 pTIImpl->TypeAttr.wMajorVerNum = 0;
5989 pTIImpl->TypeAttr.wMinorVerNum = 0;
5990 pTIImpl->TypeAttr.cbAlignment = 2;
5991 pTIImpl->TypeAttr.cbSizeInstance = -1;
5992 pTIImpl->TypeAttr.cbSizeVft = -1;
5993 pTIImpl->TypeAttr.cFuncs = 0;
5994 pTIImpl->TypeAttr.cImplTypes = 1;
5995 pTIImpl->TypeAttr.cVars = 0;
5996 pTIImpl->TypeAttr.wTypeFlags = 0;
5998 ppFuncDesc = &pTIImpl->funclist;
5999 for(func = 0; func < pidata->cMembers; func++) {
6000 METHODDATA *md = pidata->pmethdata + func;
6001 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6002 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6003 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6004 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6005 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6006 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6007 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6008 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
6009 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
6010 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6011 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6012 md->cArgs * sizeof(ELEMDESC));
6013 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6014 md->cArgs * sizeof(TLBParDesc));
6015 for(param = 0; param < md->cArgs; param++) {
6016 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6017 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6019 ppFuncDesc = &(*ppFuncDesc)->next;
6021 *pptinfo = (ITypeInfo*)pTIImpl;
6022 return S_OK;
6026 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6028 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6030 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6033 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6035 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6037 return ITypeInfo_AddRef((ITypeInfo *)This);
6040 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6042 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6044 return ITypeInfo_Release((ITypeInfo *)This);
6047 static HRESULT WINAPI ITypeComp_fnBind(
6048 ITypeComp * iface,
6049 OLECHAR * szName,
6050 ULONG lHash,
6051 WORD wFlags,
6052 ITypeInfo ** ppTInfo,
6053 DESCKIND * pDescKind,
6054 BINDPTR * pBindPtr)
6056 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6057 TLBFuncDesc * pFDesc;
6058 TLBVarDesc * pVDesc;
6060 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6062 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6063 if (pFDesc->funcdesc.invkind & wFlags)
6064 if (!strcmpW(pFDesc->Name, szName)) {
6065 break;
6068 if (pFDesc)
6070 *pDescKind = DESCKIND_FUNCDESC;
6071 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
6072 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6073 return S_OK;
6074 } else {
6075 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
6077 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6078 if (!strcmpW(pVDesc->Name, szName)) {
6079 *pDescKind = DESCKIND_VARDESC;
6080 pBindPtr->lpvardesc = &pVDesc->vardesc;
6081 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6082 return S_OK;
6087 /* not found, look for it in inherited interfaces */
6088 if (This->TypeAttr.cImplTypes &&
6089 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
6090 /* recursive search */
6091 ITypeInfo *pTInfo;
6092 ITypeComp *pTComp;
6093 HRESULT hr;
6094 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6095 if (SUCCEEDED(hr))
6097 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6098 ITypeInfo_Release(pTInfo);
6100 if (SUCCEEDED(hr))
6102 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6103 ITypeComp_Release(pTComp);
6104 return hr;
6106 WARN("Could not search inherited interface!\n");
6108 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6109 *pDescKind = DESCKIND_NONE;
6110 pBindPtr->lpfuncdesc = NULL;
6111 *ppTInfo = NULL;
6112 return DISP_E_MEMBERNOTFOUND;
6115 static HRESULT WINAPI ITypeComp_fnBindType(
6116 ITypeComp * iface,
6117 OLECHAR * szName,
6118 ULONG lHash,
6119 ITypeInfo ** ppTInfo,
6120 ITypeComp ** ppTComp)
6122 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6124 /* strange behaviour (does nothing) but like the
6125 * original */
6127 if (!ppTInfo || !ppTComp)
6128 return E_POINTER;
6130 *ppTInfo = NULL;
6131 *ppTComp = NULL;
6133 return S_OK;
6136 static const ITypeCompVtbl tcompvt =
6139 ITypeComp_fnQueryInterface,
6140 ITypeComp_fnAddRef,
6141 ITypeComp_fnRelease,
6143 ITypeComp_fnBind,
6144 ITypeComp_fnBindType