Make CryptImport/ExportPublicKeyInfoEx behave the way MSDN describes
[wine/gsoc-2012-control.git] / dlls / oleaut32 / typelib.c
blobd470de735fd8f4ee76b9ebe08da6db14a8875501
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 unsigned long dwHelpContext;
983 unsigned long dwHelpStringContext;
985 /* functions */
986 TLBFuncDesc * funclist; /* linked list with function descriptions */
988 /* variables */
989 TLBVarDesc * varlist; /* linked list with variable descriptions */
991 /* Implemented Interfaces */
992 TLBImplType * impltypelist;
994 TLBRefType * reflist;
995 int ctCustData;
996 TLBCustData * pCustData; /* linked list to cust data; */
997 struct tagITypeInfoImpl * next;
998 } ITypeInfoImpl;
1000 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1002 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1005 static const ITypeInfo2Vtbl tinfvt;
1006 static const ITypeCompVtbl tcompvt;
1008 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1010 typedef struct tagTLBContext
1012 unsigned int oStart; /* start of TLB in file */
1013 unsigned int pos; /* current pos */
1014 unsigned int length; /* total length */
1015 void *mapping; /* memory mapping */
1016 MSFT_SegDir * pTblDir;
1017 ITypeLibImpl* pLibInfo;
1018 } TLBContext;
1021 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1024 debug
1026 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1027 if (pTD->vt & VT_RESERVED)
1028 szVarType += strlen(strcpy(szVarType, "reserved | "));
1029 if (pTD->vt & VT_BYREF)
1030 szVarType += strlen(strcpy(szVarType, "ref to "));
1031 if (pTD->vt & VT_ARRAY)
1032 szVarType += strlen(strcpy(szVarType, "array of "));
1033 if (pTD->vt & VT_VECTOR)
1034 szVarType += strlen(strcpy(szVarType, "vector of "));
1035 switch(pTD->vt & VT_TYPEMASK) {
1036 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1037 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1038 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1039 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1040 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1041 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1042 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1043 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1044 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1045 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1046 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1047 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1048 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1049 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1050 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1051 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1052 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1053 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1054 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1055 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1056 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1057 pTD->u.hreftype); break;
1058 case VT_PTR: sprintf(szVarType, "ptr to ");
1059 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1060 break;
1061 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1062 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1063 break;
1064 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1065 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1066 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1067 break;
1069 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1073 static void dump_ELEMDESC(ELEMDESC *edesc) {
1074 char buf[200];
1075 dump_TypeDesc(&edesc->tdesc,buf);
1076 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1077 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
1078 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1080 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
1081 int i;
1082 MESSAGE("memid is %08lx\n",funcdesc->memid);
1083 for (i=0;i<funcdesc->cParams;i++) {
1084 MESSAGE("Param %d:\n",i);
1085 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1087 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1088 switch (funcdesc->funckind) {
1089 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1090 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1091 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1092 case FUNC_STATIC: MESSAGE("static");break;
1093 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1094 default: MESSAGE("unknown");break;
1096 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1097 switch (funcdesc->invkind) {
1098 case INVOKE_FUNC: MESSAGE("func");break;
1099 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1100 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1101 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1103 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1104 switch (funcdesc->callconv) {
1105 case CC_CDECL: MESSAGE("cdecl");break;
1106 case CC_PASCAL: MESSAGE("pascal");break;
1107 case CC_STDCALL: MESSAGE("stdcall");break;
1108 case CC_SYSCALL: MESSAGE("syscall");break;
1109 default:break;
1111 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1112 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1113 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1115 MESSAGE("\telemdescFunc (return value type):\n");
1116 dump_ELEMDESC(&funcdesc->elemdescFunc);
1119 static const char * typekind_desc[] =
1121 "TKIND_ENUM",
1122 "TKIND_RECORD",
1123 "TKIND_MODULE",
1124 "TKIND_INTERFACE",
1125 "TKIND_DISPATCH",
1126 "TKIND_COCLASS",
1127 "TKIND_ALIAS",
1128 "TKIND_UNION",
1129 "TKIND_MAX"
1132 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1134 int i;
1135 if (!TRACE_ON(typelib))
1136 return;
1137 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1138 for (i=0;i<pfd->funcdesc.cParams;i++)
1139 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1142 dump_FUNCDESC(&(pfd->funcdesc));
1144 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1145 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1147 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1149 while (pfd)
1151 dump_TLBFuncDescOne(pfd);
1152 pfd = pfd->next;
1155 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1157 while (pvd)
1159 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1160 pvd = pvd->next;
1164 static void dump_TLBImpLib(TLBImpLib *import)
1166 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1167 debugstr_w(import->name));
1168 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1169 import->wVersionMinor, import->lcid, import->offset);
1172 static void dump_TLBRefType(TLBRefType * prt)
1174 while (prt)
1176 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1177 if(prt->index == -1)
1178 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1179 else
1180 TRACE_(typelib)("type no: %d\n", prt->index);
1182 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1183 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1184 TRACE_(typelib)("in lib\n");
1185 dump_TLBImpLib(prt->pImpTLInfo);
1187 prt = prt->next;
1191 static void dump_TLBImplType(TLBImplType * impl)
1193 while (impl) {
1194 TRACE_(typelib)(
1195 "implementing/inheriting interface hRef = %lx implflags %x\n",
1196 impl->hRef, impl->implflags);
1197 impl = impl->next;
1201 void dump_Variant(VARIANT * pvar)
1203 SYSTEMTIME st;
1205 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1207 if (pvar)
1209 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1210 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1212 TRACE(",%p", V_BYREF(pvar));
1214 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1216 TRACE(",FIXME");
1218 else switch (V_TYPE(pvar))
1220 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1221 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1222 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1223 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1224 case VT_INT:
1225 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1226 case VT_UINT:
1227 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1228 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1229 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1230 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1231 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1232 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1233 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1234 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1235 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1236 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1237 V_CY(pvar).s.Lo); break;
1238 case VT_DATE:
1239 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1240 TRACE(",<invalid>");
1241 else
1242 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1243 st.wHour, st.wMinute, st.wSecond);
1244 break;
1245 case VT_ERROR:
1246 case VT_VOID:
1247 case VT_USERDEFINED:
1248 case VT_EMPTY:
1249 case VT_NULL: break;
1250 default: TRACE(",?"); break;
1253 TRACE("}\n");
1256 static void dump_DispParms(DISPPARAMS * pdp)
1258 int index = 0;
1260 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1262 while (index < pdp->cArgs)
1264 dump_Variant( &pdp->rgvarg[index] );
1265 ++index;
1269 static void dump_TypeInfo(ITypeInfoImpl * pty)
1271 TRACE("%p ref=%lu\n", pty, pty->ref);
1272 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1273 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1274 TRACE("fct:%u var:%u impl:%u\n",
1275 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1276 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1277 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1278 dump_TLBFuncDesc(pty->funclist);
1279 dump_TLBVarDesc(pty->varlist);
1280 dump_TLBImplType(pty->impltypelist);
1283 static void dump_VARDESC(VARDESC *v)
1285 MESSAGE("memid %ld\n",v->memid);
1286 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1287 MESSAGE("oInst %ld\n",v->u.oInst);
1288 dump_ELEMDESC(&(v->elemdescVar));
1289 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1290 MESSAGE("varkind %d\n",v->varkind);
1293 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1295 /* VT_LPWSTR is largest type that */
1296 /* may appear in type description*/
1297 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1298 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1299 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1300 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1301 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1302 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1303 {{0},30},{{0},31}
1306 static void TLB_abort(void)
1308 DebugBreak();
1310 static void * TLB_Alloc(unsigned size)
1312 void * ret;
1313 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1314 /* FIXME */
1315 ERR("cannot allocate memory\n");
1317 return ret;
1320 static void TLB_Free(void * ptr)
1322 HeapFree(GetProcessHeap(), 0, ptr);
1325 /* deep copy a typedesc */
1326 static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in)
1328 out->vt = in->vt;
1329 switch(in->vt) {
1330 case VT_PTR:
1331 out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC));
1332 copy_typedesc(out->u.lptdesc, in->u.lptdesc);
1333 break;
1334 case VT_USERDEFINED:
1335 out->u.hreftype = in->u.hreftype;
1336 break;
1337 case VT_CARRAY:
1338 out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) +
1339 (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND));
1340 copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem);
1341 out->u.lpadesc->cDims = in->u.lpadesc->cDims;
1342 memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND));
1343 break;
1344 default:
1345 break;
1349 /* free()s any allocated memory pointed to by the tdesc. NB does not
1350 free the tdesc itself - this is because the tdesc is typically part
1351 of a larger structure */
1352 static void free_deep_typedesc(TYPEDESC *tdesc)
1354 switch(tdesc->vt) {
1355 case VT_PTR:
1356 free_deep_typedesc(tdesc->u.lptdesc);
1357 HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc);
1358 tdesc->u.lptdesc = NULL;
1359 break;
1360 case VT_CARRAY:
1361 free_deep_typedesc(&tdesc->u.lpadesc->tdescElem);
1362 HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc);
1363 tdesc->u.lpadesc = NULL;
1364 break;
1365 default:
1366 break;
1370 /**********************************************************************
1372 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1374 /* read function */
1375 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1377 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1378 pcx->pos, count, pcx->oStart, pcx->length, where);
1380 if (where != DO_NOT_SEEK)
1382 where += pcx->oStart;
1383 if (where > pcx->length)
1385 /* FIXME */
1386 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1387 TLB_abort();
1389 pcx->pos = where;
1391 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1392 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1393 pcx->pos += count;
1394 return count;
1397 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1398 long where )
1400 DWORD ret;
1402 ret = MSFT_Read(buffer, count, pcx, where);
1403 FromLEDWords(buffer, ret);
1405 return ret;
1408 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1409 long where )
1411 DWORD ret;
1413 ret = MSFT_Read(buffer, count, pcx, where);
1414 FromLEWords(buffer, ret);
1416 return ret;
1419 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1421 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1422 memset(pGuid,0, sizeof(GUID));
1423 return;
1425 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1426 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1427 pGuid->Data2 = FromLEWord(pGuid->Data2);
1428 pGuid->Data3 = FromLEWord(pGuid->Data3);
1429 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1432 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1434 char * name;
1435 MSFT_NameIntro niName;
1436 int lengthInChars;
1437 WCHAR* pwstring = NULL;
1438 BSTR bstrName = NULL;
1440 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1441 pcx->pTblDir->pNametab.offset+offset);
1442 niName.namelen &= 0xFF; /* FIXME: correct ? */
1443 name=TLB_Alloc((niName.namelen & 0xff) +1);
1444 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1445 name[niName.namelen & 0xff]='\0';
1447 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1448 name, -1, NULL, 0);
1450 /* no invalid characters in string */
1451 if (lengthInChars)
1453 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1455 /* don't check for invalid character since this has been done previously */
1456 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1458 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1459 lengthInChars = SysStringLen(bstrName);
1460 HeapFree(GetProcessHeap(), 0, pwstring);
1463 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1464 return bstrName;
1467 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1469 char * string;
1470 INT16 length;
1471 int lengthInChars;
1472 BSTR bstr = NULL;
1474 if(offset<0) return NULL;
1475 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1476 if(length <= 0) return 0;
1477 string=TLB_Alloc(length +1);
1478 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1479 string[length]='\0';
1481 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1482 string, -1, NULL, 0);
1484 /* no invalid characters in string */
1485 if (lengthInChars)
1487 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1489 /* don't check for invalid character since this has been done previously */
1490 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1492 bstr = SysAllocStringLen(pwstring, lengthInChars);
1493 lengthInChars = SysStringLen(bstr);
1494 HeapFree(GetProcessHeap(), 0, pwstring);
1497 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1498 return bstr;
1501 * read a value and fill a VARIANT structure
1503 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1505 int size;
1507 TRACE_(typelib)("\n");
1509 if(offset <0) { /* data are packed in here */
1510 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1511 V_I2(pVar) = offset & 0x3ffffff;
1512 return;
1514 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1515 pcx->pTblDir->pCustData.offset + offset );
1516 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1517 switch (V_VT(pVar)){
1518 case VT_EMPTY: /* FIXME: is this right? */
1519 case VT_NULL: /* FIXME: is this right? */
1520 case VT_I2 : /* this should not happen */
1521 case VT_I4 :
1522 case VT_R4 :
1523 case VT_ERROR :
1524 case VT_BOOL :
1525 case VT_I1 :
1526 case VT_UI1 :
1527 case VT_UI2 :
1528 case VT_UI4 :
1529 case VT_INT :
1530 case VT_UINT :
1531 case VT_VOID : /* FIXME: is this right? */
1532 case VT_HRESULT :
1533 size=4; break;
1534 case VT_R8 :
1535 case VT_CY :
1536 case VT_DATE :
1537 case VT_I8 :
1538 case VT_UI8 :
1539 case VT_DECIMAL : /* FIXME: is this right? */
1540 case VT_FILETIME :
1541 size=8;break;
1542 /* pointer types with known behaviour */
1543 case VT_BSTR :{
1544 char * ptr;
1545 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1546 if(size < 0) {
1547 FIXME("BSTR length = %d?\n", size);
1548 } else {
1549 ptr=TLB_Alloc(size);/* allocate temp buffer */
1550 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1551 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1552 /* FIXME: do we need a AtoW conversion here? */
1553 V_UNION(pVar, bstrVal[size])=L'\0';
1554 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1555 TLB_Free(ptr);
1558 size=-4; break;
1559 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1560 case VT_DISPATCH :
1561 case VT_VARIANT :
1562 case VT_UNKNOWN :
1563 case VT_PTR :
1564 case VT_SAFEARRAY :
1565 case VT_CARRAY :
1566 case VT_USERDEFINED :
1567 case VT_LPSTR :
1568 case VT_LPWSTR :
1569 case VT_BLOB :
1570 case VT_STREAM :
1571 case VT_STORAGE :
1572 case VT_STREAMED_OBJECT :
1573 case VT_STORED_OBJECT :
1574 case VT_BLOB_OBJECT :
1575 case VT_CF :
1576 case VT_CLSID :
1577 default:
1578 size=0;
1579 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1580 V_VT(pVar));
1583 if(size>0) /* (big|small) endian correct? */
1584 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1585 return;
1588 * create a linked list with custom data
1590 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1592 MSFT_CDGuid entry;
1593 TLBCustData* pNew;
1594 int count=0;
1596 TRACE_(typelib)("\n");
1598 while(offset >=0){
1599 count++;
1600 pNew=TLB_Alloc(sizeof(TLBCustData));
1601 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1602 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1603 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1604 /* add new custom data at head of the list */
1605 pNew->next=*ppCustData;
1606 *ppCustData=pNew;
1607 offset = entry.next;
1609 return count;
1612 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1613 ITypeInfoImpl *pTI)
1615 if(type <0)
1616 pTd->vt=type & VT_TYPEMASK;
1617 else
1618 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1620 if(pTd->vt == VT_USERDEFINED)
1621 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1623 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1626 static void
1627 MSFT_DoFuncs(TLBContext* pcx,
1628 ITypeInfoImpl* pTI,
1629 int cFuncs,
1630 int cVars,
1631 int offset,
1632 TLBFuncDesc** pptfd)
1635 * member information is stored in a data structure at offset
1636 * indicated by the memoffset field of the typeinfo structure
1637 * There are several distinctive parts.
1638 * The first part starts with a field that holds the total length
1639 * of this (first) part excluding this field. Then follow the records,
1640 * for each member there is one record.
1642 * The first entry is always the length of the record (including this
1643 * length word).
1644 * The rest of the record depends on the type of the member. If there is
1645 * a field indicating the member type (function, variable, interface, etc)
1646 * I have not found it yet. At this time we depend on the information
1647 * in the type info and the usual order how things are stored.
1649 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1650 * for each member;
1652 * Third is an equal sized array with file offsets to the name entry
1653 * of each member.
1655 * The fourth and last (?) part is an array with offsets to the records
1656 * in the first part of this file segment.
1659 int infolen, nameoffset, reclength, nrattributes, i;
1660 int recoffset = offset + sizeof(INT);
1662 char recbuf[512];
1663 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1665 TRACE_(typelib)("\n");
1667 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1669 for ( i = 0; i < cFuncs ; i++ )
1671 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1673 /* name, eventually add to a hash table */
1674 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1675 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1677 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1679 /* read the function information record */
1680 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1682 reclength &= 0x1ff;
1684 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1686 /* do the attributes */
1687 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1688 / sizeof(int);
1690 if ( nrattributes > 0 )
1692 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1694 if ( nrattributes > 1 )
1696 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1697 pFuncRec->OptAttr[1]) ;
1699 if ( nrattributes > 2 )
1701 if ( pFuncRec->FKCCIC & 0x2000 )
1703 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1705 else
1707 (*pptfd)->Entry = MSFT_ReadString(pcx,
1708 pFuncRec->OptAttr[2]);
1710 if( nrattributes > 5 )
1712 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1714 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1716 MSFT_CustData(pcx,
1717 pFuncRec->OptAttr[6],
1718 &(*pptfd)->pCustData);
1725 /* fill the FuncDesc Structure */
1726 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1727 offset + infolen + ( i + 1) * sizeof(INT));
1729 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1730 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1731 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1732 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1733 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1734 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1735 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1737 MSFT_GetTdesc(pcx,
1738 pFuncRec->DataType,
1739 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1740 pTI);
1742 /* do the parameters/arguments */
1743 if(pFuncRec->nrargs)
1745 int j = 0;
1746 MSFT_ParameterInfo paraminfo;
1748 (*pptfd)->funcdesc.lprgelemdescParam =
1749 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1751 (*pptfd)->pParamDesc =
1752 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1754 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1755 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1757 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1759 TYPEDESC* lpArgTypeDesc = 0;
1761 MSFT_GetTdesc(pcx,
1762 paraminfo.DataType,
1763 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1764 pTI);
1766 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1768 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1770 /* SEEK value = jump to offset,
1771 * from there jump to the end of record,
1772 * go back by (j-1) arguments
1774 MSFT_ReadLEDWords( &paraminfo ,
1775 sizeof(MSFT_ParameterInfo), pcx,
1776 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1777 * sizeof(MSFT_ParameterInfo)));
1778 lpArgTypeDesc =
1779 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1781 while ( lpArgTypeDesc != NULL )
1783 switch ( lpArgTypeDesc->vt )
1785 case VT_PTR:
1786 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1787 break;
1789 case VT_CARRAY:
1790 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1791 break;
1793 case VT_USERDEFINED:
1794 MSFT_DoRefType(pcx, pTI,
1795 lpArgTypeDesc->u.hreftype);
1797 lpArgTypeDesc = NULL;
1798 break;
1800 default:
1801 lpArgTypeDesc = NULL;
1807 /* parameter is the return value! */
1808 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1810 TYPEDESC* lpArgTypeDesc;
1812 (*pptfd)->funcdesc.elemdescFunc =
1813 (*pptfd)->funcdesc.lprgelemdescParam[j];
1815 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1817 while ( lpArgTypeDesc != NULL )
1819 switch ( lpArgTypeDesc->vt )
1821 case VT_PTR:
1822 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1823 break;
1824 case VT_CARRAY:
1825 lpArgTypeDesc =
1826 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1828 break;
1830 case VT_USERDEFINED:
1831 MSFT_DoRefType(pcx,
1832 pTI,
1833 lpArgTypeDesc->u.hreftype);
1835 lpArgTypeDesc = NULL;
1836 break;
1838 default:
1839 lpArgTypeDesc = NULL;
1844 /* second time around */
1845 for(j=0;j<pFuncRec->nrargs;j++)
1847 /* name */
1848 (*pptfd)->pParamDesc[j].Name =
1849 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1851 /* default value */
1852 if ( (PARAMFLAG_FHASDEFAULT &
1853 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1854 ((pFuncRec->FKCCIC) & 0x1000) )
1856 INT* pInt = (INT *)((char *)pFuncRec +
1857 reclength -
1858 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1860 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1862 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1863 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1865 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1866 pInt[j], pcx);
1868 /* custom info */
1869 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1871 MSFT_CustData(pcx,
1872 pFuncRec->OptAttr[7+j],
1873 &(*pptfd)->pParamDesc[j].pCustData);
1878 /* scode is not used: archaic win16 stuff FIXME: right? */
1879 (*pptfd)->funcdesc.cScodes = 0 ;
1880 (*pptfd)->funcdesc.lprgscode = NULL ;
1882 pptfd = & ((*pptfd)->next);
1883 recoffset += reclength;
1887 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1888 int cVars, int offset, TLBVarDesc ** pptvd)
1890 int infolen, nameoffset, reclength;
1891 char recbuf[256];
1892 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1893 int i;
1894 int recoffset;
1896 TRACE_(typelib)("\n");
1898 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1899 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1900 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1901 recoffset += offset+sizeof(INT);
1902 for(i=0;i<cVars;i++){
1903 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1904 /* name, eventually add to a hash table */
1905 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1906 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1907 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1908 /* read the variable information record */
1909 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1910 reclength &=0xff;
1911 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1912 /* Optional data */
1913 if(reclength >(6*sizeof(INT)) )
1914 (*pptvd)->HelpContext=pVarRec->HelpContext;
1915 if(reclength >(7*sizeof(INT)) )
1916 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1917 if(reclength >(8*sizeof(INT)) )
1918 if(reclength >(9*sizeof(INT)) )
1919 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1920 /* fill the VarDesc Structure */
1921 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1922 offset + infolen + ( i + 1) * sizeof(INT));
1923 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1924 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1925 MSFT_GetTdesc(pcx, pVarRec->DataType,
1926 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1927 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1928 if(pVarRec->VarKind == VAR_CONST ){
1929 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1930 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1931 pVarRec->OffsValue, pcx);
1932 } else
1933 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1934 pptvd=&((*pptvd)->next);
1935 recoffset += reclength;
1938 /* fill in data for a hreftype (offset). When the referenced type is contained
1939 * in the typelib, it's just an (file) offset in the type info base dir.
1940 * If comes from import, it's an offset+1 in the ImpInfo table
1941 * */
1942 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1943 int offset)
1945 int j;
1946 TLBRefType **ppRefType = &pTI->reflist;
1948 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1950 while(*ppRefType) {
1951 if((*ppRefType)->reference == offset)
1952 return;
1953 ppRefType = &(*ppRefType)->next;
1956 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1957 sizeof(**ppRefType));
1959 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1960 /* external typelib */
1961 MSFT_ImpInfo impinfo;
1962 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1964 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1966 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1967 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1968 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1969 if(pImpLib->offset==impinfo.oImpFile) break;
1970 pImpLib=pImpLib->next;
1972 if(pImpLib){
1973 (*ppRefType)->reference=offset;
1974 (*ppRefType)->pImpTLInfo = pImpLib;
1975 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1976 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1977 (*ppRefType)->index = TLB_REF_USE_GUID;
1978 } else
1979 (*ppRefType)->index = impinfo.oGuid;
1980 }else{
1981 ERR("Cannot find a reference\n");
1982 (*ppRefType)->reference=-1;
1983 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1985 }else{
1986 /* in this typelib */
1987 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1988 (*ppRefType)->reference=offset;
1989 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1993 /* process Implemented Interfaces of a com class */
1994 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1995 int offset)
1997 int i;
1998 MSFT_RefRecord refrec;
1999 TLBImplType **ppImpl = &pTI->impltypelist;
2001 TRACE_(typelib)("\n");
2003 for(i=0;i<count;i++){
2004 if(offset<0) break; /* paranoia */
2005 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2006 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2007 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2008 (*ppImpl)->hRef = refrec.reftype;
2009 (*ppImpl)->implflags=refrec.flags;
2010 (*ppImpl)->ctCustData=
2011 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2012 offset=refrec.onext;
2013 ppImpl=&((*ppImpl)->next);
2017 * process a typeinfo record
2019 static ITypeInfoImpl * MSFT_DoTypeInfo(
2020 TLBContext *pcx,
2021 int count,
2022 ITypeLibImpl * pLibInfo)
2024 MSFT_TypeInfoBase tiBase;
2025 ITypeInfoImpl *ptiRet;
2027 TRACE_(typelib)("count=%u\n", count);
2029 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2030 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2031 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2032 /* this is where we are coming from */
2033 ptiRet->pTypeLib = pLibInfo;
2034 ptiRet->index=count;
2035 /* fill in the typeattr fields */
2036 WARN("Assign constructor/destructor memid\n");
2038 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2039 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2040 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2041 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2042 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2043 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2044 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2045 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2046 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2047 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2048 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2049 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2050 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2051 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2052 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2053 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2054 MSFT_GetTdesc(pcx, tiBase.datatype1,
2055 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2057 /* FIXME: */
2058 /* IDLDESC idldescType; *//* never saw this one != zero */
2060 /* name, eventually add to a hash table */
2061 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2062 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2063 /* help info */
2064 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2065 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2066 ptiRet->dwHelpContext=tiBase.helpcontext;
2067 /* note: InfoType's Help file and HelpStringDll come from the containing
2068 * library. Further HelpString and Docstring appear to be the same thing :(
2070 /* functions */
2071 if(ptiRet->TypeAttr.cFuncs >0 )
2072 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2073 ptiRet->TypeAttr.cVars,
2074 tiBase.memoffset, & ptiRet->funclist);
2075 /* variables */
2076 if(ptiRet->TypeAttr.cVars >0 )
2077 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2078 ptiRet->TypeAttr.cVars,
2079 tiBase.memoffset, & ptiRet->varlist);
2080 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2081 switch(ptiRet->TypeAttr.typekind)
2083 case TKIND_COCLASS:
2084 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2085 tiBase.datatype1);
2086 break;
2087 case TKIND_DISPATCH:
2088 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2090 if (tiBase.datatype1 != -1)
2092 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2093 ptiRet->impltypelist->hRef = tiBase.datatype1;
2095 else
2096 { /* FIXME: This is a really bad hack to add IDispatch */
2097 const char* szStdOle = "stdole2.tlb\0";
2098 int nStdOleLen = strlen(szStdOle);
2099 TLBRefType **ppRef = &ptiRet->reflist;
2101 while(*ppRef) {
2102 if((*ppRef)->reference == -1)
2103 break;
2104 ppRef = &(*ppRef)->next;
2106 if(!*ppRef) {
2107 *ppRef = TLB_Alloc(sizeof(**ppRef));
2108 (*ppRef)->guid = IID_IDispatch;
2109 (*ppRef)->reference = -1;
2110 (*ppRef)->index = TLB_REF_USE_GUID;
2111 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2112 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2113 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2114 nStdOleLen + 1);
2116 MultiByteToWideChar(CP_ACP,
2117 MB_PRECOMPOSED,
2118 szStdOle,
2120 (*ppRef)->pImpTLInfo->name,
2121 SysStringLen((*ppRef)->pImpTLInfo->name));
2123 (*ppRef)->pImpTLInfo->lcid = 0;
2124 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2125 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2128 break;
2129 default:
2130 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2131 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2132 ptiRet->impltypelist->hRef = tiBase.datatype1;
2133 break;
2136 ptiRet->ctCustData=
2137 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2139 TRACE_(typelib)("%s guid: %s kind:%s\n",
2140 debugstr_w(ptiRet->Name),
2141 debugstr_guid(&ptiRet->TypeAttr.guid),
2142 typekind_desc[ptiRet->TypeAttr.typekind]);
2144 return ptiRet;
2147 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2148 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2149 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2150 * tradeoff here.
2152 static ITypeLibImpl *tlb_cache_first;
2153 static CRITICAL_SECTION cache_section;
2154 static CRITICAL_SECTION_DEBUG cache_section_debug =
2156 0, 0, &cache_section,
2157 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2158 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2160 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2163 /****************************************************************************
2164 * TLB_ReadTypeLib
2166 * find the type of the typelib file and map the typelib resource into
2167 * the memory
2169 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2170 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2171 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2173 ITypeLibImpl *entry;
2174 int ret = TYPE_E_CANTLOADLIBRARY;
2175 DWORD dwSignature = 0;
2176 HANDLE hFile;
2178 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2180 *ppTypeLib = NULL;
2182 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2183 EnterCriticalSection(&cache_section);
2184 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2186 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2188 TRACE("cache hit\n");
2189 *ppTypeLib = (ITypeLib2*)entry;
2190 ITypeLib_AddRef(*ppTypeLib);
2191 LeaveCriticalSection(&cache_section);
2192 return S_OK;
2195 LeaveCriticalSection(&cache_section);
2197 /* check the signature of the file */
2198 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2199 if (INVALID_HANDLE_VALUE != hFile)
2201 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2202 if (hMapping)
2204 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2205 if(pBase)
2207 /* retrieve file size */
2208 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2210 /* first try to load as *.tlb */
2211 dwSignature = FromLEDWord(*((DWORD*) pBase));
2212 if ( dwSignature == MSFT_SIGNATURE)
2214 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2216 else if ( dwSignature == SLTG_SIGNATURE)
2218 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2220 UnmapViewOfFile(pBase);
2222 CloseHandle(hMapping);
2224 CloseHandle(hFile);
2226 else
2228 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2231 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2232 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2234 /* find the typelibrary resource*/
2235 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2236 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2237 if (hinstDLL)
2239 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2240 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2241 if (hrsrc)
2243 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2244 if (hGlobal)
2246 LPVOID pBase = LockResource(hGlobal);
2247 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2249 if (pBase)
2251 /* try to load as incore resource */
2252 dwSignature = FromLEDWord(*((DWORD*) pBase));
2253 if ( dwSignature == MSFT_SIGNATURE)
2255 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2257 else if ( dwSignature == SLTG_SIGNATURE)
2259 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2261 else
2263 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2266 FreeResource( hGlobal );
2269 FreeLibrary(hinstDLL);
2273 if(*ppTypeLib) {
2274 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2276 TRACE("adding to cache\n");
2277 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2278 lstrcpyW(impl->path, pszFileName);
2279 /* We should really canonicalise the path here. */
2280 impl->index = index;
2282 /* FIXME: check if it has added already in the meantime */
2283 EnterCriticalSection(&cache_section);
2284 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2285 impl->prev = NULL;
2286 tlb_cache_first = impl;
2287 LeaveCriticalSection(&cache_section);
2288 ret = S_OK;
2289 } else
2290 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2292 return ret;
2295 /*================== ITypeLib(2) Methods ===================================*/
2297 /****************************************************************************
2298 * ITypeLib2_Constructor_MSFT
2300 * loading an MSFT typelib from an in-memory image
2302 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2304 TLBContext cx;
2305 long lPSegDir;
2306 MSFT_Header tlbHeader;
2307 MSFT_SegDir tlbSegDir;
2308 ITypeLibImpl * pTypeLibImpl;
2310 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2312 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2313 if (!pTypeLibImpl) return NULL;
2315 pTypeLibImpl->lpVtbl = &tlbvt;
2316 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2317 pTypeLibImpl->ref = 1;
2319 /* get pointer to beginning of typelib data */
2320 cx.pos = 0;
2321 cx.oStart=0;
2322 cx.mapping = pLib;
2323 cx.pLibInfo = pTypeLibImpl;
2324 cx.length = dwTLBLength;
2326 /* read header */
2327 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2328 TRACE("header:\n");
2329 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2330 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2331 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2332 return NULL;
2334 /* there is a small amount of information here until the next important
2335 * part:
2336 * the segment directory . Try to calculate the amount of data */
2337 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2339 /* now read the segment directory */
2340 TRACE("read segment directory (at %ld)\n",lPSegDir);
2341 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2342 cx.pTblDir = &tlbSegDir;
2344 /* just check two entries */
2345 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2347 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2348 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2349 return NULL;
2352 /* now fill our internal data */
2353 /* TLIBATTR fields */
2354 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2356 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2357 /* Windows seems to have zero here, is this correct? */
2358 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2359 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2360 else
2361 pTypeLibImpl->LibAttr.lcid = 0;
2363 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2364 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2365 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2366 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2368 /* name, eventually add to a hash table */
2369 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2371 /* help info */
2372 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2373 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2375 if( tlbHeader.varflags & HELPDLLFLAG)
2377 int offset;
2378 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2379 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2382 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2384 /* custom data */
2385 if(tlbHeader.CustomDataOffset >= 0)
2387 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2390 /* fill in typedescriptions */
2391 if(tlbSegDir.pTypdescTab.length > 0)
2393 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2394 INT16 td[4];
2395 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2396 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2397 for(i=0; i<cTD; )
2399 /* FIXME: add several sanity checks here */
2400 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2401 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2403 /* FIXME: check safearray */
2404 if(td[3] < 0)
2405 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2406 else
2407 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2409 else if(td[0] == VT_CARRAY)
2411 /* array descr table here */
2412 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2414 else if(td[0] == VT_USERDEFINED)
2416 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2418 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2421 /* second time around to fill the array subscript info */
2422 for(i=0;i<cTD;i++)
2424 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2425 if(tlbSegDir.pArrayDescriptions.offset>0)
2427 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2428 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2430 if(td[1]<0)
2431 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2432 else
2433 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2435 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2437 for(j = 0; j<td[2]; j++)
2439 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2440 sizeof(INT), &cx, DO_NOT_SEEK);
2441 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2442 sizeof(INT), &cx, DO_NOT_SEEK);
2445 else
2447 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2448 ERR("didn't find array description data\n");
2453 /* imported type libs */
2454 if(tlbSegDir.pImpFiles.offset>0)
2456 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2457 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2458 UINT16 size;
2460 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2462 char *name;
2463 DWORD len;
2465 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2466 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2467 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2469 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2470 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2471 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2472 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2474 size >>= 2;
2475 name = TLB_Alloc(size+1);
2476 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2477 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2478 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2479 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2480 TLB_Free(name);
2482 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2483 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2485 ppImpLib = &(*ppImpLib)->next;
2489 /* type info's */
2490 if(tlbHeader.nrtypeinfos >= 0 )
2492 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2493 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2494 int i;
2496 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2498 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2500 ppTI = &((*ppTI)->next);
2501 (pTypeLibImpl->TypeInfoCount)++;
2505 TRACE("(%p)\n", pTypeLibImpl);
2506 return (ITypeLib2*) pTypeLibImpl;
2510 static BSTR TLB_MultiByteToBSTR(char *ptr)
2512 DWORD len;
2513 WCHAR *nameW;
2514 BSTR ret;
2516 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2517 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2518 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2519 ret = SysAllocString(nameW);
2520 HeapFree(GetProcessHeap(), 0, nameW);
2521 return ret;
2524 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2526 char b[3];
2527 int i;
2528 short s;
2530 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2531 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2532 return FALSE;
2535 guid->Data4[0] = s >> 8;
2536 guid->Data4[1] = s & 0xff;
2538 b[2] = '\0';
2539 for(i = 0; i < 6; i++) {
2540 memcpy(b, str + 24 + 2 * i, 2);
2541 guid->Data4[i + 2] = strtol(b, NULL, 16);
2543 return TRUE;
2546 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2548 WORD bytelen;
2549 DWORD len;
2550 WCHAR *nameW;
2552 *pBstr = NULL;
2553 bytelen = *(WORD*)ptr;
2554 if(bytelen == 0xffff) return 2;
2555 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2556 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2557 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2558 *pBstr = SysAllocStringLen(nameW, len);
2559 HeapFree(GetProcessHeap(), 0, nameW);
2560 return bytelen + 2;
2563 static WORD SLTG_ReadStringA(char *ptr, char **str)
2565 WORD bytelen;
2567 *str = NULL;
2568 bytelen = *(WORD*)ptr;
2569 if(bytelen == 0xffff) return 2;
2570 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2571 memcpy(*str, ptr + 2, bytelen);
2572 (*str)[bytelen] = '\0';
2573 return bytelen + 2;
2576 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2578 char *ptr = pLibBlk;
2579 WORD w;
2581 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2582 FIXME("libblk magic = %04x\n", w);
2583 return 0;
2586 ptr += 6;
2587 if((w = *(WORD*)ptr) != 0xffff) {
2588 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2589 ptr += w;
2591 ptr += 2;
2593 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2595 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2597 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2598 ptr += 4;
2600 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2601 ptr += 2;
2603 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2604 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2605 else
2606 pTypeLibImpl->LibAttr.lcid = 0;
2607 ptr += 2;
2609 ptr += 4; /* skip res12 */
2611 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2612 ptr += 2;
2614 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2615 ptr += 2;
2617 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2618 ptr += 2;
2620 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2621 ptr += sizeof(GUID);
2623 return ptr - (char*)pLibBlk;
2626 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2628 BOOL done = FALSE;
2629 TYPEDESC *pTD = &pElem->tdesc;
2631 /* Handle [in/out] first */
2632 if((*pType & 0xc000) == 0xc000)
2633 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2634 else if(*pType & 0x8000)
2635 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2636 else if(*pType & 0x4000)
2637 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2638 else
2639 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2641 if(*pType & 0x2000)
2642 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2644 if(*pType & 0x80)
2645 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2647 while(!done) {
2648 if((*pType & 0xe00) == 0xe00) {
2649 pTD->vt = VT_PTR;
2650 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2651 sizeof(TYPEDESC));
2652 pTD = pTD->u.lptdesc;
2654 switch(*pType & 0x7f) {
2655 case VT_PTR:
2656 pTD->vt = VT_PTR;
2657 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2658 sizeof(TYPEDESC));
2659 pTD = pTD->u.lptdesc;
2660 break;
2662 case VT_USERDEFINED:
2663 pTD->vt = VT_USERDEFINED;
2664 pTD->u.hreftype = *(++pType) / 4;
2665 done = TRUE;
2666 break;
2668 case VT_CARRAY:
2670 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2671 array */
2673 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2675 pTD->vt = VT_CARRAY;
2676 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2677 sizeof(ARRAYDESC) +
2678 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2679 pTD->u.lpadesc->cDims = pSA->cDims;
2680 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2681 pSA->cDims * sizeof(SAFEARRAYBOUND));
2683 pTD = &pTD->u.lpadesc->tdescElem;
2684 break;
2687 case VT_SAFEARRAY:
2689 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2690 useful? */
2692 pType++;
2693 pTD->vt = VT_SAFEARRAY;
2694 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2695 sizeof(TYPEDESC));
2696 pTD = pTD->u.lptdesc;
2697 break;
2699 default:
2700 pTD->vt = *pType & 0x7f;
2701 done = TRUE;
2702 break;
2704 pType++;
2706 return pType;
2710 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2711 char *pNameTable)
2713 int ref;
2714 char *name;
2715 TLBRefType **ppRefType;
2717 if(pRef->magic != SLTG_REF_MAGIC) {
2718 FIXME("Ref magic = %x\n", pRef->magic);
2719 return;
2721 name = ( (char*)(&pRef->names) + pRef->number);
2723 ppRefType = &pTI->reflist;
2724 for(ref = 0; ref < pRef->number >> 3; ref++) {
2725 char *refname;
2726 unsigned int lib_offs, type_num;
2728 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2729 sizeof(**ppRefType));
2731 name += SLTG_ReadStringA(name, &refname);
2732 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2733 FIXME("Can't sscanf ref\n");
2734 if(lib_offs != 0xffff) {
2735 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2737 while(*import) {
2738 if((*import)->offset == lib_offs)
2739 break;
2740 import = &(*import)->next;
2742 if(!*import) {
2743 char fname[MAX_PATH+1];
2744 int len;
2746 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2747 sizeof(**import));
2748 (*import)->offset = lib_offs;
2749 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2750 &(*import)->guid);
2751 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2752 &(*import)->wVersionMajor,
2753 &(*import)->wVersionMinor,
2754 &(*import)->lcid, fname) != 4) {
2755 FIXME("can't sscanf ref %s\n",
2756 pNameTable + lib_offs + 40);
2758 len = strlen(fname);
2759 if(fname[len-1] != '#')
2760 FIXME("fname = %s\n", fname);
2761 fname[len-1] = '\0';
2762 (*import)->name = TLB_MultiByteToBSTR(fname);
2764 (*ppRefType)->pImpTLInfo = *import;
2765 } else { /* internal ref */
2766 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2768 (*ppRefType)->reference = ref;
2769 (*ppRefType)->index = type_num;
2771 HeapFree(GetProcessHeap(), 0, refname);
2772 ppRefType = &(*ppRefType)->next;
2774 if((BYTE)*name != SLTG_REF_MAGIC)
2775 FIXME("End of ref block magic = %x\n", *name);
2776 dump_TLBRefType(pTI->reflist);
2779 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2780 BOOL OneOnly)
2782 SLTG_ImplInfo *info;
2783 TLBImplType **ppImplType = &pTI->impltypelist;
2784 /* I don't really get this structure, usually it's 0x16 bytes
2785 long, but iuser.tlb contains some that are 0x18 bytes long.
2786 That's ok because we can use the next ptr to jump to the next
2787 one. But how do we know the length of the last one? The WORD
2788 at offs 0x8 might be the clue. For now I'm just assuming that
2789 the last one is the regular 0x16 bytes. */
2791 info = (SLTG_ImplInfo*)pBlk;
2792 while(1) {
2793 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2794 sizeof(**ppImplType));
2795 (*ppImplType)->hRef = info->ref;
2796 (*ppImplType)->implflags = info->impltypeflags;
2797 pTI->TypeAttr.cImplTypes++;
2798 ppImplType = &(*ppImplType)->next;
2800 if(info->next == 0xffff)
2801 break;
2802 if(OneOnly)
2803 FIXME("Interface inheriting more than one interface\n");
2804 info = (SLTG_ImplInfo*)(pBlk + info->next);
2806 info++; /* see comment at top of function */
2807 return (char*)info;
2810 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2811 char *pNameTable)
2813 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2814 SLTG_MemberHeader *pMemHeader;
2815 char *pFirstItem, *pNextItem;
2817 if(pTIHeader->href_table != 0xffffffff) {
2818 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2819 pNameTable);
2823 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2825 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2827 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2828 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2831 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2835 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2836 char *pNameTable)
2838 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2839 SLTG_MemberHeader *pMemHeader;
2840 SLTG_Function *pFunc;
2841 char *pFirstItem, *pNextItem;
2842 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2843 int num = 0;
2845 if(pTIHeader->href_table != 0xffffffff) {
2846 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2847 pNameTable);
2850 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2852 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2854 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2855 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2858 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2859 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2861 int param;
2862 WORD *pType, *pArg;
2864 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2865 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2866 FIXME("func magic = %02x\n", pFunc->magic);
2867 return NULL;
2869 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2870 sizeof(**ppFuncDesc));
2871 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2873 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2874 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2875 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2876 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2877 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2878 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2880 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2881 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2883 if(pFunc->retnextopt & 0x80)
2884 pType = &pFunc->rettype;
2885 else
2886 pType = (WORD*)(pFirstItem + pFunc->rettype);
2889 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2891 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2892 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2893 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2894 (*ppFuncDesc)->pParamDesc =
2895 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2896 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2898 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2900 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2901 char *paramName = pNameTable + *pArg;
2902 BOOL HaveOffs;
2903 /* If arg type follows then paramName points to the 2nd
2904 letter of the name, else the next WORD is an offset to
2905 the arg type and paramName points to the first letter.
2906 So let's take one char off paramName and see if we're
2907 pointing at an alpha-numeric char. However if *pArg is
2908 0xffff or 0xfffe then the param has no name, the former
2909 meaning that the next WORD is the type, the latter
2910 meaning the the next WORD is an offset to the type. */
2912 HaveOffs = FALSE;
2913 if(*pArg == 0xffff)
2914 paramName = NULL;
2915 else if(*pArg == 0xfffe) {
2916 paramName = NULL;
2917 HaveOffs = TRUE;
2919 else if(paramName[-1] && !isalnum(paramName[-1]))
2920 HaveOffs = TRUE;
2922 pArg++;
2924 if(HaveOffs) { /* the next word is an offset to type */
2925 pType = (WORD*)(pFirstItem + *pArg);
2926 SLTG_DoType(pType, pFirstItem,
2927 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2928 pArg++;
2929 } else {
2930 if(paramName)
2931 paramName--;
2932 pArg = SLTG_DoType(pArg, pFirstItem,
2933 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2936 /* Are we an optional param ? */
2937 if((*ppFuncDesc)->funcdesc.cParams - param <=
2938 (*ppFuncDesc)->funcdesc.cParamsOpt)
2939 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2941 if(paramName) {
2942 (*ppFuncDesc)->pParamDesc[param].Name =
2943 TLB_MultiByteToBSTR(paramName);
2947 ppFuncDesc = &((*ppFuncDesc)->next);
2948 if(pFunc->next == 0xffff) break;
2950 pTI->TypeAttr.cFuncs = num;
2951 dump_TLBFuncDesc(pTI->funclist);
2952 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2955 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2956 char *pNameTable)
2958 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2959 SLTG_MemberHeader *pMemHeader;
2960 SLTG_RecordItem *pItem;
2961 char *pFirstItem;
2962 TLBVarDesc **ppVarDesc = &pTI->varlist;
2963 int num = 0;
2964 WORD *pType;
2965 char buf[300];
2967 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2969 pFirstItem = (char*)(pMemHeader + 1);
2970 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2971 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2972 if(pItem->magic != SLTG_RECORD_MAGIC) {
2973 FIXME("record magic = %02x\n", pItem->magic);
2974 return NULL;
2976 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2977 sizeof(**ppVarDesc));
2978 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2979 (*ppVarDesc)->vardesc.memid = pItem->memid;
2980 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2981 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2983 if(pItem->typepos == 0x02)
2984 pType = &pItem->type;
2985 else if(pItem->typepos == 0x00)
2986 pType = (WORD*)(pFirstItem + pItem->type);
2987 else {
2988 FIXME("typepos = %02x\n", pItem->typepos);
2989 break;
2992 SLTG_DoType(pType, pFirstItem,
2993 &(*ppVarDesc)->vardesc.elemdescVar);
2995 /* FIXME("helpcontext, helpstring\n"); */
2997 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2999 ppVarDesc = &((*ppVarDesc)->next);
3000 if(pItem->next == 0xffff) break;
3002 pTI->TypeAttr.cVars = num;
3003 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3006 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3007 char *pNameTable)
3009 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3010 SLTG_MemberHeader *pMemHeader;
3011 SLTG_AliasItem *pItem;
3012 int i, mustbelast;
3014 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3015 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3017 mustbelast = 0;
3018 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3019 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3020 if (pItem->vt == 0xffff) {
3021 if (i<(pMemHeader->cbExtra/4-1))
3022 FIXME("Endmarker too early in process alias data!\n");
3023 break;
3025 if (mustbelast) {
3026 FIXME("Chain extends over last entry?\n");
3027 break;
3029 if (pItem->vt == VT_USERDEFINED) {
3030 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3031 /* guessing here ... */
3032 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3033 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3034 mustbelast = 1;
3035 } else {
3036 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3037 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3039 pItem++;
3041 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3044 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3045 char *pNameTable)
3047 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3048 SLTG_MemberHeader *pMemHeader;
3049 SLTG_AliasItem *pItem;
3051 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3052 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3053 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3054 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3055 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3058 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3059 char *pNameTable)
3061 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3062 SLTG_MemberHeader *pMemHeader;
3063 SLTG_EnumItem *pItem;
3064 char *pFirstItem;
3065 TLBVarDesc **ppVarDesc = &pTI->varlist;
3066 int num = 0;
3068 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3070 pFirstItem = (char*)(pMemHeader + 1);
3071 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3072 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3073 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3074 FIXME("enumitem magic = %04x\n", pItem->magic);
3075 return NULL;
3077 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3078 sizeof(**ppVarDesc));
3079 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3080 (*ppVarDesc)->vardesc.memid = pItem->memid;
3081 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3082 sizeof(VARIANT));
3083 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3084 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3085 *(INT*)(pItem->value + pFirstItem);
3086 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3087 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3088 /* FIXME("helpcontext, helpstring\n"); */
3090 ppVarDesc = &((*ppVarDesc)->next);
3091 if(pItem->next == 0xffff) break;
3093 pTI->TypeAttr.cVars = num;
3094 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3097 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3098 managable copy of it into this */
3099 typedef struct {
3100 WORD small_no;
3101 char *index_name;
3102 char *other_name;
3103 WORD res1a;
3104 WORD name_offs;
3105 WORD more_bytes;
3106 char *extra;
3107 WORD res20;
3108 DWORD helpcontext;
3109 WORD res26;
3110 GUID uuid;
3111 } SLTG_InternalOtherTypeInfo;
3113 /****************************************************************************
3114 * ITypeLib2_Constructor_SLTG
3116 * loading a SLTG typelib from an in-memory image
3118 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3120 ITypeLibImpl *pTypeLibImpl;
3121 SLTG_Header *pHeader;
3122 SLTG_BlkEntry *pBlkEntry;
3123 SLTG_Magic *pMagic;
3124 SLTG_Index *pIndex;
3125 SLTG_Pad9 *pPad9;
3126 LPVOID pBlk, pFirstBlk;
3127 SLTG_LibBlk *pLibBlk;
3128 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3129 char *pAfterOTIBlks = NULL;
3130 char *pNameTable, *ptr;
3131 int i;
3132 DWORD len, order;
3133 ITypeInfoImpl **ppTypeInfoImpl;
3135 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3137 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3138 if (!pTypeLibImpl) return NULL;
3140 pTypeLibImpl->lpVtbl = &tlbvt;
3141 pTypeLibImpl->ref = 1;
3143 pHeader = pLib;
3145 TRACE_(typelib)("header:\n");
3146 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3147 pHeader->nrOfFileBlks );
3148 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3149 FIXME("Header type magic 0x%08lx not supported.\n",
3150 pHeader->SLTG_magic);
3151 return NULL;
3154 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3155 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3157 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3158 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3160 /* Next we have a magic block */
3161 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3163 /* Let's see if we're still in sync */
3164 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3165 sizeof(SLTG_COMPOBJ_MAGIC))) {
3166 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3167 return NULL;
3169 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3170 sizeof(SLTG_DIR_MAGIC))) {
3171 FIXME("dir magic = %s\n", pMagic->dir_magic);
3172 return NULL;
3175 pIndex = (SLTG_Index*)(pMagic+1);
3177 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3179 pFirstBlk = (LPVOID)(pPad9 + 1);
3181 /* We'll set up a ptr to the main library block, which is the last one. */
3183 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3184 pBlkEntry[order].next != 0;
3185 order = pBlkEntry[order].next - 1, i++) {
3186 pBlk = (char*)pBlk + pBlkEntry[order].len;
3188 pLibBlk = pBlk;
3190 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3192 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3193 interspersed */
3195 len += 0x40;
3197 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3199 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3200 sizeof(*pOtherTypeInfoBlks) *
3201 pTypeLibImpl->TypeInfoCount);
3204 ptr = (char*)pLibBlk + len;
3206 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3207 WORD w, extra;
3208 len = 0;
3210 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3212 w = *(WORD*)(ptr + 2);
3213 if(w != 0xffff) {
3214 len += w;
3215 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3216 w+1);
3217 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3218 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3220 w = *(WORD*)(ptr + 4 + len);
3221 if(w != 0xffff) {
3222 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3223 len += w;
3224 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3225 w+1);
3226 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3227 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3229 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3230 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3231 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3232 if(extra) {
3233 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3234 extra);
3235 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3236 len += extra;
3238 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3239 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3240 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3241 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3242 len += sizeof(SLTG_OtherTypeInfo);
3243 ptr += len;
3246 pAfterOTIBlks = ptr;
3248 /* Skip this WORD and get the next DWORD */
3249 len = *(DWORD*)(pAfterOTIBlks + 2);
3251 /* Now add this to pLibBLk look at what we're pointing at and
3252 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3253 dust and we should be pointing at the beginning of the name
3254 table */
3256 pNameTable = (char*)pLibBlk + len;
3258 switch(*(WORD*)pNameTable) {
3259 case 0xffff:
3260 break;
3261 case 0x0200:
3262 pNameTable += 0x20;
3263 break;
3264 default:
3265 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3266 break;
3269 pNameTable += 0x216;
3271 pNameTable += 2;
3273 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3275 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3278 /* Hopefully we now have enough ptrs set up to actually read in
3279 some TypeInfos. It's not clear which order to do them in, so
3280 I'll just follow the links along the BlkEntry chain and read
3281 them in in the order in which they're in the file */
3283 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3285 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3286 pBlkEntry[order].next != 0;
3287 order = pBlkEntry[order].next - 1, i++) {
3289 SLTG_TypeInfoHeader *pTIHeader;
3290 SLTG_TypeInfoTail *pTITail;
3292 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3293 pOtherTypeInfoBlks[i].index_name)) {
3294 FIXME("Index strings don't match\n");
3295 return NULL;
3298 pTIHeader = pBlk;
3299 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3300 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3301 return NULL;
3303 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3304 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3305 (*ppTypeInfoImpl)->index = i;
3306 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3307 pOtherTypeInfoBlks[i].name_offs +
3308 pNameTable);
3309 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3310 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3311 sizeof(GUID));
3312 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3313 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3314 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3315 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3316 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3318 if((pTIHeader->typeflags1 & 7) != 2)
3319 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3320 if(pTIHeader->typeflags3 != 2)
3321 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3323 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3324 debugstr_w((*ppTypeInfoImpl)->Name),
3325 typekind_desc[pTIHeader->typekind],
3326 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3327 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3329 switch(pTIHeader->typekind) {
3330 case TKIND_ENUM:
3331 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3332 break;
3334 case TKIND_RECORD:
3335 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3336 break;
3338 case TKIND_INTERFACE:
3339 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3340 break;
3342 case TKIND_COCLASS:
3343 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3344 break;
3346 case TKIND_ALIAS:
3347 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3348 if (pTITail->tdescalias_vt)
3349 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3350 break;
3352 case TKIND_DISPATCH:
3353 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3354 break;
3356 default:
3357 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3358 pTITail = NULL;
3359 break;
3363 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3364 but we've already set those */
3365 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3366 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3367 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3369 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3370 X(06);
3371 X(08);
3372 X(0a);
3373 X(0c);
3374 X(0e);
3375 X(10);
3376 X(12);
3377 X(16);
3378 X(18);
3379 X(1a);
3380 X(1c);
3381 X(1e);
3382 X(24);
3383 X(26);
3384 X(2a);
3385 X(2c);
3386 X(2e);
3387 X(30);
3388 X(32);
3389 X(34);
3391 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3392 pBlk = (char*)pBlk + pBlkEntry[order].len;
3395 if(i != pTypeLibImpl->TypeInfoCount) {
3396 FIXME("Somehow processed %d TypeInfos\n", i);
3397 return NULL;
3400 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3401 return (ITypeLib2*)pTypeLibImpl;
3404 /* ITypeLib::QueryInterface
3406 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3407 ITypeLib2 * iface,
3408 REFIID riid,
3409 VOID **ppvObject)
3411 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3413 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3415 *ppvObject=NULL;
3416 if(IsEqualIID(riid, &IID_IUnknown) ||
3417 IsEqualIID(riid,&IID_ITypeLib)||
3418 IsEqualIID(riid,&IID_ITypeLib2))
3420 *ppvObject = This;
3423 if(*ppvObject)
3425 ITypeLib2_AddRef(iface);
3426 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3427 return S_OK;
3429 TRACE("-- Interface: E_NOINTERFACE\n");
3430 return E_NOINTERFACE;
3433 /* ITypeLib::AddRef
3435 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3437 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3438 ULONG ref = InterlockedIncrement(&This->ref);
3440 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3442 return ref;
3445 /* ITypeLib::Release
3447 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3449 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3450 ULONG ref = InterlockedDecrement(&This->ref);
3452 TRACE("(%p)->(%lu)\n",This, ref);
3454 if (!ref)
3456 /* remove cache entry */
3457 TRACE("removing from cache list\n");
3458 EnterCriticalSection(&cache_section);
3459 if (This->next) This->next->prev = This->prev;
3460 if (This->prev) This->prev->next = This->next;
3461 else tlb_cache_first = This->next;
3462 LeaveCriticalSection(&cache_section);
3464 /* FIXME destroy child objects */
3465 TRACE(" destroying ITypeLib(%p)\n",This);
3467 if (This->Name)
3469 SysFreeString(This->Name);
3470 This->Name = NULL;
3473 if (This->DocString)
3475 SysFreeString(This->DocString);
3476 This->DocString = NULL;
3479 if (This->HelpFile)
3481 SysFreeString(This->HelpFile);
3482 This->HelpFile = NULL;
3485 if (This->HelpStringDll)
3487 SysFreeString(This->HelpStringDll);
3488 This->HelpStringDll = NULL;
3491 if (This->pTypeInfo) /* can be NULL */
3492 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3493 HeapFree(GetProcessHeap(),0,This);
3494 return 0;
3497 return ref;
3500 /* ITypeLib::GetTypeInfoCount
3502 * Returns the number of type descriptions in the type library
3504 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3506 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3507 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3508 return This->TypeInfoCount;
3511 /* ITypeLib::GetTypeInfo
3513 * retrieves the specified type description in the library.
3515 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3516 ITypeLib2 *iface,
3517 UINT index,
3518 ITypeInfo **ppTInfo)
3520 int i;
3522 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3523 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3525 TRACE("(%p)->(index=%d) \n", This, index);
3527 if (!ppTInfo) return E_INVALIDARG;
3529 /* search element n in list */
3530 for(i=0; i < index; i++)
3532 pTypeInfo = pTypeInfo->next;
3533 if (!pTypeInfo)
3535 TRACE("-- element not found\n");
3536 return TYPE_E_ELEMENTNOTFOUND;
3540 *ppTInfo = (ITypeInfo *) pTypeInfo;
3542 ITypeInfo_AddRef(*ppTInfo);
3543 TRACE("-- found (%p)\n",*ppTInfo);
3544 return S_OK;
3548 /* ITypeLibs::GetTypeInfoType
3550 * Retrieves the type of a type description.
3552 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3553 ITypeLib2 *iface,
3554 UINT index,
3555 TYPEKIND *pTKind)
3557 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3558 int i;
3559 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3561 TRACE("(%p) index %d \n",This, index);
3563 if(!pTKind) return E_INVALIDARG;
3565 /* search element n in list */
3566 for(i=0; i < index; i++)
3568 if(!pTInfo)
3570 TRACE("-- element not found\n");
3571 return TYPE_E_ELEMENTNOTFOUND;
3573 pTInfo = pTInfo->next;
3576 *pTKind = pTInfo->TypeAttr.typekind;
3577 TRACE("-- found Type (%d)\n", *pTKind);
3578 return S_OK;
3581 /* ITypeLib::GetTypeInfoOfGuid
3583 * Retrieves the type description that corresponds to the specified GUID.
3586 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3587 ITypeLib2 *iface,
3588 REFGUID guid,
3589 ITypeInfo **ppTInfo)
3591 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3592 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3594 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3596 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3598 /* search linked list for guid */
3599 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3601 pTypeInfo = pTypeInfo->next;
3603 if (!pTypeInfo)
3605 /* end of list reached */
3606 TRACE("-- element not found\n");
3607 return TYPE_E_ELEMENTNOTFOUND;
3611 TRACE("-- found (%p, %s)\n",
3612 pTypeInfo,
3613 debugstr_w(pTypeInfo->Name));
3615 *ppTInfo = (ITypeInfo*)pTypeInfo;
3616 ITypeInfo_AddRef(*ppTInfo);
3617 return S_OK;
3620 /* ITypeLib::GetLibAttr
3622 * Retrieves the structure that contains the library's attributes.
3625 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3626 ITypeLib2 *iface,
3627 LPTLIBATTR *ppTLibAttr)
3629 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3630 TRACE("(%p)\n",This);
3631 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3632 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3633 return S_OK;
3636 /* ITypeLib::GetTypeComp
3638 * Enables a client compiler to bind to a library's types, variables,
3639 * constants, and global functions.
3642 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3643 ITypeLib2 *iface,
3644 ITypeComp **ppTComp)
3646 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3648 TRACE("(%p)->(%p)\n",This,ppTComp);
3649 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3650 ITypeComp_AddRef(*ppTComp);
3652 return S_OK;
3655 /* ITypeLib::GetDocumentation
3657 * Retrieves the library's documentation string, the complete Help file name
3658 * and path, and the context identifier for the library Help topic in the Help
3659 * file.
3661 * On a successful return all non-null BSTR pointers will have been set,
3662 * possibly to NULL.
3664 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3665 ITypeLib2 *iface,
3666 INT index,
3667 BSTR *pBstrName,
3668 BSTR *pBstrDocString,
3669 DWORD *pdwHelpContext,
3670 BSTR *pBstrHelpFile)
3672 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3674 HRESULT result = E_INVALIDARG;
3676 ITypeInfo *pTInfo;
3679 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3680 This, index,
3681 pBstrName, pBstrDocString,
3682 pdwHelpContext, pBstrHelpFile);
3684 if(index<0)
3686 /* documentation for the typelib */
3687 if(pBstrName)
3689 if (This->Name)
3691 if(!(*pBstrName = SysAllocString(This->Name)))
3692 goto memerr1;
3694 else
3695 *pBstrName = NULL;
3697 if(pBstrDocString)
3699 if (This->DocString)
3701 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3702 goto memerr2;
3704 else if (This->Name)
3706 if(!(*pBstrDocString = SysAllocString(This->Name)))
3707 goto memerr2;
3709 else
3710 *pBstrDocString = NULL;
3712 if(pdwHelpContext)
3714 *pdwHelpContext = This->dwHelpContext;
3716 if(pBstrHelpFile)
3718 if (This->HelpFile)
3720 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3721 goto memerr3;
3723 else
3724 *pBstrHelpFile = NULL;
3727 result = S_OK;
3729 else
3731 /* for a typeinfo */
3732 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3734 if(SUCCEEDED(result))
3736 result = ITypeInfo_GetDocumentation(pTInfo,
3737 MEMBERID_NIL,
3738 pBstrName,
3739 pBstrDocString,
3740 pdwHelpContext, pBstrHelpFile);
3742 ITypeInfo_Release(pTInfo);
3745 return result;
3746 memerr3:
3747 if (pBstrDocString) SysFreeString (*pBstrDocString);
3748 memerr2:
3749 if (pBstrName) SysFreeString (*pBstrName);
3750 memerr1:
3751 return STG_E_INSUFFICIENTMEMORY;
3754 /* ITypeLib::IsName
3756 * Indicates whether a passed-in string contains the name of a type or member
3757 * described in the library.
3760 static HRESULT WINAPI ITypeLib2_fnIsName(
3761 ITypeLib2 *iface,
3762 LPOLESTR szNameBuf,
3763 ULONG lHashVal,
3764 BOOL *pfName)
3766 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3767 ITypeInfoImpl *pTInfo;
3768 TLBFuncDesc *pFInfo;
3769 TLBVarDesc *pVInfo;
3770 int i;
3771 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3773 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3774 pfName);
3776 *pfName=TRUE;
3777 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3778 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3779 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3780 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3781 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3782 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3783 goto ITypeLib2_fnIsName_exit;
3785 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3786 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3789 *pfName=FALSE;
3791 ITypeLib2_fnIsName_exit:
3792 TRACE("(%p)slow! search for %s: %s found!\n", This,
3793 debugstr_w(szNameBuf), *pfName?"NOT":"");
3795 return S_OK;
3798 /* ITypeLib::FindName
3800 * Finds occurrences of a type description in a type library. This may be used
3801 * to quickly verify that a name exists in a type library.
3804 static HRESULT WINAPI ITypeLib2_fnFindName(
3805 ITypeLib2 *iface,
3806 LPOLESTR szNameBuf,
3807 ULONG lHashVal,
3808 ITypeInfo **ppTInfo,
3809 MEMBERID *rgMemId,
3810 UINT16 *pcFound)
3812 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3813 ITypeInfoImpl *pTInfo;
3814 TLBFuncDesc *pFInfo;
3815 TLBVarDesc *pVInfo;
3816 int i,j = 0;
3817 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3819 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3820 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3821 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3822 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3823 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3824 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3825 goto ITypeLib2_fnFindName_exit;
3828 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3829 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3830 continue;
3831 ITypeLib2_fnFindName_exit:
3832 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3833 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3834 j++;
3836 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3837 This, *pcFound, debugstr_w(szNameBuf), j);
3839 *pcFound=j;
3841 return S_OK;
3844 /* ITypeLib::ReleaseTLibAttr
3846 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3849 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3850 ITypeLib2 *iface,
3851 TLIBATTR *pTLibAttr)
3853 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3854 TRACE("freeing (%p)\n",This);
3855 HeapFree(GetProcessHeap(),0,pTLibAttr);
3859 /* ITypeLib2::GetCustData
3861 * gets the custom data
3863 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3864 ITypeLib2 * iface,
3865 REFGUID guid,
3866 VARIANT *pVarVal)
3868 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3869 TLBCustData *pCData;
3871 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3873 if( IsEqualIID(guid, &pCData->guid)) break;
3876 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3878 if(pCData)
3880 VariantInit( pVarVal);
3881 VariantCopy( pVarVal, &pCData->data);
3882 return S_OK;
3884 return E_INVALIDARG; /* FIXME: correct? */
3887 /* ITypeLib2::GetLibStatistics
3889 * Returns statistics about a type library that are required for efficient
3890 * sizing of hash tables.
3893 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3894 ITypeLib2 * iface,
3895 ULONG *pcUniqueNames,
3896 ULONG *pcchUniqueNames)
3898 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3900 FIXME("(%p): stub!\n", This);
3902 if(pcUniqueNames) *pcUniqueNames=1;
3903 if(pcchUniqueNames) *pcchUniqueNames=1;
3904 return S_OK;
3907 /* ITypeLib2::GetDocumentation2
3909 * Retrieves the library's documentation string, the complete Help file name
3910 * and path, the localization context to use, and the context ID for the
3911 * library Help topic in the Help file.
3914 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3915 ITypeLib2 * iface,
3916 INT index,
3917 LCID lcid,
3918 BSTR *pbstrHelpString,
3919 DWORD *pdwHelpStringContext,
3920 BSTR *pbstrHelpStringDll)
3922 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3923 HRESULT result;
3924 ITypeInfo *pTInfo;
3926 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3928 /* the help string should be obtained from the helpstringdll,
3929 * using the _DLLGetDocumentation function, based on the supplied
3930 * lcid. Nice to do sometime...
3932 if(index<0)
3934 /* documentation for the typelib */
3935 if(pbstrHelpString)
3936 *pbstrHelpString=SysAllocString(This->DocString);
3937 if(pdwHelpStringContext)
3938 *pdwHelpStringContext=This->dwHelpContext;
3939 if(pbstrHelpStringDll)
3940 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3942 result = S_OK;
3944 else
3946 /* for a typeinfo */
3947 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3949 if(SUCCEEDED(result))
3951 ITypeInfo2 * pTInfo2;
3952 result = ITypeInfo_QueryInterface(pTInfo,
3953 &IID_ITypeInfo2,
3954 (LPVOID*) &pTInfo2);
3956 if(SUCCEEDED(result))
3958 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3959 MEMBERID_NIL,
3960 lcid,
3961 pbstrHelpString,
3962 pdwHelpStringContext,
3963 pbstrHelpStringDll);
3965 ITypeInfo2_Release(pTInfo2);
3968 ITypeInfo_Release(pTInfo);
3971 return result;
3974 /* ITypeLib2::GetAllCustData
3976 * Gets all custom data items for the library.
3979 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3980 ITypeLib2 * iface,
3981 CUSTDATA *pCustData)
3983 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3984 TLBCustData *pCData;
3985 int i;
3986 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3987 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3988 if(pCustData->prgCustData ){
3989 pCustData->cCustData=This->ctCustData;
3990 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3991 pCustData->prgCustData[i].guid=pCData->guid;
3992 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3994 }else{
3995 ERR(" OUT OF MEMORY! \n");
3996 return E_OUTOFMEMORY;
3998 return S_OK;
4001 static const ITypeLib2Vtbl tlbvt = {
4002 ITypeLib2_fnQueryInterface,
4003 ITypeLib2_fnAddRef,
4004 ITypeLib2_fnRelease,
4005 ITypeLib2_fnGetTypeInfoCount,
4006 ITypeLib2_fnGetTypeInfo,
4007 ITypeLib2_fnGetTypeInfoType,
4008 ITypeLib2_fnGetTypeInfoOfGuid,
4009 ITypeLib2_fnGetLibAttr,
4010 ITypeLib2_fnGetTypeComp,
4011 ITypeLib2_fnGetDocumentation,
4012 ITypeLib2_fnIsName,
4013 ITypeLib2_fnFindName,
4014 ITypeLib2_fnReleaseTLibAttr,
4016 ITypeLib2_fnGetCustData,
4017 ITypeLib2_fnGetLibStatistics,
4018 ITypeLib2_fnGetDocumentation2,
4019 ITypeLib2_fnGetAllCustData
4023 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4025 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4027 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4030 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4032 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4034 return ITypeLib2_AddRef((ITypeLib2 *)This);
4037 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4039 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4041 return ITypeLib2_Release((ITypeLib2 *)This);
4044 static HRESULT WINAPI ITypeLibComp_fnBind(
4045 ITypeComp * iface,
4046 OLECHAR * szName,
4047 ULONG lHash,
4048 WORD wFlags,
4049 ITypeInfo ** ppTInfo,
4050 DESCKIND * pDescKind,
4051 BINDPTR * pBindPtr)
4053 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4054 return E_NOTIMPL;
4057 static HRESULT WINAPI ITypeLibComp_fnBindType(
4058 ITypeComp * iface,
4059 OLECHAR * szName,
4060 ULONG lHash,
4061 ITypeInfo ** ppTInfo,
4062 ITypeComp ** ppTComp)
4064 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4065 return E_NOTIMPL;
4068 static const ITypeCompVtbl tlbtcvt =
4071 ITypeLibComp_fnQueryInterface,
4072 ITypeLibComp_fnAddRef,
4073 ITypeLibComp_fnRelease,
4075 ITypeLibComp_fnBind,
4076 ITypeLibComp_fnBindType
4079 /*================== ITypeInfo(2) Methods ===================================*/
4080 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4082 ITypeInfoImpl * pTypeInfoImpl;
4084 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4085 if (pTypeInfoImpl)
4087 pTypeInfoImpl->lpVtbl = &tinfvt;
4088 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4089 pTypeInfoImpl->ref=1;
4091 TRACE("(%p)\n", pTypeInfoImpl);
4092 return (ITypeInfo2*) pTypeInfoImpl;
4095 /* ITypeInfo::QueryInterface
4097 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4098 ITypeInfo2 *iface,
4099 REFIID riid,
4100 VOID **ppvObject)
4102 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4104 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4106 *ppvObject=NULL;
4107 if(IsEqualIID(riid, &IID_IUnknown) ||
4108 IsEqualIID(riid,&IID_ITypeInfo)||
4109 IsEqualIID(riid,&IID_ITypeInfo2))
4110 *ppvObject = This;
4112 if(*ppvObject){
4113 ITypeInfo_AddRef(iface);
4114 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4115 return S_OK;
4117 TRACE("-- Interface: E_NOINTERFACE\n");
4118 return E_NOINTERFACE;
4121 /* ITypeInfo::AddRef
4123 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4125 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4126 ULONG ref = InterlockedIncrement(&This->ref);
4128 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4130 TRACE("(%p)->ref is %lu\n",This, ref);
4131 return ref;
4134 /* ITypeInfo::Release
4136 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4138 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4139 ULONG ref = InterlockedDecrement(&This->ref);
4141 TRACE("(%p)->(%lu)\n",This, ref);
4143 if (ref) {
4144 /* We don't release ITypeLib when ref=0 because
4145 it means that function is called by ITypeLib2_Release */
4146 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4147 } else {
4148 FIXME("destroy child objects\n");
4150 TRACE("destroying ITypeInfo(%p)\n",This);
4151 if (This->Name)
4153 SysFreeString(This->Name);
4154 This->Name = 0;
4157 if (This->DocString)
4159 SysFreeString(This->DocString);
4160 This->DocString = 0;
4163 if (This->next)
4165 ITypeInfo_Release((ITypeInfo*)This->next);
4168 HeapFree(GetProcessHeap(),0,This);
4169 return 0;
4171 return ref;
4174 /* ITypeInfo::GetTypeAttr
4176 * Retrieves a TYPEATTR structure that contains the attributes of the type
4177 * description.
4180 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4181 LPTYPEATTR *ppTypeAttr)
4183 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4184 TRACE("(%p)\n",This);
4185 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr));
4186 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4188 if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */
4189 copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias);
4191 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4192 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4193 funcs */
4194 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4195 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4197 return S_OK;
4200 /* ITypeInfo::GetTypeComp
4202 * Retrieves the ITypeComp interface for the type description, which enables a
4203 * client compiler to bind to the type description's members.
4206 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4207 ITypeComp * *ppTComp)
4209 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4211 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4213 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4214 ITypeComp_AddRef(*ppTComp);
4215 return S_OK;
4218 /* ITypeInfo::GetFuncDesc
4220 * Retrieves the FUNCDESC structure that contains information about a
4221 * specified function.
4224 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4225 LPFUNCDESC *ppFuncDesc)
4227 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4228 int i;
4229 TLBFuncDesc * pFDesc;
4230 TRACE("(%p) index %d\n", This, index);
4231 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4233 if(pFDesc){
4234 /* FIXME: must do a copy here */
4235 *ppFuncDesc=&pFDesc->funcdesc;
4236 return S_OK;
4238 return E_INVALIDARG;
4241 /* ITypeInfo::GetVarDesc
4243 * Retrieves a VARDESC structure that describes the specified variable.
4246 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4247 LPVARDESC *ppVarDesc)
4249 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4250 int i;
4251 TLBVarDesc * pVDesc;
4252 TRACE("(%p) index %d\n", This, index);
4253 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4255 if(pVDesc){
4256 /* FIXME: must do a copy here */
4257 *ppVarDesc=&pVDesc->vardesc;
4258 return S_OK;
4260 return E_INVALIDARG;
4263 /* ITypeInfo_GetNames
4265 * Retrieves the variable with the specified member ID (or the name of the
4266 * property or method and its parameters) that correspond to the specified
4267 * function ID.
4269 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4270 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4272 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4273 TLBFuncDesc * pFDesc;
4274 TLBVarDesc * pVDesc;
4275 int i;
4276 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4277 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4278 if(pFDesc)
4280 /* function found, now return function and parameter names */
4281 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4283 if(!i)
4284 *rgBstrNames=SysAllocString(pFDesc->Name);
4285 else
4286 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4288 *pcNames=i;
4290 else
4292 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4293 if(pVDesc)
4295 *rgBstrNames=SysAllocString(pVDesc->Name);
4296 *pcNames=1;
4298 else
4300 if(This->TypeAttr.cImplTypes &&
4301 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4302 /* recursive search */
4303 ITypeInfo *pTInfo;
4304 HRESULT result;
4305 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4306 &pTInfo);
4307 if(SUCCEEDED(result))
4309 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4310 ITypeInfo_Release(pTInfo);
4311 return result;
4313 WARN("Could not search inherited interface!\n");
4315 else
4317 WARN("no names found\n");
4319 *pcNames=0;
4320 return TYPE_E_ELEMENTNOTFOUND;
4323 return S_OK;
4327 /* ITypeInfo::GetRefTypeOfImplType
4329 * If a type description describes a COM class, it retrieves the type
4330 * description of the implemented interface types. For an interface,
4331 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4332 * if any exist.
4335 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4336 ITypeInfo2 *iface,
4337 UINT index,
4338 HREFTYPE *pRefType)
4340 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4341 int(i);
4342 TLBImplType *pImpl = This->impltypelist;
4344 TRACE("(%p) index %d\n", This, index);
4345 if (TRACE_ON(ole)) dump_TypeInfo(This);
4347 if(index==(UINT)-1)
4349 /* only valid on dual interfaces;
4350 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4352 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4354 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4355 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4357 *pRefType = -1;
4359 else
4361 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4362 *pRefType = pImpl->hRef;
4365 else
4367 /* get element n from linked list */
4368 for(i=0; pImpl && i<index; i++)
4370 pImpl = pImpl->next;
4373 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4375 *pRefType = pImpl->hRef;
4377 TRACE("-- 0x%08lx\n", pImpl->hRef );
4380 return S_OK;
4384 /* ITypeInfo::GetImplTypeFlags
4386 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4387 * or base interface in a type description.
4389 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4390 UINT index, INT *pImplTypeFlags)
4392 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4393 int i;
4394 TLBImplType *pImpl;
4396 TRACE("(%p) index %d\n", This, index);
4397 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4398 i++, pImpl=pImpl->next)
4400 if(i==index && pImpl){
4401 *pImplTypeFlags=pImpl->implflags;
4402 return S_OK;
4404 *pImplTypeFlags=0;
4405 return TYPE_E_ELEMENTNOTFOUND;
4408 /* GetIDsOfNames
4409 * Maps between member names and member IDs, and parameter names and
4410 * parameter IDs.
4412 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4413 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4415 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4416 TLBFuncDesc * pFDesc;
4417 TLBVarDesc * pVDesc;
4418 HRESULT ret=S_OK;
4420 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4421 cNames);
4422 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4423 int i, j;
4424 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4425 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4426 for(i=1; i < cNames; i++){
4427 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4428 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4429 break;
4430 if( j<pFDesc->funcdesc.cParams)
4431 pMemId[i]=j;
4432 else
4433 ret=DISP_E_UNKNOWNNAME;
4435 return ret;
4438 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4439 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4440 if(cNames) *pMemId=pVDesc->vardesc.memid;
4441 return ret;
4444 /* not found, see if this is and interface with an inheritance */
4445 if(This->TypeAttr.cImplTypes &&
4446 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4447 /* recursive search */
4448 ITypeInfo *pTInfo;
4449 ret=ITypeInfo_GetRefTypeInfo(iface,
4450 This->impltypelist->hRef, &pTInfo);
4451 if(SUCCEEDED(ret)){
4452 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4453 ITypeInfo_Release(pTInfo);
4454 return ret;
4456 WARN("Could not search inherited interface!\n");
4457 } else
4458 WARN("no names found\n");
4459 return DISP_E_UNKNOWNNAME;
4462 /* ITypeInfo::Invoke
4464 * Invokes a method, or accesses a property of an object, that implements the
4465 * interface described by the type description.
4467 DWORD
4468 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4469 DWORD res;
4471 if (TRACE_ON(ole)) {
4472 int i;
4473 TRACE("Calling %p(",func);
4474 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4475 TRACE(")\n");
4478 switch (callconv) {
4479 case CC_STDCALL:
4481 switch (nrargs) {
4482 case 0:
4483 res = func();
4484 break;
4485 case 1:
4486 res = func(args[0]);
4487 break;
4488 case 2:
4489 res = func(args[0],args[1]);
4490 break;
4491 case 3:
4492 res = func(args[0],args[1],args[2]);
4493 break;
4494 case 4:
4495 res = func(args[0],args[1],args[2],args[3]);
4496 break;
4497 case 5:
4498 res = func(args[0],args[1],args[2],args[3],args[4]);
4499 break;
4500 case 6:
4501 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4502 break;
4503 case 7:
4504 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4505 break;
4506 case 8:
4507 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4508 break;
4509 case 9:
4510 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4511 break;
4512 case 10:
4513 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4514 break;
4515 case 11:
4516 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4517 break;
4518 case 12:
4519 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]);
4520 break;
4521 case 13:
4522 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]);
4523 break;
4524 case 14:
4525 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]);
4526 break;
4527 default:
4528 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4529 res = -1;
4530 break;
4532 break;
4533 default:
4534 FIXME("unsupported calling convention %d\n",callconv);
4535 res = -1;
4536 break;
4538 TRACE("returns %08lx\n",res);
4539 return res;
4542 extern int _argsize(DWORD vt);
4544 /****************************************************************************
4545 * Helper functions for Dispcall / Invoke, which copies one variant
4546 * with target type onto the argument stack.
4548 static HRESULT
4549 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4550 DWORD *argpos, VARIANT *arg, VARTYPE vt
4552 UINT arglen = _argsize(vt)*sizeof(DWORD);
4553 VARIANT va;
4555 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4556 memcpy(argpos,&arg,sizeof(void*));
4557 return S_OK;
4560 if (V_VT(arg) == vt) {
4561 memcpy(argpos, &V_I4(arg), arglen);
4562 return S_OK;
4565 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4566 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4567 return S_OK;
4570 if (vt == VT_VARIANT) {
4571 memcpy(argpos, arg, arglen);
4572 return S_OK;
4574 /* Deref BYREF vars if there is need */
4575 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4576 memcpy(argpos,(void*)V_I4(arg), arglen);
4577 return S_OK;
4579 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4580 /* in this context, if the type lib specifies IUnknown*, giving an
4581 IDispatch* is correct; so, don't invoke VariantChangeType */
4582 memcpy(argpos,&V_I4(arg), arglen);
4583 return S_OK;
4585 if ((vt == VT_PTR) && tdesc)
4586 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4588 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4589 ITypeInfo *tinfo2 = NULL;
4590 TYPEATTR *tattr = NULL;
4591 HRESULT hres;
4593 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4594 if (hres) {
4595 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4596 "while coercing from vt 0x%x. Copying 4 byte.\n",
4597 tdesc->u.hreftype,V_VT(arg));
4598 memcpy(argpos, &V_I4(arg), 4);
4599 return S_OK;
4601 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4602 if( hres )
4604 ERR("GetTypeAttr failed\n");
4605 ITypeInfo_Release(tinfo2);
4606 return hres;
4608 switch (tattr->typekind) {
4609 case TKIND_ENUM:
4610 switch ( V_VT( arg ) ) {
4611 case VT_I2:
4612 *argpos = V_I2(arg);
4613 hres = S_OK;
4614 break;
4615 case VT_I4:
4616 memcpy(argpos, &V_I4(arg), 4);
4617 hres = S_OK;
4618 break;
4619 case VT_BYREF|VT_I4:
4620 memcpy(argpos, V_I4REF(arg), 4);
4621 hres = S_OK;
4622 break;
4623 default:
4624 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4625 hres = E_FAIL;
4626 break;
4628 break;
4630 case TKIND_ALIAS:
4631 tdesc = &(tattr->tdescAlias);
4632 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4633 break;
4635 case TKIND_INTERFACE:
4636 if (V_VT(arg) == VT_DISPATCH) {
4637 IDispatch *disp;
4638 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4639 memcpy(argpos, &V_DISPATCH(arg), 4);
4640 hres = S_OK;
4641 break;
4643 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4644 &IID_IDispatch,(LPVOID*)&disp);
4645 if (SUCCEEDED(hres)) {
4646 memcpy(argpos,&disp,4);
4647 IUnknown_Release(V_DISPATCH(arg));
4648 hres = S_OK;
4649 break;
4651 FIXME("Failed to query IDispatch interface from %s while "
4652 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4653 hres = E_FAIL;
4654 break;
4656 if (V_VT(arg) == VT_UNKNOWN) {
4657 memcpy(argpos, &V_UNKNOWN(arg), 4);
4658 hres = S_OK;
4659 break;
4661 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4662 V_VT(arg),debugstr_guid(&(tattr->guid)));
4663 hres = E_FAIL;
4664 break;
4666 case TKIND_DISPATCH:
4667 if (V_VT(arg) == VT_DISPATCH) {
4668 memcpy(argpos, &V_DISPATCH(arg), 4);
4669 hres = S_OK;
4671 else {
4672 hres = E_FAIL;
4673 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4675 break;
4676 case TKIND_RECORD:
4677 FIXME("TKIND_RECORD unhandled.\n");
4678 hres = E_FAIL;
4679 break;
4680 default:
4681 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4682 hres = E_FAIL;
4683 break;
4685 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4686 ITypeInfo_Release(tinfo2);
4687 return hres;
4690 VariantInit(&va);
4691 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4692 memcpy(argpos,&V_I4(&va), arglen);
4693 FIXME("Should not use VariantChangeType here."
4694 " (conversion from 0x%x -> 0x%x) %08lx\n",
4695 V_VT(arg), vt, *argpos
4697 return S_OK;
4699 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4700 return E_FAIL;
4703 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
4705 HRESULT hr = S_OK;
4706 ITypeInfo *tinfo2 = NULL;
4707 TYPEATTR *tattr = NULL;
4709 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4710 if (hr)
4712 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4713 "hr = 0x%08lx\n",
4714 tdesc->u.hreftype, hr);
4715 return hr;
4717 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4718 if (hr)
4720 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4721 ITypeInfo_Release(tinfo2);
4722 return hr;
4725 switch (tattr->typekind)
4727 case TKIND_ENUM:
4728 *vt |= VT_INT;
4729 break;
4731 case TKIND_ALIAS:
4732 tdesc = &tattr->tdescAlias;
4733 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4734 break;
4736 case TKIND_INTERFACE:
4737 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4738 *vt |= VT_DISPATCH;
4739 else
4740 *vt |= VT_UNKNOWN;
4741 break;
4743 case TKIND_DISPATCH:
4744 *vt |= VT_DISPATCH;
4745 break;
4747 case TKIND_RECORD:
4748 FIXME("TKIND_RECORD unhandled.\n");
4749 hr = E_NOTIMPL;
4750 break;
4752 case TKIND_UNION:
4753 FIXME("TKIND_RECORD unhandled.\n");
4754 hr = E_NOTIMPL;
4755 break;
4757 default:
4758 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4759 hr = E_NOTIMPL;
4760 break;
4762 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4763 ITypeInfo_Release(tinfo2);
4764 return hr;
4767 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
4769 HRESULT hr = S_OK;
4771 /* enforce only one level of pointer indirection */
4772 if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
4774 tdesc = tdesc->u.lptdesc;
4776 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4777 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4778 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4779 if ((tdesc->vt == VT_USERDEFINED) ||
4780 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4782 VARTYPE vt_userdefined = 0;
4783 TYPEDESC *tdesc_userdefined = tdesc;
4784 if (tdesc->vt == VT_PTR)
4786 vt_userdefined = VT_BYREF;
4787 tdesc_userdefined = tdesc->u.lptdesc;
4789 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
4790 if ((hr == S_OK) &&
4791 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
4792 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
4794 *vt |= vt_userdefined;
4795 return S_OK;
4798 *vt = VT_BYREF;
4801 switch (tdesc->vt)
4803 case VT_HRESULT:
4804 *vt |= VT_ERROR;
4805 break;
4806 case VT_USERDEFINED:
4807 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
4808 break;
4809 case VT_PTR:
4810 ERR("cannot convert VT_PTR into variant VT\n");
4811 hr = E_FAIL;
4812 break;
4813 default:
4814 *vt |= tdesc->vt;
4815 break;
4817 return hr;
4820 /***********************************************************************
4821 * DispCallFunc (OLEAUT32.@)
4823 HRESULT WINAPI
4824 DispCallFunc(
4825 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4826 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4828 int i, argsize, argspos;
4829 DWORD *args;
4830 HRESULT hres;
4832 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4833 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4835 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4836 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4837 argsize = 1;
4838 for (i=0;i<cActuals;i++) {
4839 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4840 dump_Variant(prgpvarg[i]);
4841 argsize += _argsize(prgvt[i]);
4843 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4844 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4845 argspos = 1;
4846 for (i=0;i<cActuals;i++) {
4847 VARIANT *arg = prgpvarg[i];
4848 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4849 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4850 argspos += _argsize(prgvt[i]);
4853 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4855 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4856 hres=S_OK;
4858 else
4860 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4861 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4862 FIXME("Method returned %lx\n",hres);
4864 HeapFree(GetProcessHeap(),0,args);
4865 return hres;
4868 static HRESULT WINAPI ITypeInfo_fnInvoke(
4869 ITypeInfo2 *iface,
4870 VOID *pIUnk,
4871 MEMBERID memid,
4872 UINT16 dwFlags,
4873 DISPPARAMS *pDispParams,
4874 VARIANT *pVarResult,
4875 EXCEPINFO *pExcepInfo,
4876 UINT *pArgErr)
4878 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4879 int i;
4880 unsigned int func_index, var_index;
4881 TYPEKIND type_kind;
4882 HRESULT hres;
4884 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4885 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4887 dump_DispParms(pDispParams);
4889 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4890 if (SUCCEEDED(hres)) {
4891 FUNCDESC *func_desc;
4893 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4894 if(FAILED(hres)) return hres;
4895 if (TRACE_ON(ole))
4897 TRACE("invoking:\n");
4898 dump_FUNCDESC(func_desc);
4901 switch (func_desc->funckind) {
4902 case FUNC_PUREVIRTUAL:
4903 case FUNC_VIRTUAL: {
4904 DWORD res;
4905 int numargs, numargs2, argspos, args2pos;
4906 DWORD *args , *args2;
4907 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4908 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4910 hres = S_OK;
4911 numargs = 1; /* sizeof(thisptr) */
4912 numargs2 = 0;
4913 for (i = 0; i < func_desc->cParams; i++) {
4914 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4916 numargs += _argsize(tdesc->vt);
4917 if (i>=pDispParams->cArgs) { /* arguments to return */
4918 if (tdesc->vt == VT_PTR) {
4919 numargs2 += _argsize(tdesc->u.lptdesc->vt);
4920 } else {
4921 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
4922 numargs2 += _argsize(tdesc->vt);
4927 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4928 args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
4930 args[0] = (DWORD)pIUnk;
4931 argspos = 1; args2pos = 0;
4932 for (i = 0; i < func_desc->cParams; i++) {
4933 ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
4934 TYPEDESC *tdesc = &(elemdesc->tdesc);
4935 USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
4936 int arglen = _argsize(tdesc->vt);
4938 if (i<pDispParams->cArgs) {
4939 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4941 if (paramFlags & PARAMFLAG_FOPT) {
4942 if(i < func_desc->cParams - func_desc->cParamsOpt)
4943 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4944 if(V_VT(arg) == VT_EMPTY
4945 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
4946 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4947 How to determine it? */
4949 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4950 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4951 V_VT(arg) = VT_ERROR;
4952 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4953 arglen = _argsize(VT_ERROR);
4956 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4957 if (FAILED(hres)) goto func_fail;
4958 argspos += arglen;
4959 } else if (paramFlags & PARAMFLAG_FOPT) {
4960 VARIANT *arg = &rgvarg[i];
4962 if (i < func_desc->cParams - func_desc->cParamsOpt)
4963 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4964 if (paramFlags & PARAMFLAG_FHASDEFAULT)
4965 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4967 V_VT(arg) = VT_ERROR;
4968 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4969 arglen = _argsize(VT_ERROR);
4970 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4971 if (FAILED(hres)) goto func_fail;
4972 argspos += arglen;
4973 } else {
4974 if (tdesc->vt == VT_PTR)
4975 arglen = _argsize(tdesc->u.lptdesc->vt);
4976 else
4977 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4979 /* Supply pointers for the rest, so propertyget works*/
4980 args[argspos] = (DWORD)&args2[args2pos];
4982 /* If pointer to variant, pass reference it. */
4983 if ((tdesc->vt == VT_PTR) &&
4984 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4985 pVarResult
4987 args[argspos]= (DWORD)pVarResult;
4988 argspos += 1;
4989 args2pos += arglen;
4992 if (func_desc->cParamsOpt < 0)
4993 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
4995 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
4996 func_desc->callconv,
4997 numargs,
4998 args
5001 if (pVarResult) {
5002 for (i = 0; i < func_desc->cParams; i++) {
5003 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5004 if (wParamFlags & PARAMFLAG_FRETVAL) {
5005 ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
5006 TYPEDESC *tdesc = &elemdesc->tdesc;
5007 VARIANTARG varresult;
5008 V_VT(&varresult) = 0;
5009 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
5010 if (hres)
5011 break;
5012 /* FIXME: this is really messy - we should keep the
5013 * args in VARIANTARGs rather than a DWORD array */
5014 memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
5015 if (TRACE_ON(ole))
5017 TRACE("varresult: ");
5018 dump_Variant(&varresult);
5020 hres = VariantCopyInd(pVarResult, &varresult);
5021 /* free data stored in varresult. Note that
5022 * VariantClear doesn't do what we want because we are
5023 * working with byref types. */
5024 /* FIXME: clear safearrays, bstrs, records and
5025 * variants here too */
5026 if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) ||
5027 (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF)))
5028 IUnknown_Release(*V_UNKNOWNREF(&varresult));
5029 break;
5034 if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
5035 WARN("invoked function failed with error 0x%08lx\n", res);
5036 hres = DISP_E_EXCEPTION;
5037 if (pExcepInfo) pExcepInfo->scode = res;
5039 func_fail:
5040 HeapFree(GetProcessHeap(), 0, rgvarg);
5041 HeapFree(GetProcessHeap(),0,args2);
5042 HeapFree(GetProcessHeap(),0,args);
5043 break;
5045 case FUNC_DISPATCH: {
5046 IDispatch *disp;
5048 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5049 if (SUCCEEDED(hres)) {
5050 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5051 hres = IDispatch_Invoke(
5052 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
5053 pVarResult,pExcepInfo,pArgErr
5055 if (FAILED(hres))
5056 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5057 IDispatch_Release(disp);
5058 } else
5059 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5060 break;
5062 default:
5063 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5064 hres = E_FAIL;
5065 break;
5068 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
5069 return hres;
5071 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5072 VARDESC *var_desc;
5074 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5075 if(FAILED(hres)) return hres;
5077 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5078 dump_VARDESC(var_desc);
5079 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5080 return E_NOTIMPL;
5083 /* not found, look for it in inherited interfaces */
5084 ITypeInfo2_GetTypeKind(iface, &type_kind);
5085 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5086 HREFTYPE ref_type;
5087 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5088 /* recursive search */
5089 ITypeInfo *pTInfo;
5090 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5091 if(SUCCEEDED(hres)){
5092 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5093 ITypeInfo_Release(pTInfo);
5094 return hres;
5096 WARN("Could not search inherited interface!\n");
5099 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
5100 return DISP_E_MEMBERNOTFOUND;
5103 /* ITypeInfo::GetDocumentation
5105 * Retrieves the documentation string, the complete Help file name and path,
5106 * and the context ID for the Help topic for a specified type description.
5108 * (Can be tested by the Visual Basic Editor in Word for instance.)
5110 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5111 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5112 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5114 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5115 TLBFuncDesc * pFDesc;
5116 TLBVarDesc * pVDesc;
5117 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5118 " HelpContext(%p) HelpFile(%p)\n",
5119 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5120 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5121 if(pBstrName)
5122 *pBstrName=SysAllocString(This->Name);
5123 if(pBstrDocString)
5124 *pBstrDocString=SysAllocString(This->DocString);
5125 if(pdwHelpContext)
5126 *pdwHelpContext=This->dwHelpContext;
5127 if(pBstrHelpFile)
5128 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5129 return S_OK;
5130 }else {/* for a member */
5131 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5132 if(pFDesc->funcdesc.memid==memid){
5133 if(pBstrName)
5134 *pBstrName = SysAllocString(pFDesc->Name);
5135 if(pBstrDocString)
5136 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5137 if(pdwHelpContext)
5138 *pdwHelpContext=pFDesc->helpcontext;
5139 return S_OK;
5141 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5142 if(pVDesc->vardesc.memid==memid){
5143 if(pBstrName)
5144 *pBstrName = SysAllocString(pVDesc->Name);
5145 if(pBstrDocString)
5146 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5147 if(pdwHelpContext)
5148 *pdwHelpContext=pVDesc->HelpContext;
5149 return S_OK;
5152 WARN("member %ld not found\n", memid);
5153 return TYPE_E_ELEMENTNOTFOUND;
5156 /* ITypeInfo::GetDllEntry
5158 * Retrieves a description or specification of an entry point for a function
5159 * in a DLL.
5161 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5162 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5163 WORD *pwOrdinal)
5165 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5166 TLBFuncDesc *pFDesc;
5168 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5170 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5171 if(pFDesc->funcdesc.memid==memid){
5172 dump_TypeInfo(This);
5173 dump_TLBFuncDescOne(pFDesc);
5175 /* FIXME: This is wrong, but how do you find that out? */
5176 if (pBstrDllName) {
5177 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5178 *pBstrDllName = SysAllocString(oleaut32W);
5181 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5182 if (pBstrName)
5183 *pBstrName = SysAllocString(pFDesc->Entry);
5184 if (pwOrdinal)
5185 *pwOrdinal = -1;
5186 return S_OK;
5188 if (pBstrName)
5189 *pBstrName = NULL;
5190 if (pwOrdinal)
5191 *pwOrdinal = (DWORD)pFDesc->Entry;
5192 return S_OK;
5194 return E_FAIL;
5197 /* ITypeInfo::GetRefTypeInfo
5199 * If a type description references other type descriptions, it retrieves
5200 * the referenced type descriptions.
5202 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5203 ITypeInfo2 *iface,
5204 HREFTYPE hRefType,
5205 ITypeInfo **ppTInfo)
5207 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5208 HRESULT result = E_FAIL;
5210 if (hRefType == -1 &&
5211 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5212 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5214 /* when we meet a DUAL dispinterface, we must create the interface
5215 * version of it.
5217 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5220 /* the interface version contains the same information as the dispinterface
5221 * copy the contents of the structs.
5223 *pTypeInfoImpl = *This;
5224 pTypeInfoImpl->ref = 1;
5226 /* change the type to interface */
5227 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5229 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5231 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5233 result = S_OK;
5235 } else {
5236 TLBRefType *pRefType;
5237 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5238 if(pRefType->reference == hRefType)
5239 break;
5241 if(!pRefType)
5242 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5243 if(pRefType && hRefType != -1) {
5244 ITypeLib *pTLib = NULL;
5246 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5247 UINT Index;
5248 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5249 } else {
5250 if(pRefType->pImpTLInfo->pImpTypeLib) {
5251 TRACE("typeinfo in imported typelib that is already loaded\n");
5252 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5253 ITypeLib2_AddRef((ITypeLib*) pTLib);
5254 result = S_OK;
5255 } else {
5256 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5257 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5258 pRefType->pImpTLInfo->wVersionMajor,
5259 pRefType->pImpTLInfo->wVersionMinor,
5260 pRefType->pImpTLInfo->lcid,
5261 &pTLib);
5263 if(!SUCCEEDED(result)) {
5264 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5265 result=LoadTypeLib(libnam, &pTLib);
5266 SysFreeString(libnam);
5268 if(SUCCEEDED(result)) {
5269 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5270 ITypeLib2_AddRef(pTLib);
5274 if(SUCCEEDED(result)) {
5275 if(pRefType->index == TLB_REF_USE_GUID)
5276 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5277 &pRefType->guid,
5278 ppTInfo);
5279 else
5280 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5281 ppTInfo);
5283 if (pTLib != NULL)
5284 ITypeLib2_Release(pTLib);
5288 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5289 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5290 return result;
5293 /* ITypeInfo::AddressOfMember
5295 * Retrieves the addresses of static functions or variables, such as those
5296 * defined in a DLL.
5298 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5299 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5301 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5302 FIXME("(%p) stub!\n", This);
5303 return S_OK;
5306 /* ITypeInfo::CreateInstance
5308 * Creates a new instance of a type that describes a component object class
5309 * (coclass).
5311 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5312 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5314 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5315 FIXME("(%p) stub!\n", This);
5316 return S_OK;
5319 /* ITypeInfo::GetMops
5321 * Retrieves marshalling information.
5323 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5324 BSTR *pBstrMops)
5326 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5327 FIXME("(%p) stub!\n", This);
5328 return S_OK;
5331 /* ITypeInfo::GetContainingTypeLib
5333 * Retrieves the containing type library and the index of the type description
5334 * within that type library.
5336 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5337 ITypeLib * *ppTLib, UINT *pIndex)
5339 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5341 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5342 if (pIndex) {
5343 *pIndex=This->index;
5344 TRACE("returning pIndex=%d\n", *pIndex);
5347 if (ppTLib) {
5348 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5349 ITypeLib2_AddRef(*ppTLib);
5350 TRACE("returning ppTLib=%p\n", *ppTLib);
5353 return S_OK;
5356 /* ITypeInfo::ReleaseTypeAttr
5358 * Releases a TYPEATTR previously returned by GetTypeAttr.
5361 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5362 TYPEATTR* pTypeAttr)
5364 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5365 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5366 if(This->TypeAttr.typekind == TKIND_ALIAS)
5367 free_deep_typedesc(&pTypeAttr->tdescAlias);
5368 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5371 /* ITypeInfo::ReleaseFuncDesc
5373 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5375 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5376 ITypeInfo2 *iface,
5377 FUNCDESC *pFuncDesc)
5379 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5380 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5383 /* ITypeInfo::ReleaseVarDesc
5385 * Releases a VARDESC previously returned by GetVarDesc.
5387 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5388 VARDESC *pVarDesc)
5390 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5391 TRACE("(%p)->(%p)\n", This, pVarDesc);
5394 /* ITypeInfo2::GetTypeKind
5396 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5399 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5400 TYPEKIND *pTypeKind)
5402 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5403 *pTypeKind=This->TypeAttr.typekind;
5404 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5405 return S_OK;
5408 /* ITypeInfo2::GetTypeFlags
5410 * Returns the type flags without any allocations. This returns a DWORD type
5411 * flag, which expands the type flags without growing the TYPEATTR (type
5412 * attribute).
5415 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5417 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5418 *pTypeFlags=This->TypeAttr.wTypeFlags;
5419 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5420 return S_OK;
5423 /* ITypeInfo2::GetFuncIndexOfMemId
5424 * Binds to a specific member based on a known DISPID, where the member name
5425 * is not known (for example, when binding to a default member).
5428 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5429 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5431 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5432 TLBFuncDesc *pFuncInfo;
5433 int i;
5434 HRESULT result;
5436 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5437 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5438 break;
5439 if(pFuncInfo) {
5440 *pFuncIndex = i;
5441 result = S_OK;
5442 } else
5443 result = TYPE_E_ELEMENTNOTFOUND;
5445 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5446 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5447 return result;
5450 /* TypeInfo2::GetVarIndexOfMemId
5452 * Binds to a specific member based on a known DISPID, where the member name
5453 * is not known (for example, when binding to a default member).
5456 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5457 MEMBERID memid, UINT *pVarIndex)
5459 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5460 TLBVarDesc *pVarInfo;
5461 int i;
5462 HRESULT result;
5463 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5464 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5466 if(pVarInfo) {
5467 *pVarIndex = i;
5468 result = S_OK;
5469 } else
5470 result = TYPE_E_ELEMENTNOTFOUND;
5472 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5473 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5474 return result;
5477 /* ITypeInfo2::GetCustData
5479 * Gets the custom data
5481 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5482 ITypeInfo2 * iface,
5483 REFGUID guid,
5484 VARIANT *pVarVal)
5486 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5487 TLBCustData *pCData;
5489 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5490 if( IsEqualIID(guid, &pCData->guid)) break;
5492 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5494 if(pCData)
5496 VariantInit( pVarVal);
5497 VariantCopy( pVarVal, &pCData->data);
5498 return S_OK;
5500 return E_INVALIDARG; /* FIXME: correct? */
5503 /* ITypeInfo2::GetFuncCustData
5505 * Gets the custom data
5507 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5508 ITypeInfo2 * iface,
5509 UINT index,
5510 REFGUID guid,
5511 VARIANT *pVarVal)
5513 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5514 TLBCustData *pCData=NULL;
5515 TLBFuncDesc * pFDesc;
5516 int i;
5517 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5518 pFDesc=pFDesc->next);
5520 if(pFDesc)
5521 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5522 if( IsEqualIID(guid, &pCData->guid)) break;
5524 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5526 if(pCData){
5527 VariantInit( pVarVal);
5528 VariantCopy( pVarVal, &pCData->data);
5529 return S_OK;
5531 return E_INVALIDARG; /* FIXME: correct? */
5534 /* ITypeInfo2::GetParamCustData
5536 * Gets the custom data
5538 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5539 ITypeInfo2 * iface,
5540 UINT indexFunc,
5541 UINT indexParam,
5542 REFGUID guid,
5543 VARIANT *pVarVal)
5545 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5546 TLBCustData *pCData=NULL;
5547 TLBFuncDesc * pFDesc;
5548 int i;
5550 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5552 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5553 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5554 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)
5561 VariantInit( pVarVal);
5562 VariantCopy( pVarVal, &pCData->data);
5563 return S_OK;
5565 return E_INVALIDARG; /* FIXME: correct? */
5568 /* ITypeInfo2::GetVarCustData
5570 * Gets the custom data
5572 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5573 ITypeInfo2 * iface,
5574 UINT index,
5575 REFGUID guid,
5576 VARIANT *pVarVal)
5578 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5579 TLBCustData *pCData=NULL;
5580 TLBVarDesc * pVDesc;
5581 int i;
5583 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5585 if(pVDesc)
5587 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5589 if( IsEqualIID(guid, &pCData->guid)) break;
5593 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5595 if(pCData)
5597 VariantInit( pVarVal);
5598 VariantCopy( pVarVal, &pCData->data);
5599 return S_OK;
5601 return E_INVALIDARG; /* FIXME: correct? */
5604 /* ITypeInfo2::GetImplCustData
5606 * Gets the custom data
5608 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5609 ITypeInfo2 * iface,
5610 UINT index,
5611 REFGUID guid,
5612 VARIANT *pVarVal)
5614 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5615 TLBCustData *pCData=NULL;
5616 TLBImplType * pRDesc;
5617 int i;
5619 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5621 if(pRDesc)
5623 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5625 if( IsEqualIID(guid, &pCData->guid)) break;
5629 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5631 if(pCData)
5633 VariantInit( pVarVal);
5634 VariantCopy( pVarVal, &pCData->data);
5635 return S_OK;
5637 return E_INVALIDARG; /* FIXME: correct? */
5640 /* ITypeInfo2::GetDocumentation2
5642 * Retrieves the documentation string, the complete Help file name and path,
5643 * the localization context to use, and the context ID for the library Help
5644 * topic in the Help file.
5647 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5648 ITypeInfo2 * iface,
5649 MEMBERID memid,
5650 LCID lcid,
5651 BSTR *pbstrHelpString,
5652 DWORD *pdwHelpStringContext,
5653 BSTR *pbstrHelpStringDll)
5655 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5656 TLBFuncDesc * pFDesc;
5657 TLBVarDesc * pVDesc;
5658 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5659 "HelpStringContext(%p) HelpStringDll(%p)\n",
5660 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5661 pbstrHelpStringDll );
5662 /* the help string should be obtained from the helpstringdll,
5663 * using the _DLLGetDocumentation function, based on the supplied
5664 * lcid. Nice to do sometime...
5666 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5667 if(pbstrHelpString)
5668 *pbstrHelpString=SysAllocString(This->Name);
5669 if(pdwHelpStringContext)
5670 *pdwHelpStringContext=This->dwHelpStringContext;
5671 if(pbstrHelpStringDll)
5672 *pbstrHelpStringDll=
5673 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5674 return S_OK;
5675 }else {/* for a member */
5676 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5677 if(pFDesc->funcdesc.memid==memid){
5678 if(pbstrHelpString)
5679 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5680 if(pdwHelpStringContext)
5681 *pdwHelpStringContext=pFDesc->HelpStringContext;
5682 if(pbstrHelpStringDll)
5683 *pbstrHelpStringDll=
5684 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5685 return S_OK;
5687 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5688 if(pVDesc->vardesc.memid==memid){
5689 if(pbstrHelpString)
5690 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5691 if(pdwHelpStringContext)
5692 *pdwHelpStringContext=pVDesc->HelpStringContext;
5693 if(pbstrHelpStringDll)
5694 *pbstrHelpStringDll=
5695 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5696 return S_OK;
5699 return TYPE_E_ELEMENTNOTFOUND;
5702 /* ITypeInfo2::GetAllCustData
5704 * Gets all custom data items for the Type info.
5707 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5708 ITypeInfo2 * iface,
5709 CUSTDATA *pCustData)
5711 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5712 TLBCustData *pCData;
5713 int i;
5715 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5717 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5718 if(pCustData->prgCustData ){
5719 pCustData->cCustData=This->ctCustData;
5720 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5721 pCustData->prgCustData[i].guid=pCData->guid;
5722 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5724 }else{
5725 ERR(" OUT OF MEMORY! \n");
5726 return E_OUTOFMEMORY;
5728 return S_OK;
5731 /* ITypeInfo2::GetAllFuncCustData
5733 * Gets all custom data items for the specified Function
5736 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5737 ITypeInfo2 * iface,
5738 UINT index,
5739 CUSTDATA *pCustData)
5741 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5742 TLBCustData *pCData;
5743 TLBFuncDesc * pFDesc;
5744 int i;
5745 TRACE("(%p) index %d\n", This, index);
5746 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5747 pFDesc=pFDesc->next)
5749 if(pFDesc){
5750 pCustData->prgCustData =
5751 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5752 if(pCustData->prgCustData ){
5753 pCustData->cCustData=pFDesc->ctCustData;
5754 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5755 pCData = pCData->next){
5756 pCustData->prgCustData[i].guid=pCData->guid;
5757 VariantCopy(& pCustData->prgCustData[i].varValue,
5758 & pCData->data);
5760 }else{
5761 ERR(" OUT OF MEMORY! \n");
5762 return E_OUTOFMEMORY;
5764 return S_OK;
5766 return TYPE_E_ELEMENTNOTFOUND;
5769 /* ITypeInfo2::GetAllParamCustData
5771 * Gets all custom data items for the Functions
5774 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5775 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5777 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5778 TLBCustData *pCData=NULL;
5779 TLBFuncDesc * pFDesc;
5780 int i;
5781 TRACE("(%p) index %d\n", This, indexFunc);
5782 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5783 pFDesc=pFDesc->next)
5785 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5786 pCustData->prgCustData =
5787 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5788 sizeof(CUSTDATAITEM));
5789 if(pCustData->prgCustData ){
5790 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5791 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5792 pCData; i++, pCData = pCData->next){
5793 pCustData->prgCustData[i].guid=pCData->guid;
5794 VariantCopy(& pCustData->prgCustData[i].varValue,
5795 & pCData->data);
5797 }else{
5798 ERR(" OUT OF MEMORY! \n");
5799 return E_OUTOFMEMORY;
5801 return S_OK;
5803 return TYPE_E_ELEMENTNOTFOUND;
5806 /* ITypeInfo2::GetAllVarCustData
5808 * Gets all custom data items for the specified Variable
5811 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5812 UINT index, CUSTDATA *pCustData)
5814 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5815 TLBCustData *pCData;
5816 TLBVarDesc * pVDesc;
5817 int i;
5818 TRACE("(%p) index %d\n", This, index);
5819 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5820 pVDesc=pVDesc->next)
5822 if(pVDesc){
5823 pCustData->prgCustData =
5824 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5825 if(pCustData->prgCustData ){
5826 pCustData->cCustData=pVDesc->ctCustData;
5827 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5828 pCData = pCData->next){
5829 pCustData->prgCustData[i].guid=pCData->guid;
5830 VariantCopy(& pCustData->prgCustData[i].varValue,
5831 & pCData->data);
5833 }else{
5834 ERR(" OUT OF MEMORY! \n");
5835 return E_OUTOFMEMORY;
5837 return S_OK;
5839 return TYPE_E_ELEMENTNOTFOUND;
5842 /* ITypeInfo2::GetAllImplCustData
5844 * Gets all custom data items for the specified implementation type
5847 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5848 ITypeInfo2 * iface,
5849 UINT index,
5850 CUSTDATA *pCustData)
5852 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5853 TLBCustData *pCData;
5854 TLBImplType * pRDesc;
5855 int i;
5856 TRACE("(%p) index %d\n", This, index);
5857 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5858 pRDesc=pRDesc->next)
5860 if(pRDesc){
5861 pCustData->prgCustData =
5862 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5863 if(pCustData->prgCustData ){
5864 pCustData->cCustData=pRDesc->ctCustData;
5865 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5866 pCData = pCData->next){
5867 pCustData->prgCustData[i].guid=pCData->guid;
5868 VariantCopy(& pCustData->prgCustData[i].varValue,
5869 & pCData->data);
5871 }else{
5872 ERR(" OUT OF MEMORY! \n");
5873 return E_OUTOFMEMORY;
5875 return S_OK;
5877 return TYPE_E_ELEMENTNOTFOUND;
5880 static const ITypeInfo2Vtbl tinfvt =
5883 ITypeInfo_fnQueryInterface,
5884 ITypeInfo_fnAddRef,
5885 ITypeInfo_fnRelease,
5887 ITypeInfo_fnGetTypeAttr,
5888 ITypeInfo_fnGetTypeComp,
5889 ITypeInfo_fnGetFuncDesc,
5890 ITypeInfo_fnGetVarDesc,
5891 ITypeInfo_fnGetNames,
5892 ITypeInfo_fnGetRefTypeOfImplType,
5893 ITypeInfo_fnGetImplTypeFlags,
5894 ITypeInfo_fnGetIDsOfNames,
5895 ITypeInfo_fnInvoke,
5896 ITypeInfo_fnGetDocumentation,
5897 ITypeInfo_fnGetDllEntry,
5898 ITypeInfo_fnGetRefTypeInfo,
5899 ITypeInfo_fnAddressOfMember,
5900 ITypeInfo_fnCreateInstance,
5901 ITypeInfo_fnGetMops,
5902 ITypeInfo_fnGetContainingTypeLib,
5903 ITypeInfo_fnReleaseTypeAttr,
5904 ITypeInfo_fnReleaseFuncDesc,
5905 ITypeInfo_fnReleaseVarDesc,
5907 ITypeInfo2_fnGetTypeKind,
5908 ITypeInfo2_fnGetTypeFlags,
5909 ITypeInfo2_fnGetFuncIndexOfMemId,
5910 ITypeInfo2_fnGetVarIndexOfMemId,
5911 ITypeInfo2_fnGetCustData,
5912 ITypeInfo2_fnGetFuncCustData,
5913 ITypeInfo2_fnGetParamCustData,
5914 ITypeInfo2_fnGetVarCustData,
5915 ITypeInfo2_fnGetImplTypeCustData,
5916 ITypeInfo2_fnGetDocumentation2,
5917 ITypeInfo2_fnGetAllCustData,
5918 ITypeInfo2_fnGetAllFuncCustData,
5919 ITypeInfo2_fnGetAllParamCustData,
5920 ITypeInfo2_fnGetAllVarCustData,
5921 ITypeInfo2_fnGetAllImplTypeCustData,
5924 /******************************************************************************
5925 * CreateDispTypeInfo [OLEAUT32.31]
5927 * Build type information for an object so it can be called through an
5928 * IDispatch interface.
5930 * RETURNS
5931 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5932 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5934 * NOTES
5935 * This call allows an objects methods to be accessed through IDispatch, by
5936 * building an ITypeInfo object that IDispatch can use to call through.
5938 HRESULT WINAPI CreateDispTypeInfo(
5939 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5940 LCID lcid, /* [I] Locale Id */
5941 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5943 ITypeInfoImpl *pTIImpl;
5944 int param, func;
5945 TLBFuncDesc **ppFuncDesc;
5947 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5948 pTIImpl->pTypeLib = NULL;
5949 pTIImpl->index = 0;
5950 pTIImpl->Name = NULL;
5951 pTIImpl->dwHelpContext = -1;
5952 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
5953 pTIImpl->TypeAttr.lcid = lcid;
5954 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
5955 pTIImpl->TypeAttr.wMajorVerNum = 0;
5956 pTIImpl->TypeAttr.wMinorVerNum = 0;
5957 pTIImpl->TypeAttr.cbAlignment = 2;
5958 pTIImpl->TypeAttr.cbSizeInstance = -1;
5959 pTIImpl->TypeAttr.cbSizeVft = -1;
5960 pTIImpl->TypeAttr.cFuncs = 0;
5961 pTIImpl->TypeAttr.cImplTypes = 1;
5962 pTIImpl->TypeAttr.cVars = 0;
5963 pTIImpl->TypeAttr.wTypeFlags = 0;
5965 ppFuncDesc = &pTIImpl->funclist;
5966 for(func = 0; func < pidata->cMembers; func++) {
5967 METHODDATA *md = pidata->pmethdata + func;
5968 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
5969 (*ppFuncDesc)->Name = SysAllocString(md->szName);
5970 (*ppFuncDesc)->funcdesc.memid = md->dispid;
5971 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
5972 (*ppFuncDesc)->funcdesc.callconv = md->cc;
5973 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
5974 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
5975 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
5976 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
5977 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
5978 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5979 md->cArgs * sizeof(ELEMDESC));
5980 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5981 md->cArgs * sizeof(TLBParDesc));
5982 for(param = 0; param < md->cArgs; param++) {
5983 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
5984 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
5986 ppFuncDesc = &(*ppFuncDesc)->next;
5988 *pptinfo = (ITypeInfo*)pTIImpl;
5989 return S_OK;
5993 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5995 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
5997 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6000 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6002 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6004 return ITypeInfo_AddRef((ITypeInfo *)This);
6007 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6009 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6011 return ITypeInfo_Release((ITypeInfo *)This);
6014 static HRESULT WINAPI ITypeComp_fnBind(
6015 ITypeComp * iface,
6016 OLECHAR * szName,
6017 ULONG lHash,
6018 WORD wFlags,
6019 ITypeInfo ** ppTInfo,
6020 DESCKIND * pDescKind,
6021 BINDPTR * pBindPtr)
6023 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6024 TLBFuncDesc * pFDesc;
6025 TLBVarDesc * pVDesc;
6027 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6029 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6030 if (pFDesc->funcdesc.invkind & wFlags)
6031 if (!strcmpW(pFDesc->Name, szName)) {
6032 break;
6035 if (pFDesc)
6037 *pDescKind = DESCKIND_FUNCDESC;
6038 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
6039 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6040 return S_OK;
6041 } else {
6042 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
6044 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6045 if (!strcmpW(pVDesc->Name, szName)) {
6046 *pDescKind = DESCKIND_VARDESC;
6047 pBindPtr->lpvardesc = &pVDesc->vardesc;
6048 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6049 return S_OK;
6054 /* not found, look for it in inherited interfaces */
6055 if (This->TypeAttr.cImplTypes &&
6056 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
6057 /* recursive search */
6058 ITypeInfo *pTInfo;
6059 ITypeComp *pTComp;
6060 HRESULT hr;
6061 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6062 if (SUCCEEDED(hr))
6064 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6065 ITypeInfo_Release(pTInfo);
6067 if (SUCCEEDED(hr))
6069 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6070 ITypeComp_Release(pTComp);
6071 return hr;
6073 WARN("Could not search inherited interface!\n");
6075 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6076 *pDescKind = DESCKIND_NONE;
6077 pBindPtr->lpfuncdesc = NULL;
6078 *ppTInfo = NULL;
6079 return DISP_E_MEMBERNOTFOUND;
6082 static HRESULT WINAPI ITypeComp_fnBindType(
6083 ITypeComp * iface,
6084 OLECHAR * szName,
6085 ULONG lHash,
6086 ITypeInfo ** ppTInfo,
6087 ITypeComp ** ppTComp)
6089 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6091 /* strange behaviour (does nothing) but like the
6092 * original */
6094 if (!ppTInfo || !ppTComp)
6095 return E_POINTER;
6097 *ppTInfo = NULL;
6098 *ppTComp = NULL;
6100 return S_OK;
6103 static const ITypeCompVtbl tcompvt =
6106 ITypeComp_fnQueryInterface,
6107 ITypeComp_fnAddRef,
6108 ITypeComp_fnRelease,
6110 ITypeComp_fnBind,
6111 ITypeComp_fnBindType