kernel32: The Isle of Man uses the Manx Pound.
[wine/hacks.git] / dlls / oleaut32 / typelib.c
blob5792cc5187044c252c5679b6701e6a09bd1f5590
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
48 #include "config.h"
49 #include "wine/port.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
67 #include "lzexpand.h"
69 #include "wine/unicode.h"
70 #include "objbase.h"
71 #include "typelib.h"
72 #include "wine/debug.h"
73 #include "variant.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 typedef struct
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
89 typedef struct
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
95 * Name info array.
97 } NE_TYPEINFO;
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
102 /****************************************************************************
103 * FromLExxx
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
116 static DWORD FromLEDWord(DWORD p_iVal)
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
123 #else
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
126 #endif
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
132 * FromLExxx
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
139 WORD *Val = p_Val;
141 p_iSize /= sizeof(WORD);
143 while (p_iSize) {
144 *Val = FromLEWord(*Val);
145 Val++;
146 p_iSize--;
151 static void FromLEDWords(void *p_Val, int p_iSize)
153 DWORD *Val = p_Val;
155 p_iSize /= sizeof(DWORD);
157 while (p_iSize) {
158 *Val = FromLEDWord(*Val);
159 Val++;
160 p_iSize--;
163 #else
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
166 #endif
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
174 WCHAR buffer[60];
175 char key_name[16];
176 DWORD len, i;
177 INT best_maj = -1, best_min = -1;
178 HKEY hkey;
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 INT v_maj, v_min;
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
203 best_maj = v_maj;
205 if (*wMin == v_min)
207 best_min = v_min;
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
215 RegCloseKey( hkey );
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
223 *wMaj = best_maj;
224 *wMin = best_min;
225 return TRUE;
229 if (*wMaj == best_maj && best_min >= 0)
231 *wMin = best_min;
232 return TRUE;
234 return FALSE;
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
244 memcpy( buffer, TypelibW, sizeof(TypelibW) );
245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
247 return buffer;
250 /* get the path of an interface key, in the form "Interface\\<guid>" */
251 /* buffer must be at least 50 characters long */
252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
258 return buffer;
261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
262 /* buffer must be at least 16 characters long */
263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
266 static const WCHAR win16W[] = {'w','i','n','1','6',0};
267 static const WCHAR win32W[] = {'w','i','n','3','2',0};
268 static const WCHAR win64W[] = {'w','i','n','6','4',0};
270 sprintfW( buffer, LcidFormatW, lcid );
271 switch(syskind)
273 case SYS_WIN16: strcatW( buffer, win16W ); break;
274 case SYS_WIN32: strcatW( buffer, win32W ); break;
275 case SYS_WIN64: strcatW( buffer, win64W ); break;
276 default:
277 TRACE("Typelib is for unsupported syskind %i\n", syskind);
278 return NULL;
280 return buffer;
283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
286 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
287 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
288 SYSKIND syskind, LCID lcid, LPBSTR path )
290 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
291 LCID myLCID = lcid;
292 HKEY hkey;
293 WCHAR buffer[60];
294 WCHAR Path[MAX_PATH];
295 LONG res;
297 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
299 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
300 get_typelib_key( guid, wMaj, wMin, buffer );
302 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
303 if (res == ERROR_FILE_NOT_FOUND)
305 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
306 return TYPE_E_LIBNOTREGISTERED;
308 else if (res != ERROR_SUCCESS)
310 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
311 return TYPE_E_REGISTRYACCESS;
314 while (hr != S_OK)
316 LONG dwPathLen = sizeof(Path);
318 get_lcid_subkey( myLCID, syskind, buffer );
320 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
322 if (!lcid)
323 break;
324 else if (myLCID == lcid)
326 /* try with sub-langid */
327 myLCID = SUBLANGID(lcid);
329 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
331 /* try with system langid */
332 myLCID = 0;
334 else
336 break;
339 else
341 *path = SysAllocString( Path );
342 hr = S_OK;
345 RegCloseKey( hkey );
346 TRACE_(typelib)("-- 0x%08x\n", hr);
347 return hr;
350 /****************************************************************************
351 * QueryPathOfRegTypeLib [OLEAUT32.164]
353 * Gets the path to a registered type library.
355 * PARAMS
356 * guid [I] referenced guid
357 * wMaj [I] major version
358 * wMin [I] minor version
359 * lcid [I] locale id
360 * path [O] path of typelib
362 * RETURNS
363 * Success: S_OK.
364 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
365 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
366 * opened.
368 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
370 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
373 /******************************************************************************
374 * CreateTypeLib [OLEAUT32.160] creates a typelib
376 * RETURNS
377 * Success: S_OK
378 * Failure: Status
380 HRESULT WINAPI CreateTypeLib(
381 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
383 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
384 return E_FAIL;
387 /******************************************************************************
388 * LoadTypeLib [OLEAUT32.161]
390 * Loads a type library
392 * PARAMS
393 * szFile [I] Name of file to load from.
394 * pptLib [O] Pointer that receives ITypeLib object on success.
396 * RETURNS
397 * Success: S_OK
398 * Failure: Status
400 * SEE
401 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
403 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
405 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
406 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
409 /******************************************************************************
410 * LoadTypeLibEx [OLEAUT32.183]
412 * Loads and optionally registers a type library
414 * RETURNS
415 * Success: S_OK
416 * Failure: Status
418 HRESULT WINAPI LoadTypeLibEx(
419 LPCOLESTR szFile, /* [in] Name of file to load from */
420 REGKIND regkind, /* [in] Specify kind of registration */
421 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
423 WCHAR szPath[MAX_PATH+1];
424 HRESULT res;
426 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
428 *pptLib = NULL;
430 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
432 if (SUCCEEDED(res))
433 switch(regkind)
435 case REGKIND_DEFAULT:
436 /* don't register typelibs supplied with full path. Experimentation confirms the following */
437 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
438 (szFile[0] && (szFile[1] == ':'))) break;
439 /* else fall-through */
441 case REGKIND_REGISTER:
442 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
444 IUnknown_Release(*pptLib);
445 *pptLib = 0;
447 break;
448 case REGKIND_NONE:
449 break;
452 TRACE(" returns %08x\n",res);
453 return res;
456 /******************************************************************************
457 * LoadRegTypeLib [OLEAUT32.162]
459 * Loads a registered type library.
461 * PARAMS
462 * rguid [I] GUID of the registered type library.
463 * wVerMajor [I] major version.
464 * wVerMinor [I] minor version.
465 * lcid [I] locale ID.
466 * ppTLib [O] pointer that receives an ITypeLib object on success.
468 * RETURNS
469 * Success: S_OK.
470 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
471 * LoadTypeLib.
473 HRESULT WINAPI LoadRegTypeLib(
474 REFGUID rguid,
475 WORD wVerMajor,
476 WORD wVerMinor,
477 LCID lcid,
478 ITypeLib **ppTLib)
480 BSTR bstr=NULL;
481 HRESULT res;
483 *ppTLib = NULL;
485 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
487 if(SUCCEEDED(res))
489 res= LoadTypeLib(bstr, ppTLib);
490 SysFreeString(bstr);
493 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
495 return res;
499 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
500 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
501 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
502 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
503 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
504 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
506 /******************************************************************************
507 * RegisterTypeLib [OLEAUT32.163]
508 * Adds information about a type library to the System Registry
509 * NOTES
510 * Docs: ITypeLib FAR * ptlib
511 * Docs: OLECHAR FAR* szFullPath
512 * Docs: OLECHAR FAR* szHelpDir
514 * RETURNS
515 * Success: S_OK
516 * Failure: Status
518 HRESULT WINAPI RegisterTypeLib(
519 ITypeLib * ptlib, /* [in] Pointer to the library*/
520 OLECHAR * szFullPath, /* [in] full Path of the library*/
521 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
522 may be NULL*/
524 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
525 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
526 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
527 HRESULT res;
528 TLIBATTR *attr;
529 WCHAR keyName[60];
530 WCHAR tmp[16];
531 HKEY key, subKey;
532 UINT types, tidx;
533 TYPEKIND kind;
534 DWORD disposition;
536 if (ptlib == NULL || szFullPath == NULL)
537 return E_INVALIDARG;
539 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
540 return E_FAIL;
542 #ifdef _WIN64
543 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
544 #else
545 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
546 #endif
548 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
550 res = S_OK;
551 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
552 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
554 LPOLESTR doc;
556 /* Set the human-readable name of the typelib */
557 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
558 res = E_FAIL;
559 else if (doc)
561 if (RegSetValueExW(key, NULL, 0, REG_SZ,
562 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
563 res = E_FAIL;
565 SysFreeString(doc);
568 /* Make up the name of the typelib path subkey */
569 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
571 /* Create the typelib path subkey */
572 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
573 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
575 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
576 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
577 res = E_FAIL;
579 RegCloseKey(subKey);
581 else
582 res = E_FAIL;
584 /* Create the flags subkey */
585 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
586 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
588 /* FIXME: is %u correct? */
589 static const WCHAR formatW[] = {'%','u',0};
590 WCHAR buf[20];
591 sprintfW(buf, formatW, attr->wLibFlags);
592 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
593 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
594 res = E_FAIL;
596 RegCloseKey(subKey);
598 else
599 res = E_FAIL;
601 /* create the helpdir subkey */
602 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
603 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
605 BOOL freeHelpDir = FALSE;
606 OLECHAR* pIndexStr;
608 /* if we created a new key, and helpDir was null, set the helpdir
609 to the directory which contains the typelib. However,
610 if we just opened an existing key, we leave the helpdir alone */
611 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
612 szHelpDir = SysAllocString(szFullPath);
613 pIndexStr = strrchrW(szHelpDir, '\\');
614 if (pIndexStr) {
615 *pIndexStr = 0;
617 freeHelpDir = TRUE;
620 /* if we have an szHelpDir, set it! */
621 if (szHelpDir != NULL) {
622 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
623 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
624 res = E_FAIL;
628 /* tidy up */
629 if (freeHelpDir) SysFreeString(szHelpDir);
630 RegCloseKey(subKey);
632 } else {
633 res = E_FAIL;
636 RegCloseKey(key);
638 else
639 res = E_FAIL;
641 /* register OLE Automation-compatible interfaces for this typelib */
642 types = ITypeLib_GetTypeInfoCount(ptlib);
643 for (tidx=0; tidx<types; tidx++) {
644 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
645 LPOLESTR name = NULL;
646 ITypeInfo *tinfo = NULL;
648 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
650 switch (kind) {
651 case TKIND_INTERFACE:
652 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
653 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
654 break;
656 case TKIND_DISPATCH:
657 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
658 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
659 break;
661 default:
662 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
663 break;
666 if (tinfo) {
667 TYPEATTR *tattr = NULL;
668 ITypeInfo_GetTypeAttr(tinfo, &tattr);
670 if (tattr) {
671 TRACE_(typelib)("guid=%s, flags=%04x (",
672 debugstr_guid(&tattr->guid),
673 tattr->wTypeFlags);
675 if (TRACE_ON(typelib)) {
676 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
677 XX(FAPPOBJECT);
678 XX(FCANCREATE);
679 XX(FLICENSED);
680 XX(FPREDECLID);
681 XX(FHIDDEN);
682 XX(FCONTROL);
683 XX(FDUAL);
684 XX(FNONEXTENSIBLE);
685 XX(FOLEAUTOMATION);
686 XX(FRESTRICTED);
687 XX(FAGGREGATABLE);
688 XX(FREPLACEABLE);
689 XX(FDISPATCHABLE);
690 XX(FREVERSEBIND);
691 XX(FPROXY);
692 #undef XX
693 MESSAGE("\n");
696 /* Register all dispinterfaces (which includes dual interfaces) and
697 oleautomation interfaces */
698 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
699 kind == TKIND_DISPATCH)
701 /* register interface<->typelib coupling */
702 get_interface_key( &tattr->guid, keyName );
703 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
704 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
706 if (name)
707 RegSetValueExW(key, NULL, 0, REG_SZ,
708 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
710 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
711 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
712 RegSetValueExW(subKey, NULL, 0, REG_SZ,
713 (const BYTE *)PSOA, sizeof PSOA);
714 RegCloseKey(subKey);
717 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
718 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
719 RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (const BYTE *)PSOA, sizeof PSOA);
721 RegCloseKey(subKey);
724 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
725 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
727 WCHAR buffer[40];
728 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
729 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
731 StringFromGUID2(&attr->guid, buffer, 40);
732 RegSetValueExW(subKey, NULL, 0, REG_SZ,
733 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
734 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
735 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
736 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
737 RegCloseKey(subKey);
740 RegCloseKey(key);
744 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
747 ITypeInfo_Release(tinfo);
750 SysFreeString(name);
754 ITypeLib_ReleaseTLibAttr(ptlib, attr);
756 return res;
760 /******************************************************************************
761 * UnRegisterTypeLib [OLEAUT32.186]
762 * Removes information about a type library from the System Registry
763 * NOTES
765 * RETURNS
766 * Success: S_OK
767 * Failure: Status
769 HRESULT WINAPI UnRegisterTypeLib(
770 REFGUID libid, /* [in] Guid of the library */
771 WORD wVerMajor, /* [in] major version */
772 WORD wVerMinor, /* [in] minor version */
773 LCID lcid, /* [in] locale id */
774 SYSKIND syskind)
776 BSTR tlibPath = NULL;
777 DWORD tmpLength;
778 WCHAR keyName[60];
779 WCHAR subKeyName[50];
780 int result = S_OK;
781 DWORD i = 0;
782 BOOL deleteOtherStuff;
783 HKEY key = NULL;
784 HKEY subKey = NULL;
785 TYPEATTR* typeAttr = NULL;
786 TYPEKIND kind;
787 ITypeInfo* typeInfo = NULL;
788 ITypeLib* typeLib = NULL;
789 int numTypes;
791 TRACE("(IID: %s)\n",debugstr_guid(libid));
793 /* Create the path to the key */
794 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
796 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
798 TRACE("Unsupported syskind %i\n", syskind);
799 result = E_INVALIDARG;
800 goto end;
803 /* get the path to the typelib on disk */
804 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
805 result = E_INVALIDARG;
806 goto end;
809 /* Try and open the key to the type library. */
810 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
811 result = E_INVALIDARG;
812 goto end;
815 /* Try and load the type library */
816 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
817 result = TYPE_E_INVALIDSTATE;
818 goto end;
821 /* remove any types registered with this typelib */
822 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
823 for (i=0; i<numTypes; i++) {
824 /* get the kind of type */
825 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
826 goto enddeleteloop;
829 /* skip non-interfaces, and get type info for the type */
830 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
831 goto enddeleteloop;
833 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
834 goto enddeleteloop;
836 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
837 goto enddeleteloop;
840 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
841 kind == TKIND_DISPATCH)
843 /* the path to the type */
844 get_interface_key( &typeAttr->guid, subKeyName );
846 /* Delete its bits */
847 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
848 goto enddeleteloop;
850 RegDeleteKeyW(subKey, ProxyStubClsidW);
851 RegDeleteKeyW(subKey, ProxyStubClsid32W);
852 RegDeleteKeyW(subKey, TypeLibW);
853 RegCloseKey(subKey);
854 subKey = NULL;
855 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
858 enddeleteloop:
859 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
860 typeAttr = NULL;
861 if (typeInfo) ITypeInfo_Release(typeInfo);
862 typeInfo = NULL;
865 /* Now, delete the type library path subkey */
866 get_lcid_subkey( lcid, syskind, subKeyName );
867 RegDeleteKeyW(key, subKeyName);
868 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
869 RegDeleteKeyW(key, subKeyName);
871 /* check if there is anything besides the FLAGS/HELPDIR keys.
872 If there is, we don't delete them */
873 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
874 deleteOtherStuff = TRUE;
875 i = 0;
876 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
877 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
879 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
880 if (!strcmpW(subKeyName, FLAGSW)) continue;
881 if (!strcmpW(subKeyName, HELPDIRW)) continue;
882 deleteOtherStuff = FALSE;
883 break;
886 /* only delete the other parts of the key if we're absolutely sure */
887 if (deleteOtherStuff) {
888 RegDeleteKeyW(key, FLAGSW);
889 RegDeleteKeyW(key, HELPDIRW);
890 RegCloseKey(key);
891 key = NULL;
893 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
894 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
895 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
898 end:
899 SysFreeString(tlibPath);
900 if (typeLib) ITypeLib_Release(typeLib);
901 if (subKey) RegCloseKey(subKey);
902 if (key) RegCloseKey(key);
903 return result;
906 /*======================= ITypeLib implementation =======================*/
908 typedef struct tagTLBCustData
910 GUID guid;
911 VARIANT data;
912 struct tagTLBCustData* next;
913 } TLBCustData;
915 /* data structure for import typelibs */
916 typedef struct tagTLBImpLib
918 int offset; /* offset in the file (MSFT)
919 offset in nametable (SLTG)
920 just used to identify library while reading
921 data from file */
922 GUID guid; /* libid */
923 BSTR name; /* name */
925 LCID lcid; /* lcid of imported typelib */
927 WORD wVersionMajor; /* major version number */
928 WORD wVersionMinor; /* minor version number */
930 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
931 NULL if not yet loaded */
932 struct tagTLBImpLib * next;
933 } TLBImpLib;
935 /* internal ITypeLib data */
936 typedef struct tagITypeLibImpl
938 const ITypeLib2Vtbl *lpVtbl;
939 const ITypeCompVtbl *lpVtblTypeComp;
940 LONG ref;
941 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
942 LCID lcid;
944 /* strings can be stored in tlb as multibyte strings BUT they are *always*
945 * exported to the application as a UNICODE string.
947 BSTR Name;
948 BSTR DocString;
949 BSTR HelpFile;
950 BSTR HelpStringDll;
951 DWORD dwHelpContext;
952 int TypeInfoCount; /* nr of typeinfo's in librarry */
953 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
954 int ctCustData; /* number of items in cust data list */
955 TLBCustData * pCustData; /* linked list to cust data */
956 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
957 int ctTypeDesc; /* number of items in type desc array */
958 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
959 library. Only used while reading MSFT
960 typelibs */
961 struct list ref_list; /* list of ref types in this typelib */
962 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
965 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
966 struct tagITypeLibImpl *next, *prev;
967 WCHAR *path;
968 INT index;
969 } ITypeLibImpl;
971 static const ITypeLib2Vtbl tlbvt;
972 static const ITypeCompVtbl tlbtcvt;
974 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
976 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
979 /* ITypeLib methods */
980 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
981 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
983 /*======================= ITypeInfo implementation =======================*/
985 /* data for referenced types */
986 typedef struct tagTLBRefType
988 INT index; /* Type index for internal ref or for external ref
989 it the format is SLTG. -2 indicates to
990 use guid */
992 GUID guid; /* guid of the referenced type */
993 /* if index == TLB_REF_USE_GUID */
995 HREFTYPE reference; /* The href of this ref */
996 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
997 TLB_REF_INTERNAL for internal refs
998 TLB_REF_NOT_FOUND for broken refs */
1000 struct list entry;
1001 } TLBRefType;
1003 #define TLB_REF_USE_GUID -2
1005 #define TLB_REF_INTERNAL (void*)-2
1006 #define TLB_REF_NOT_FOUND (void*)-1
1008 /* internal Parameter data */
1009 typedef struct tagTLBParDesc
1011 BSTR Name;
1012 int ctCustData;
1013 TLBCustData * pCustData; /* linked list to cust data */
1014 } TLBParDesc;
1016 /* internal Function data */
1017 typedef struct tagTLBFuncDesc
1019 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1020 BSTR Name; /* the name of this function */
1021 TLBParDesc *pParamDesc; /* array with param names and custom data */
1022 int helpcontext;
1023 int HelpStringContext;
1024 BSTR HelpString;
1025 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1026 int ctCustData;
1027 TLBCustData * pCustData; /* linked list to cust data; */
1028 struct tagTLBFuncDesc * next;
1029 } TLBFuncDesc;
1031 /* internal Variable data */
1032 typedef struct tagTLBVarDesc
1034 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1035 BSTR Name; /* the name of this variable */
1036 int HelpContext;
1037 int HelpStringContext; /* FIXME: where? */
1038 BSTR HelpString;
1039 int ctCustData;
1040 TLBCustData * pCustData;/* linked list to cust data; */
1041 struct tagTLBVarDesc * next;
1042 } TLBVarDesc;
1044 /* internal implemented interface data */
1045 typedef struct tagTLBImplType
1047 HREFTYPE hRef; /* hRef of interface */
1048 int implflags; /* IMPLFLAG_*s */
1049 int ctCustData;
1050 TLBCustData * pCustData;/* linked list to custom data; */
1051 struct tagTLBImplType *next;
1052 } TLBImplType;
1054 /* internal TypeInfo data */
1055 typedef struct tagITypeInfoImpl
1057 const ITypeInfo2Vtbl *lpVtbl;
1058 const ITypeCompVtbl *lpVtblTypeComp;
1059 LONG ref;
1060 BOOL not_attached_to_typelib;
1061 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1062 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1063 int index; /* index in this typelib; */
1064 HREFTYPE hreftype; /* hreftype for app object binding */
1065 /* type libs seem to store the doc strings in ascii
1066 * so why should we do it in unicode?
1068 BSTR Name;
1069 BSTR DocString;
1070 BSTR DllName;
1071 DWORD dwHelpContext;
1072 DWORD dwHelpStringContext;
1074 /* functions */
1075 TLBFuncDesc * funclist; /* linked list with function descriptions */
1077 /* variables */
1078 TLBVarDesc * varlist; /* linked list with variable descriptions */
1080 /* Implemented Interfaces */
1081 TLBImplType * impltypelist;
1083 int ctCustData;
1084 TLBCustData * pCustData; /* linked list to cust data; */
1085 struct tagITypeInfoImpl * next;
1086 } ITypeInfoImpl;
1088 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1090 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1093 static const ITypeInfo2Vtbl tinfvt;
1094 static const ITypeCompVtbl tcompvt;
1096 static ITypeInfo2 * ITypeInfo_Constructor(void);
1097 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This);
1099 typedef struct tagTLBContext
1101 unsigned int oStart; /* start of TLB in file */
1102 unsigned int pos; /* current pos */
1103 unsigned int length; /* total length */
1104 void *mapping; /* memory mapping */
1105 MSFT_SegDir * pTblDir;
1106 ITypeLibImpl* pLibInfo;
1107 } TLBContext;
1110 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1113 debug
1115 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1116 if (pTD->vt & VT_RESERVED)
1117 szVarType += strlen(strcpy(szVarType, "reserved | "));
1118 if (pTD->vt & VT_BYREF)
1119 szVarType += strlen(strcpy(szVarType, "ref to "));
1120 if (pTD->vt & VT_ARRAY)
1121 szVarType += strlen(strcpy(szVarType, "array of "));
1122 if (pTD->vt & VT_VECTOR)
1123 szVarType += strlen(strcpy(szVarType, "vector of "));
1124 switch(pTD->vt & VT_TYPEMASK) {
1125 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1126 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1127 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1128 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1129 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1130 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1131 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1132 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1133 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1134 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1135 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1136 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1137 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1138 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1139 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1140 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1141 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1142 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1143 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1144 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1145 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1146 pTD->u.hreftype); break;
1147 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1148 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1149 case VT_PTR: sprintf(szVarType, "ptr to ");
1150 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1151 break;
1152 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1153 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1154 break;
1155 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1156 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1157 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1158 break;
1160 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1164 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1165 char buf[200];
1166 USHORT flags = edesc->u.paramdesc.wParamFlags;
1167 dump_TypeDesc(&edesc->tdesc,buf);
1168 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1169 MESSAGE("\t\tu.paramdesc.wParamFlags");
1170 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1171 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1172 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1173 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1174 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1175 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1176 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1177 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1178 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1180 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1181 int i;
1182 MESSAGE("memid is %08x\n",funcdesc->memid);
1183 for (i=0;i<funcdesc->cParams;i++) {
1184 MESSAGE("Param %d:\n",i);
1185 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1187 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1188 switch (funcdesc->funckind) {
1189 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1190 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1191 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1192 case FUNC_STATIC: MESSAGE("static");break;
1193 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1194 default: MESSAGE("unknown");break;
1196 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1197 switch (funcdesc->invkind) {
1198 case INVOKE_FUNC: MESSAGE("func");break;
1199 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1200 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1201 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1203 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1204 switch (funcdesc->callconv) {
1205 case CC_CDECL: MESSAGE("cdecl");break;
1206 case CC_PASCAL: MESSAGE("pascal");break;
1207 case CC_STDCALL: MESSAGE("stdcall");break;
1208 case CC_SYSCALL: MESSAGE("syscall");break;
1209 default:break;
1211 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1212 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1213 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1215 MESSAGE("\telemdescFunc (return value type):\n");
1216 dump_ELEMDESC(&funcdesc->elemdescFunc);
1219 static const char * const typekind_desc[] =
1221 "TKIND_ENUM",
1222 "TKIND_RECORD",
1223 "TKIND_MODULE",
1224 "TKIND_INTERFACE",
1225 "TKIND_DISPATCH",
1226 "TKIND_COCLASS",
1227 "TKIND_ALIAS",
1228 "TKIND_UNION",
1229 "TKIND_MAX"
1232 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1234 int i;
1235 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1236 for (i=0;i<pfd->funcdesc.cParams;i++)
1237 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1240 dump_FUNCDESC(&(pfd->funcdesc));
1242 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1243 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1245 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1247 while (pfd)
1249 dump_TLBFuncDescOne(pfd);
1250 pfd = pfd->next;
1253 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1255 while (pvd)
1257 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1258 pvd = pvd->next;
1262 static void dump_TLBImpLib(const TLBImpLib *import)
1264 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1265 debugstr_w(import->name));
1266 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1267 import->wVersionMinor, import->lcid, import->offset);
1270 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1272 TLBRefType *ref;
1274 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1276 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1277 if(ref->index == -1)
1278 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1279 else
1280 TRACE_(typelib)("type no: %d\n", ref->index);
1282 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1284 TRACE_(typelib)("in lib\n");
1285 dump_TLBImpLib(ref->pImpTLInfo);
1290 static void dump_TLBImplType(const TLBImplType * impl)
1292 while (impl) {
1293 TRACE_(typelib)(
1294 "implementing/inheriting interface hRef = %x implflags %x\n",
1295 impl->hRef, impl->implflags);
1296 impl = impl->next;
1300 static void dump_Variant(const VARIANT * pvar)
1302 SYSTEMTIME st;
1304 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1306 if (pvar)
1308 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1309 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1311 TRACE(",%p", V_BYREF(pvar));
1313 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1315 TRACE(",%p", V_ARRAY(pvar));
1317 else switch (V_TYPE(pvar))
1319 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1320 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1321 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1322 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1323 case VT_INT:
1324 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1325 case VT_UINT:
1326 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1327 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1328 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1329 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1330 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1331 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1332 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1333 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1334 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1335 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1336 V_CY(pvar).s.Lo); break;
1337 case VT_DATE:
1338 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1339 TRACE(",<invalid>");
1340 else
1341 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1342 st.wHour, st.wMinute, st.wSecond);
1343 break;
1344 case VT_ERROR:
1345 case VT_VOID:
1346 case VT_USERDEFINED:
1347 case VT_EMPTY:
1348 case VT_NULL: break;
1349 default: TRACE(",?"); break;
1352 TRACE("}\n");
1355 static void dump_DispParms(const DISPPARAMS * pdp)
1357 unsigned int index;
1359 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1361 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1363 TRACE("named args:\n");
1364 for (index = 0; index < pdp->cNamedArgs; index++)
1365 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1368 if (pdp->cArgs && pdp->rgvarg)
1370 TRACE("args:\n");
1371 for (index = 0; index < pdp->cArgs; index++)
1372 dump_Variant( &pdp->rgvarg[index] );
1376 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1378 TRACE("%p ref=%u\n", pty, pty->ref);
1379 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1380 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1381 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1382 TRACE("fct:%u var:%u impl:%u\n",
1383 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1384 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1385 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1386 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1387 if (TRACE_ON(ole))
1388 dump_TLBFuncDesc(pty->funclist);
1389 dump_TLBVarDesc(pty->varlist);
1390 dump_TLBImplType(pty->impltypelist);
1393 static void dump_VARDESC(const VARDESC *v)
1395 MESSAGE("memid %d\n",v->memid);
1396 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1397 MESSAGE("oInst %d\n",v->u.oInst);
1398 dump_ELEMDESC(&(v->elemdescVar));
1399 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1400 MESSAGE("varkind %d\n",v->varkind);
1403 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1405 /* VT_LPWSTR is largest type that */
1406 /* may appear in type description*/
1407 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1408 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1409 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1410 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1411 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1412 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1413 {{0},30},{{0},31}
1416 static void TLB_abort(void)
1418 DebugBreak();
1421 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1422 static void * TLB_Alloc(unsigned size)
1424 void * ret;
1425 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1426 /* FIXME */
1427 ERR("cannot allocate memory\n");
1429 return ret;
1432 static void TLB_Free(void * ptr)
1434 HeapFree(GetProcessHeap(), 0, ptr);
1437 /* returns the size required for a deep copy of a typedesc into a
1438 * flat buffer */
1439 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1441 SIZE_T size = 0;
1443 if (alloc_initial_space)
1444 size += sizeof(TYPEDESC);
1446 switch (tdesc->vt)
1448 case VT_PTR:
1449 case VT_SAFEARRAY:
1450 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1451 break;
1452 case VT_CARRAY:
1453 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1454 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1455 break;
1457 return size;
1460 /* deep copy a typedesc into a flat buffer */
1461 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1463 if (!dest)
1465 dest = buffer;
1466 buffer = (char *)buffer + sizeof(TYPEDESC);
1469 *dest = *src;
1471 switch (src->vt)
1473 case VT_PTR:
1474 case VT_SAFEARRAY:
1475 dest->u.lptdesc = buffer;
1476 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1477 break;
1478 case VT_CARRAY:
1479 dest->u.lpadesc = buffer;
1480 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1481 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1482 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1483 break;
1485 return buffer;
1488 /* free custom data allocated by MSFT_CustData */
1489 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1491 TLBCustData *pCustDataNext;
1492 for (; pCustData; pCustData = pCustDataNext)
1494 VariantClear(&pCustData->data);
1496 pCustDataNext = pCustData->next;
1497 TLB_Free(pCustData);
1501 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1503 DWORD len;
1504 BSTR ret;
1506 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1507 ret = SysAllocStringLen(NULL, len - 1);
1508 if (!ret) return ret;
1509 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1510 return ret;
1513 /**********************************************************************
1515 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1517 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1519 return pcx->pos;
1522 static inline void MSFT_Seek(TLBContext *pcx, long where)
1524 if (where != DO_NOT_SEEK)
1526 where += pcx->oStart;
1527 if (where > pcx->length)
1529 /* FIXME */
1530 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1531 TLB_abort();
1533 pcx->pos = where;
1537 /* read function */
1538 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1540 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1541 pcx->pos, count, pcx->oStart, pcx->length, where);
1543 MSFT_Seek(pcx, where);
1544 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1545 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1546 pcx->pos += count;
1547 return count;
1550 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1551 long where )
1553 DWORD ret;
1555 ret = MSFT_Read(buffer, count, pcx, where);
1556 FromLEDWords(buffer, ret);
1558 return ret;
1561 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1562 long where )
1564 DWORD ret;
1566 ret = MSFT_Read(buffer, count, pcx, where);
1567 FromLEWords(buffer, ret);
1569 return ret;
1572 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1574 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1575 memset(pGuid,0, sizeof(GUID));
1576 return;
1578 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1579 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1580 pGuid->Data2 = FromLEWord(pGuid->Data2);
1581 pGuid->Data3 = FromLEWord(pGuid->Data3);
1582 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1585 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1587 MSFT_NameIntro niName;
1589 if (offset < 0)
1591 ERR_(typelib)("bad offset %d\n", offset);
1592 return -1;
1595 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1596 pcx->pTblDir->pNametab.offset+offset);
1598 return niName.hreftype;
1601 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1603 char * name;
1604 MSFT_NameIntro niName;
1605 int lengthInChars;
1606 BSTR bstrName = NULL;
1608 if (offset < 0)
1610 ERR_(typelib)("bad offset %d\n", offset);
1611 return NULL;
1613 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1614 pcx->pTblDir->pNametab.offset+offset);
1615 niName.namelen &= 0xFF; /* FIXME: correct ? */
1616 name=TLB_Alloc((niName.namelen & 0xff) +1);
1617 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1618 name[niName.namelen & 0xff]='\0';
1620 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1621 name, -1, NULL, 0);
1623 /* no invalid characters in string */
1624 if (lengthInChars)
1626 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1628 /* don't check for invalid character since this has been done previously */
1629 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1631 TLB_Free(name);
1633 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1634 return bstrName;
1637 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1639 char * string;
1640 INT16 length;
1641 int lengthInChars;
1642 BSTR bstr = NULL;
1644 if(offset<0) return NULL;
1645 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1646 if(length <= 0) return 0;
1647 string=TLB_Alloc(length +1);
1648 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1649 string[length]='\0';
1651 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1652 string, -1, NULL, 0);
1654 /* no invalid characters in string */
1655 if (lengthInChars)
1657 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1659 /* don't check for invalid character since this has been done previously */
1660 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1662 TLB_Free(string);
1664 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1665 return bstr;
1668 * read a value and fill a VARIANT structure
1670 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1672 int size;
1674 TRACE_(typelib)("\n");
1676 if(offset <0) { /* data are packed in here */
1677 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1678 V_I4(pVar) = offset & 0x3ffffff;
1679 return;
1681 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1682 pcx->pTblDir->pCustData.offset + offset );
1683 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1684 switch (V_VT(pVar)){
1685 case VT_EMPTY: /* FIXME: is this right? */
1686 case VT_NULL: /* FIXME: is this right? */
1687 case VT_I2 : /* this should not happen */
1688 case VT_I4 :
1689 case VT_R4 :
1690 case VT_ERROR :
1691 case VT_BOOL :
1692 case VT_I1 :
1693 case VT_UI1 :
1694 case VT_UI2 :
1695 case VT_UI4 :
1696 case VT_INT :
1697 case VT_UINT :
1698 case VT_VOID : /* FIXME: is this right? */
1699 case VT_HRESULT :
1700 size=4; break;
1701 case VT_R8 :
1702 case VT_CY :
1703 case VT_DATE :
1704 case VT_I8 :
1705 case VT_UI8 :
1706 case VT_DECIMAL : /* FIXME: is this right? */
1707 case VT_FILETIME :
1708 size=8;break;
1709 /* pointer types with known behaviour */
1710 case VT_BSTR :{
1711 char * ptr;
1712 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1713 if(size < 0) {
1714 char next;
1715 DWORD origPos = MSFT_Tell(pcx), nullPos;
1717 do {
1718 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1719 } while (next);
1720 nullPos = MSFT_Tell(pcx);
1721 size = nullPos - origPos;
1722 MSFT_Seek(pcx, origPos);
1724 ptr=TLB_Alloc(size);/* allocate temp buffer */
1725 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1726 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1727 /* FIXME: do we need a AtoW conversion here? */
1728 V_UNION(pVar, bstrVal[size])='\0';
1729 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1730 TLB_Free(ptr);
1732 size=-4; break;
1733 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1734 case VT_DISPATCH :
1735 case VT_VARIANT :
1736 case VT_UNKNOWN :
1737 case VT_PTR :
1738 case VT_SAFEARRAY :
1739 case VT_CARRAY :
1740 case VT_USERDEFINED :
1741 case VT_LPSTR :
1742 case VT_LPWSTR :
1743 case VT_BLOB :
1744 case VT_STREAM :
1745 case VT_STORAGE :
1746 case VT_STREAMED_OBJECT :
1747 case VT_STORED_OBJECT :
1748 case VT_BLOB_OBJECT :
1749 case VT_CF :
1750 case VT_CLSID :
1751 default:
1752 size=0;
1753 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1754 V_VT(pVar));
1757 if(size>0) /* (big|small) endian correct? */
1758 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1759 return;
1762 * create a linked list with custom data
1764 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1766 MSFT_CDGuid entry;
1767 TLBCustData* pNew;
1768 int count=0;
1770 TRACE_(typelib)("\n");
1772 while(offset >=0){
1773 count++;
1774 pNew=TLB_Alloc(sizeof(TLBCustData));
1775 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1776 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1777 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1778 /* add new custom data at head of the list */
1779 pNew->next=*ppCustData;
1780 *ppCustData=pNew;
1781 offset = entry.next;
1783 return count;
1786 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1787 ITypeInfoImpl *pTI)
1789 if(type <0)
1790 pTd->vt=type & VT_TYPEMASK;
1791 else
1792 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1794 if(pTd->vt == VT_USERDEFINED)
1795 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1797 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1800 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1802 /* resolve referenced type if any */
1803 while (lpTypeDesc)
1805 switch (lpTypeDesc->vt)
1807 case VT_PTR:
1808 lpTypeDesc = lpTypeDesc->u.lptdesc;
1809 break;
1811 case VT_CARRAY:
1812 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1813 break;
1815 case VT_USERDEFINED:
1816 MSFT_DoRefType(pcx, pTI->pTypeLib,
1817 lpTypeDesc->u.hreftype);
1819 lpTypeDesc = NULL;
1820 break;
1822 default:
1823 lpTypeDesc = NULL;
1828 static void
1829 MSFT_DoFuncs(TLBContext* pcx,
1830 ITypeInfoImpl* pTI,
1831 int cFuncs,
1832 int cVars,
1833 int offset,
1834 TLBFuncDesc** pptfd)
1837 * member information is stored in a data structure at offset
1838 * indicated by the memoffset field of the typeinfo structure
1839 * There are several distinctive parts.
1840 * The first part starts with a field that holds the total length
1841 * of this (first) part excluding this field. Then follow the records,
1842 * for each member there is one record.
1844 * The first entry is always the length of the record (including this
1845 * length word).
1846 * The rest of the record depends on the type of the member. If there is
1847 * a field indicating the member type (function, variable, interface, etc)
1848 * I have not found it yet. At this time we depend on the information
1849 * in the type info and the usual order how things are stored.
1851 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1852 * for each member;
1854 * Third is an equal sized array with file offsets to the name entry
1855 * of each member.
1857 * The fourth and last (?) part is an array with offsets to the records
1858 * in the first part of this file segment.
1861 int infolen, nameoffset, reclength, nrattributes, i;
1862 int recoffset = offset + sizeof(INT);
1864 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1865 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1866 TLBFuncDesc *ptfd_prev = NULL;
1868 TRACE_(typelib)("\n");
1870 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1872 for ( i = 0; i < cFuncs ; i++ )
1874 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1876 /* name, eventually add to a hash table */
1877 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1878 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1880 /* nameoffset is sometimes -1 on the second half of a propget/propput
1881 * pair of functions */
1882 if ((nameoffset == -1) && (i > 0))
1883 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1884 else
1885 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1887 /* read the function information record */
1888 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1890 reclength &= 0xffff;
1892 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1894 /* do the attributes */
1895 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1896 / sizeof(int);
1898 if ( nrattributes > 0 )
1900 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1902 if ( nrattributes > 1 )
1904 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1905 pFuncRec->OptAttr[1]) ;
1907 if ( nrattributes > 2 )
1909 if ( pFuncRec->FKCCIC & 0x2000 )
1911 if (!IS_INTRESOURCE(pFuncRec->OptAttr[2]))
1912 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->OptAttr[2]);
1913 (*pptfd)->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->OptAttr[2]);
1915 else
1917 (*pptfd)->Entry = MSFT_ReadString(pcx,
1918 pFuncRec->OptAttr[2]);
1920 if( nrattributes > 5 )
1922 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1924 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1926 MSFT_CustData(pcx,
1927 pFuncRec->OptAttr[6],
1928 &(*pptfd)->pCustData);
1932 else
1934 (*pptfd)->Entry = (BSTR)-1;
1939 /* fill the FuncDesc Structure */
1940 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1941 offset + infolen + ( i + 1) * sizeof(INT));
1943 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1944 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1945 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1946 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1947 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1948 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1949 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1951 MSFT_GetTdesc(pcx,
1952 pFuncRec->DataType,
1953 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1954 pTI);
1955 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1957 /* do the parameters/arguments */
1958 if(pFuncRec->nrargs)
1960 int j = 0;
1961 MSFT_ParameterInfo paraminfo;
1963 (*pptfd)->funcdesc.lprgelemdescParam =
1964 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1966 (*pptfd)->pParamDesc =
1967 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1969 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1970 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1972 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1974 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1976 MSFT_GetTdesc(pcx,
1977 paraminfo.DataType,
1978 &elemdesc->tdesc,
1979 pTI);
1981 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1983 /* name */
1984 if (paraminfo.oName == -1)
1985 /* this occurs for [propput] or [propget] methods, so
1986 * we should just set the name of the parameter to the
1987 * name of the method. */
1988 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1989 else
1990 (*pptfd)->pParamDesc[j].Name =
1991 MSFT_ReadName( pcx, paraminfo.oName );
1992 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1994 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1996 /* default value */
1997 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1998 (pFuncRec->FKCCIC & 0x1000) )
2000 INT* pInt = (INT *)((char *)pFuncRec +
2001 reclength -
2002 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
2004 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2006 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
2007 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2009 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2010 pInt[j], pcx);
2012 else
2013 elemdesc->u.paramdesc.pparamdescex = NULL;
2014 /* custom info */
2015 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2017 MSFT_CustData(pcx,
2018 pFuncRec->OptAttr[7+j],
2019 &(*pptfd)->pParamDesc[j].pCustData);
2022 /* SEEK value = jump to offset,
2023 * from there jump to the end of record,
2024 * go back by (j-1) arguments
2026 MSFT_ReadLEDWords( &paraminfo ,
2027 sizeof(MSFT_ParameterInfo), pcx,
2028 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2029 * sizeof(MSFT_ParameterInfo)));
2033 /* scode is not used: archaic win16 stuff FIXME: right? */
2034 (*pptfd)->funcdesc.cScodes = 0 ;
2035 (*pptfd)->funcdesc.lprgscode = NULL ;
2037 ptfd_prev = *pptfd;
2038 pptfd = & ((*pptfd)->next);
2039 recoffset += reclength;
2041 HeapFree(GetProcessHeap(), 0, recbuf);
2044 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2045 int cVars, int offset, TLBVarDesc ** pptvd)
2047 int infolen, nameoffset, reclength;
2048 char recbuf[256];
2049 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2050 int i;
2051 int recoffset;
2053 TRACE_(typelib)("\n");
2055 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2056 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2057 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2058 recoffset += offset+sizeof(INT);
2059 for(i=0;i<cVars;i++){
2060 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2061 /* name, eventually add to a hash table */
2062 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2063 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2064 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2065 /* read the variable information record */
2066 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2067 reclength &=0xff;
2068 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2069 /* Optional data */
2070 if(reclength >(6*sizeof(INT)) )
2071 (*pptvd)->HelpContext=pVarRec->HelpContext;
2072 if(reclength >(7*sizeof(INT)) )
2073 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2074 if(reclength >(8*sizeof(INT)) )
2075 if(reclength >(9*sizeof(INT)) )
2076 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2077 /* fill the VarDesc Structure */
2078 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2079 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2080 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2081 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2082 MSFT_GetTdesc(pcx, pVarRec->DataType,
2083 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2084 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2085 if(pVarRec->VarKind == VAR_CONST ){
2086 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2087 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2088 pVarRec->OffsValue, pcx);
2089 } else
2090 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2091 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2092 pptvd=&((*pptvd)->next);
2093 recoffset += reclength;
2096 /* fill in data for a hreftype (offset). When the referenced type is contained
2097 * in the typelib, it's just an (file) offset in the type info base dir.
2098 * If comes from import, it's an offset+1 in the ImpInfo table
2099 * */
2100 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2101 int offset)
2103 TLBRefType *ref;
2105 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2107 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2109 if(ref->reference == offset) return;
2112 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2113 list_add_tail(&pTL->ref_list, &ref->entry);
2115 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2116 /* external typelib */
2117 MSFT_ImpInfo impinfo;
2118 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2120 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2122 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2123 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2124 while (pImpLib){ /* search the known offsets of all import libraries */
2125 if(pImpLib->offset==impinfo.oImpFile) break;
2126 pImpLib=pImpLib->next;
2128 if(pImpLib){
2129 ref->reference = offset;
2130 ref->pImpTLInfo = pImpLib;
2131 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2132 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2133 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2134 ref->index = TLB_REF_USE_GUID;
2135 } else
2136 ref->index = impinfo.oGuid;
2137 }else{
2138 ERR("Cannot find a reference\n");
2139 ref->reference = -1;
2140 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2142 }else{
2143 /* in this typelib */
2144 ref->index = MSFT_HREFTYPE_INDEX(offset);
2145 ref->reference = offset;
2146 ref->pImpTLInfo = TLB_REF_INTERNAL;
2150 /* process Implemented Interfaces of a com class */
2151 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2152 int offset)
2154 int i;
2155 MSFT_RefRecord refrec;
2156 TLBImplType **ppImpl = &pTI->impltypelist;
2158 TRACE_(typelib)("\n");
2160 for(i=0;i<count;i++){
2161 if(offset<0) break; /* paranoia */
2162 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2163 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2164 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2165 (*ppImpl)->hRef = refrec.reftype;
2166 (*ppImpl)->implflags=refrec.flags;
2167 (*ppImpl)->ctCustData=
2168 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2169 offset=refrec.onext;
2170 ppImpl=&((*ppImpl)->next);
2174 * process a typeinfo record
2176 static ITypeInfoImpl * MSFT_DoTypeInfo(
2177 TLBContext *pcx,
2178 int count,
2179 ITypeLibImpl * pLibInfo)
2181 MSFT_TypeInfoBase tiBase;
2182 ITypeInfoImpl *ptiRet;
2184 TRACE_(typelib)("count=%u\n", count);
2186 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2187 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2188 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2190 /* this is where we are coming from */
2191 ptiRet->pTypeLib = pLibInfo;
2192 ptiRet->index=count;
2193 /* fill in the typeattr fields */
2195 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2196 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2197 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2198 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2199 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2200 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2201 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2202 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2203 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2204 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2205 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2206 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2207 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2208 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2209 MSFT_GetTdesc(pcx, tiBase.datatype1,
2210 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2212 /* FIXME: */
2213 /* IDLDESC idldescType; *//* never saw this one != zero */
2215 /* name, eventually add to a hash table */
2216 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2217 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2218 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2219 /* help info */
2220 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2221 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2222 ptiRet->dwHelpContext=tiBase.helpcontext;
2224 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2225 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2227 /* note: InfoType's Help file and HelpStringDll come from the containing
2228 * library. Further HelpString and Docstring appear to be the same thing :(
2230 /* functions */
2231 if(ptiRet->TypeAttr.cFuncs >0 )
2232 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2233 ptiRet->TypeAttr.cVars,
2234 tiBase.memoffset, & ptiRet->funclist);
2235 /* variables */
2236 if(ptiRet->TypeAttr.cVars >0 )
2237 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2238 ptiRet->TypeAttr.cVars,
2239 tiBase.memoffset, & ptiRet->varlist);
2240 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2241 switch(ptiRet->TypeAttr.typekind)
2243 case TKIND_COCLASS:
2244 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2245 tiBase.datatype1);
2246 break;
2247 case TKIND_DISPATCH:
2248 /* This is not -1 when the interface is a non-base dual interface or
2249 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2250 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2251 not this interface.
2254 if (tiBase.datatype1 != -1)
2256 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2257 ptiRet->impltypelist->hRef = tiBase.datatype1;
2258 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2260 break;
2261 default:
2262 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2263 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2264 ptiRet->impltypelist->hRef = tiBase.datatype1;
2265 break;
2268 ptiRet->ctCustData=
2269 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2271 TRACE_(typelib)("%s guid: %s kind:%s\n",
2272 debugstr_w(ptiRet->Name),
2273 debugstr_guid(&ptiRet->TypeAttr.guid),
2274 typekind_desc[ptiRet->TypeAttr.typekind]);
2275 if (TRACE_ON(typelib))
2276 dump_TypeInfo(ptiRet);
2278 return ptiRet;
2281 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2282 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2283 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2284 * tradeoff here.
2286 static ITypeLibImpl *tlb_cache_first;
2287 static CRITICAL_SECTION cache_section;
2288 static CRITICAL_SECTION_DEBUG cache_section_debug =
2290 0, 0, &cache_section,
2291 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2292 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2294 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2297 typedef struct TLB_PEFile
2299 const IUnknownVtbl *lpvtbl;
2300 LONG refs;
2301 HMODULE dll;
2302 HRSRC typelib_resource;
2303 HGLOBAL typelib_global;
2304 LPVOID typelib_base;
2305 } TLB_PEFile;
2307 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2309 if (IsEqualIID(riid, &IID_IUnknown))
2311 *ppv = iface;
2312 IUnknown_AddRef(iface);
2313 return S_OK;
2315 *ppv = NULL;
2316 return E_NOINTERFACE;
2319 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2321 TLB_PEFile *This = (TLB_PEFile *)iface;
2322 return InterlockedIncrement(&This->refs);
2325 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2327 TLB_PEFile *This = (TLB_PEFile *)iface;
2328 ULONG refs = InterlockedDecrement(&This->refs);
2329 if (!refs)
2331 if (This->typelib_global)
2332 FreeResource(This->typelib_global);
2333 if (This->dll)
2334 FreeLibrary(This->dll);
2335 HeapFree(GetProcessHeap(), 0, This);
2337 return refs;
2340 static const IUnknownVtbl TLB_PEFile_Vtable =
2342 TLB_PEFile_QueryInterface,
2343 TLB_PEFile_AddRef,
2344 TLB_PEFile_Release
2347 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2349 TLB_PEFile *This;
2351 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2352 if (!This)
2353 return E_OUTOFMEMORY;
2355 This->lpvtbl = &TLB_PEFile_Vtable;
2356 This->refs = 1;
2357 This->dll = NULL;
2358 This->typelib_resource = NULL;
2359 This->typelib_global = NULL;
2360 This->typelib_base = NULL;
2362 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2363 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2365 if (This->dll)
2367 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2368 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2369 if (This->typelib_resource)
2371 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2372 if (This->typelib_global)
2374 This->typelib_base = LockResource(This->typelib_global);
2376 if (This->typelib_base)
2378 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2379 *ppBase = This->typelib_base;
2380 *ppFile = (IUnknown *)&This->lpvtbl;
2381 return S_OK;
2387 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2388 return TYPE_E_CANTLOADLIBRARY;
2391 typedef struct TLB_NEFile
2393 const IUnknownVtbl *lpvtbl;
2394 LONG refs;
2395 LPVOID typelib_base;
2396 } TLB_NEFile;
2398 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2400 if (IsEqualIID(riid, &IID_IUnknown))
2402 *ppv = iface;
2403 IUnknown_AddRef(iface);
2404 return S_OK;
2406 *ppv = NULL;
2407 return E_NOINTERFACE;
2410 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2412 TLB_NEFile *This = (TLB_NEFile *)iface;
2413 return InterlockedIncrement(&This->refs);
2416 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2418 TLB_NEFile *This = (TLB_NEFile *)iface;
2419 ULONG refs = InterlockedDecrement(&This->refs);
2420 if (!refs)
2422 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2423 HeapFree(GetProcessHeap(), 0, This);
2425 return refs;
2428 static const IUnknownVtbl TLB_NEFile_Vtable =
2430 TLB_NEFile_QueryInterface,
2431 TLB_NEFile_AddRef,
2432 TLB_NEFile_Release
2435 /***********************************************************************
2436 * read_xx_header [internal]
2438 static int read_xx_header( HFILE lzfd )
2440 IMAGE_DOS_HEADER mzh;
2441 char magic[3];
2443 LZSeek( lzfd, 0, SEEK_SET );
2444 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2445 return 0;
2446 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2447 return 0;
2449 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2450 if ( 2 != LZRead( lzfd, magic, 2 ) )
2451 return 0;
2453 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2455 if ( magic[0] == 'N' && magic[1] == 'E' )
2456 return IMAGE_OS2_SIGNATURE;
2457 if ( magic[0] == 'P' && magic[1] == 'E' )
2458 return IMAGE_NT_SIGNATURE;
2460 magic[2] = '\0';
2461 WARN("Can't handle %s files.\n", magic );
2462 return 0;
2466 /***********************************************************************
2467 * find_ne_resource [internal]
2469 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2470 DWORD *resLen, DWORD *resOff )
2472 IMAGE_OS2_HEADER nehd;
2473 NE_TYPEINFO *typeInfo;
2474 NE_NAMEINFO *nameInfo;
2475 DWORD nehdoffset;
2476 LPBYTE resTab;
2477 DWORD resTabSize;
2478 int count;
2480 /* Read in NE header */
2481 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2482 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2484 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2485 if ( !resTabSize )
2487 TRACE("No resources in NE dll\n" );
2488 return FALSE;
2491 /* Read in resource table */
2492 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2493 if ( !resTab ) return FALSE;
2495 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2496 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2498 HeapFree( GetProcessHeap(), 0, resTab );
2499 return FALSE;
2502 /* Find resource */
2503 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2505 if (!IS_INTRESOURCE(typeid)) /* named type */
2507 BYTE len = strlen( typeid );
2508 while (typeInfo->type_id)
2510 if (!(typeInfo->type_id & 0x8000))
2512 BYTE *p = resTab + typeInfo->type_id;
2513 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2515 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2516 typeInfo->count * sizeof(NE_NAMEINFO));
2519 else /* numeric type id */
2521 WORD id = LOWORD(typeid) | 0x8000;
2522 while (typeInfo->type_id)
2524 if (typeInfo->type_id == id) goto found_type;
2525 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2526 typeInfo->count * sizeof(NE_NAMEINFO));
2529 TRACE("No typeid entry found for %p\n", typeid );
2530 HeapFree( GetProcessHeap(), 0, resTab );
2531 return FALSE;
2533 found_type:
2534 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2536 if (!IS_INTRESOURCE(resid)) /* named resource */
2538 BYTE len = strlen( resid );
2539 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2541 BYTE *p = resTab + nameInfo->id;
2542 if (nameInfo->id & 0x8000) continue;
2543 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2546 else /* numeric resource id */
2548 WORD id = LOWORD(resid) | 0x8000;
2549 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2550 if (nameInfo->id == id) goto found_name;
2552 TRACE("No resid entry found for %p\n", typeid );
2553 HeapFree( GetProcessHeap(), 0, resTab );
2554 return FALSE;
2556 found_name:
2557 /* Return resource data */
2558 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2559 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2561 HeapFree( GetProcessHeap(), 0, resTab );
2562 return TRUE;
2565 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2567 HFILE lzfd = -1;
2568 OFSTRUCT ofs;
2569 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2570 TLB_NEFile *This = NULL;
2572 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2573 if (!This) return E_OUTOFMEMORY;
2575 This->lpvtbl = &TLB_NEFile_Vtable;
2576 This->refs = 1;
2577 This->typelib_base = NULL;
2579 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2580 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2582 DWORD reslen, offset;
2583 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2585 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2586 if( !This->typelib_base )
2587 hr = E_OUTOFMEMORY;
2588 else
2590 LZSeek( lzfd, offset, SEEK_SET );
2591 reslen = LZRead( lzfd, This->typelib_base, reslen );
2592 LZClose( lzfd );
2593 *ppBase = This->typelib_base;
2594 *pdwTLBLength = reslen;
2595 *ppFile = (IUnknown *)&This->lpvtbl;
2596 return S_OK;
2601 if( lzfd >= 0) LZClose( lzfd );
2602 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2603 return hr;
2606 typedef struct TLB_Mapping
2608 const IUnknownVtbl *lpvtbl;
2609 LONG refs;
2610 HANDLE file;
2611 HANDLE mapping;
2612 LPVOID typelib_base;
2613 } TLB_Mapping;
2615 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2617 if (IsEqualIID(riid, &IID_IUnknown))
2619 *ppv = iface;
2620 IUnknown_AddRef(iface);
2621 return S_OK;
2623 *ppv = NULL;
2624 return E_NOINTERFACE;
2627 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2629 TLB_Mapping *This = (TLB_Mapping *)iface;
2630 return InterlockedIncrement(&This->refs);
2633 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2635 TLB_Mapping *This = (TLB_Mapping *)iface;
2636 ULONG refs = InterlockedDecrement(&This->refs);
2637 if (!refs)
2639 if (This->typelib_base)
2640 UnmapViewOfFile(This->typelib_base);
2641 if (This->mapping)
2642 CloseHandle(This->mapping);
2643 if (This->file != INVALID_HANDLE_VALUE)
2644 CloseHandle(This->file);
2645 HeapFree(GetProcessHeap(), 0, This);
2647 return refs;
2650 static const IUnknownVtbl TLB_Mapping_Vtable =
2652 TLB_Mapping_QueryInterface,
2653 TLB_Mapping_AddRef,
2654 TLB_Mapping_Release
2657 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2659 TLB_Mapping *This;
2661 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2662 if (!This)
2663 return E_OUTOFMEMORY;
2665 This->lpvtbl = &TLB_Mapping_Vtable;
2666 This->refs = 1;
2667 This->file = INVALID_HANDLE_VALUE;
2668 This->mapping = NULL;
2669 This->typelib_base = NULL;
2671 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2672 if (INVALID_HANDLE_VALUE != This->file)
2674 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2675 if (This->mapping)
2677 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2678 if(This->typelib_base)
2680 /* retrieve file size */
2681 *pdwTLBLength = GetFileSize(This->file, NULL);
2682 *ppBase = This->typelib_base;
2683 *ppFile = (IUnknown *)&This->lpvtbl;
2684 return S_OK;
2689 IUnknown_Release((IUnknown *)&This->lpvtbl);
2690 return TYPE_E_CANTLOADLIBRARY;
2693 /****************************************************************************
2694 * TLB_ReadTypeLib
2696 * find the type of the typelib file and map the typelib resource into
2697 * the memory
2699 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2700 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2701 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2703 ITypeLibImpl *entry;
2704 HRESULT ret;
2705 INT index = 1;
2706 LPWSTR index_str, file = (LPWSTR)pszFileName;
2707 LPVOID pBase = NULL;
2708 DWORD dwTLBLength = 0;
2709 IUnknown *pFile = NULL;
2711 *ppTypeLib = NULL;
2713 index_str = strrchrW(pszFileName, '\\');
2714 if(index_str && *++index_str != '\0')
2716 LPWSTR end_ptr;
2717 long idx = strtolW(index_str, &end_ptr, 10);
2718 if(*end_ptr == '\0')
2720 int str_len = index_str - pszFileName - 1;
2721 index = idx;
2722 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2723 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2724 file[str_len] = 0;
2728 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2730 if(strchrW(file, '\\'))
2732 lstrcpyW(pszPath, file);
2734 else
2736 int len = GetSystemDirectoryW(pszPath, cchPath);
2737 pszPath[len] = '\\';
2738 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2742 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2744 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2746 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2747 EnterCriticalSection(&cache_section);
2748 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2750 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2752 TRACE("cache hit\n");
2753 *ppTypeLib = (ITypeLib2*)entry;
2754 ITypeLib_AddRef(*ppTypeLib);
2755 LeaveCriticalSection(&cache_section);
2756 return S_OK;
2759 LeaveCriticalSection(&cache_section);
2761 /* now actually load and parse the typelib */
2763 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2764 if (ret == TYPE_E_CANTLOADLIBRARY)
2765 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2766 if (ret == TYPE_E_CANTLOADLIBRARY)
2767 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2768 if (SUCCEEDED(ret))
2770 if (dwTLBLength >= 4)
2772 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2773 if (dwSignature == MSFT_SIGNATURE)
2774 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2775 else if (dwSignature == SLTG_SIGNATURE)
2776 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2777 else
2779 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2780 ret = TYPE_E_CANTLOADLIBRARY;
2783 else
2784 ret = TYPE_E_CANTLOADLIBRARY;
2785 IUnknown_Release(pFile);
2788 if(*ppTypeLib) {
2789 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2791 TRACE("adding to cache\n");
2792 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2793 lstrcpyW(impl->path, pszPath);
2794 /* We should really canonicalise the path here. */
2795 impl->index = index;
2797 /* FIXME: check if it has added already in the meantime */
2798 EnterCriticalSection(&cache_section);
2799 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2800 impl->prev = NULL;
2801 tlb_cache_first = impl;
2802 LeaveCriticalSection(&cache_section);
2803 ret = S_OK;
2804 } else
2805 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2807 return ret;
2810 /*================== ITypeLib(2) Methods ===================================*/
2812 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2814 ITypeLibImpl* pTypeLibImpl;
2816 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2817 if (!pTypeLibImpl) return NULL;
2819 pTypeLibImpl->lpVtbl = &tlbvt;
2820 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2821 pTypeLibImpl->ref = 1;
2823 list_init(&pTypeLibImpl->ref_list);
2824 pTypeLibImpl->dispatch_href = -1;
2826 return pTypeLibImpl;
2829 /****************************************************************************
2830 * ITypeLib2_Constructor_MSFT
2832 * loading an MSFT typelib from an in-memory image
2834 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2836 TLBContext cx;
2837 long lPSegDir;
2838 MSFT_Header tlbHeader;
2839 MSFT_SegDir tlbSegDir;
2840 ITypeLibImpl * pTypeLibImpl;
2842 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2844 pTypeLibImpl = TypeLibImpl_Constructor();
2845 if (!pTypeLibImpl) return NULL;
2847 /* get pointer to beginning of typelib data */
2848 cx.pos = 0;
2849 cx.oStart=0;
2850 cx.mapping = pLib;
2851 cx.pLibInfo = pTypeLibImpl;
2852 cx.length = dwTLBLength;
2854 /* read header */
2855 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2856 TRACE_(typelib)("header:\n");
2857 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2858 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2859 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2860 return NULL;
2862 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2864 /* there is a small amount of information here until the next important
2865 * part:
2866 * the segment directory . Try to calculate the amount of data */
2867 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2869 /* now read the segment directory */
2870 TRACE("read segment directory (at %ld)\n",lPSegDir);
2871 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2872 cx.pTblDir = &tlbSegDir;
2874 /* just check two entries */
2875 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2877 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2878 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2879 return NULL;
2882 /* now fill our internal data */
2883 /* TLIBATTR fields */
2884 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2886 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2887 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2888 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2889 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2890 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2892 pTypeLibImpl->lcid = tlbHeader.lcid;
2894 /* name, eventually add to a hash table */
2895 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2897 /* help info */
2898 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2899 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2901 if( tlbHeader.varflags & HELPDLLFLAG)
2903 int offset;
2904 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2905 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2908 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2910 /* custom data */
2911 if(tlbHeader.CustomDataOffset >= 0)
2913 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2916 /* fill in type descriptions */
2917 if(tlbSegDir.pTypdescTab.length > 0)
2919 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2920 INT16 td[4];
2921 pTypeLibImpl->ctTypeDesc = cTD;
2922 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2923 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2924 for(i=0; i<cTD; )
2926 /* FIXME: add several sanity checks here */
2927 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2928 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2930 /* FIXME: check safearray */
2931 if(td[3] < 0)
2932 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2933 else
2934 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2936 else if(td[0] == VT_CARRAY)
2938 /* array descr table here */
2939 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
2941 else if(td[0] == VT_USERDEFINED)
2943 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2945 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2948 /* second time around to fill the array subscript info */
2949 for(i=0;i<cTD;i++)
2951 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2952 if(tlbSegDir.pArrayDescriptions.offset>0)
2954 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2955 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2957 if(td[1]<0)
2958 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2959 else
2960 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
2962 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2964 for(j = 0; j<td[2]; j++)
2966 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2967 sizeof(INT), &cx, DO_NOT_SEEK);
2968 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2969 sizeof(INT), &cx, DO_NOT_SEEK);
2972 else
2974 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2975 ERR("didn't find array description data\n");
2980 /* imported type libs */
2981 if(tlbSegDir.pImpFiles.offset>0)
2983 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2984 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2985 UINT16 size;
2987 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2989 char *name;
2991 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2992 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2993 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2995 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2996 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2997 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2998 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3000 size >>= 2;
3001 name = TLB_Alloc(size+1);
3002 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3003 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3004 TLB_Free(name);
3006 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3007 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3009 ppImpLib = &(*ppImpLib)->next;
3013 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3014 if(pTypeLibImpl->dispatch_href != -1)
3015 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3017 /* type info's */
3018 if(tlbHeader.nrtypeinfos >= 0 )
3020 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3021 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3022 int i;
3024 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3026 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3028 ppTI = &((*ppTI)->next);
3029 (pTypeLibImpl->TypeInfoCount)++;
3033 TRACE("(%p)\n", pTypeLibImpl);
3034 return (ITypeLib2*) pTypeLibImpl;
3038 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3040 char b[3];
3041 int i;
3042 short s;
3044 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3045 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3046 return FALSE;
3049 guid->Data4[0] = s >> 8;
3050 guid->Data4[1] = s & 0xff;
3052 b[2] = '\0';
3053 for(i = 0; i < 6; i++) {
3054 memcpy(b, str + 24 + 2 * i, 2);
3055 guid->Data4[i + 2] = strtol(b, NULL, 16);
3057 return TRUE;
3060 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3062 WORD bytelen;
3063 DWORD len;
3065 *pBstr = NULL;
3066 bytelen = *(const WORD*)ptr;
3067 if(bytelen == 0xffff) return 2;
3068 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3069 *pBstr = SysAllocStringLen(NULL, len);
3070 if (*pBstr)
3071 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3072 return bytelen + 2;
3075 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3077 WORD bytelen;
3079 *str = NULL;
3080 bytelen = *(const WORD*)ptr;
3081 if(bytelen == 0xffff) return 2;
3082 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3083 memcpy(*str, ptr + 2, bytelen);
3084 (*str)[bytelen] = '\0';
3085 return bytelen + 2;
3088 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3090 char *ptr = pLibBlk;
3091 WORD w;
3093 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3094 FIXME("libblk magic = %04x\n", w);
3095 return 0;
3098 ptr += 6;
3099 if((w = *(WORD*)ptr) != 0xffff) {
3100 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3101 ptr += w;
3103 ptr += 2;
3105 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3107 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3109 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3110 ptr += 4;
3112 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3113 ptr += 2;
3115 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3116 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3117 else
3118 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3119 ptr += 2;
3121 ptr += 4; /* skip res12 */
3123 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3124 ptr += 2;
3126 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3127 ptr += 2;
3129 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3130 ptr += 2;
3132 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3133 ptr += sizeof(GUID);
3135 return ptr - (char*)pLibBlk;
3138 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3139 typedef struct
3141 unsigned int num;
3142 HREFTYPE refs[1];
3143 } sltg_ref_lookup_t;
3145 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3146 HREFTYPE *typelib_ref)
3148 if(table && typeinfo_ref < table->num)
3150 *typelib_ref = table->refs[typeinfo_ref];
3151 return S_OK;
3154 ERR_(typelib)("Unable to find reference\n");
3155 *typelib_ref = -1;
3156 return E_FAIL;
3159 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3161 BOOL done = FALSE;
3163 while(!done) {
3164 if((*pType & 0xe00) == 0xe00) {
3165 pTD->vt = VT_PTR;
3166 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3167 sizeof(TYPEDESC));
3168 pTD = pTD->u.lptdesc;
3170 switch(*pType & 0x3f) {
3171 case VT_PTR:
3172 pTD->vt = VT_PTR;
3173 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3174 sizeof(TYPEDESC));
3175 pTD = pTD->u.lptdesc;
3176 break;
3178 case VT_USERDEFINED:
3179 pTD->vt = VT_USERDEFINED;
3180 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3181 done = TRUE;
3182 break;
3184 case VT_CARRAY:
3186 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3187 array */
3189 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3191 pTD->vt = VT_CARRAY;
3192 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3193 sizeof(ARRAYDESC) +
3194 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3195 pTD->u.lpadesc->cDims = pSA->cDims;
3196 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3197 pSA->cDims * sizeof(SAFEARRAYBOUND));
3199 pTD = &pTD->u.lpadesc->tdescElem;
3200 break;
3203 case VT_SAFEARRAY:
3205 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3206 useful? */
3208 pType++;
3209 pTD->vt = VT_SAFEARRAY;
3210 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3211 sizeof(TYPEDESC));
3212 pTD = pTD->u.lptdesc;
3213 break;
3215 default:
3216 pTD->vt = *pType & 0x3f;
3217 done = TRUE;
3218 break;
3220 pType++;
3222 return pType;
3225 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3226 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3228 /* Handle [in/out] first */
3229 if((*pType & 0xc000) == 0xc000)
3230 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3231 else if(*pType & 0x8000)
3232 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3233 else if(*pType & 0x4000)
3234 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3235 else
3236 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3238 if(*pType & 0x2000)
3239 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3241 if(*pType & 0x80)
3242 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3244 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3248 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3249 char *pNameTable)
3251 unsigned int ref;
3252 char *name;
3253 TLBRefType *ref_type;
3254 sltg_ref_lookup_t *table;
3255 HREFTYPE typelib_ref;
3257 if(pRef->magic != SLTG_REF_MAGIC) {
3258 FIXME("Ref magic = %x\n", pRef->magic);
3259 return NULL;
3261 name = ( (char*)pRef->names + pRef->number);
3263 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3264 table->num = pRef->number >> 3;
3266 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3268 /* We don't want the first href to be 0 */
3269 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3271 for(ref = 0; ref < pRef->number >> 3; ref++) {
3272 char *refname;
3273 unsigned int lib_offs, type_num;
3275 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3277 name += SLTG_ReadStringA(name, &refname);
3278 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3279 FIXME_(typelib)("Can't sscanf ref\n");
3280 if(lib_offs != 0xffff) {
3281 TLBImpLib **import = &pTL->pImpLibs;
3283 while(*import) {
3284 if((*import)->offset == lib_offs)
3285 break;
3286 import = &(*import)->next;
3288 if(!*import) {
3289 char fname[MAX_PATH+1];
3290 int len;
3292 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3293 sizeof(**import));
3294 (*import)->offset = lib_offs;
3295 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3296 &(*import)->guid);
3297 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3298 &(*import)->wVersionMajor,
3299 &(*import)->wVersionMinor,
3300 &(*import)->lcid, fname) != 4) {
3301 FIXME_(typelib)("can't sscanf ref %s\n",
3302 pNameTable + lib_offs + 40);
3304 len = strlen(fname);
3305 if(fname[len-1] != '#')
3306 FIXME("fname = %s\n", fname);
3307 fname[len-1] = '\0';
3308 (*import)->name = TLB_MultiByteToBSTR(fname);
3310 ref_type->pImpTLInfo = *import;
3312 /* Store a reference to IDispatch */
3313 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3314 pTL->dispatch_href = typelib_ref;
3316 } else { /* internal ref */
3317 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3319 ref_type->reference = typelib_ref;
3320 ref_type->index = type_num;
3322 HeapFree(GetProcessHeap(), 0, refname);
3323 list_add_tail(&pTL->ref_list, &ref_type->entry);
3325 table->refs[ref] = typelib_ref;
3326 typelib_ref += 4;
3328 if((BYTE)*name != SLTG_REF_MAGIC)
3329 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3330 dump_TLBRefType(pTL);
3331 return table;
3334 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3335 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3337 SLTG_ImplInfo *info;
3338 TLBImplType **ppImplType = &pTI->impltypelist;
3339 /* I don't really get this structure, usually it's 0x16 bytes
3340 long, but iuser.tlb contains some that are 0x18 bytes long.
3341 That's ok because we can use the next ptr to jump to the next
3342 one. But how do we know the length of the last one? The WORD
3343 at offs 0x8 might be the clue. For now I'm just assuming that
3344 the last one is the regular 0x16 bytes. */
3346 info = (SLTG_ImplInfo*)pBlk;
3347 while(1) {
3348 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3349 sizeof(**ppImplType));
3350 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3351 (*ppImplType)->implflags = info->impltypeflags;
3352 pTI->TypeAttr.cImplTypes++;
3353 ppImplType = &(*ppImplType)->next;
3355 if(info->next == 0xffff)
3356 break;
3357 if(OneOnly)
3358 FIXME_(typelib)("Interface inheriting more than one interface\n");
3359 info = (SLTG_ImplInfo*)(pBlk + info->next);
3361 info++; /* see comment at top of function */
3362 return (char*)info;
3365 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3366 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3368 TLBVarDesc **ppVarDesc = &pTI->varlist;
3369 BSTR bstrPrevName = NULL;
3370 SLTG_Variable *pItem;
3371 unsigned short i;
3372 WORD *pType;
3374 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3375 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3377 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3378 sizeof(**ppVarDesc));
3379 (*ppVarDesc)->vardesc.memid = pItem->memid;
3381 if (pItem->magic != SLTG_VAR_MAGIC &&
3382 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3383 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3384 return;
3387 if (pItem->name == 0xfffe)
3388 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3389 else
3390 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3392 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3393 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3394 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3396 if(pItem->flags & 0x02)
3397 pType = &pItem->type;
3398 else
3399 pType = (WORD*)(pBlk + pItem->type);
3401 if (pItem->flags & ~0xda)
3402 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3404 SLTG_DoElem(pType, pBlk,
3405 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3407 if (TRACE_ON(typelib)) {
3408 char buf[300];
3409 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3410 TRACE_(typelib)("elemdescVar: %s\n", buf);
3413 if (pItem->flags & 0x40) {
3414 TRACE_(typelib)("VAR_DISPATCH\n");
3415 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3417 else if (pItem->flags & 0x10) {
3418 TRACE_(typelib)("VAR_CONST\n");
3419 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3420 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3421 sizeof(VARIANT));
3422 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3423 if (pItem->flags & 0x08)
3424 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3425 else {
3426 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3428 case VT_LPSTR:
3429 case VT_LPWSTR:
3430 case VT_BSTR:
3432 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3433 BSTR str;
3434 TRACE_(typelib)("len = %u\n", len);
3435 if (len == 0xffff) {
3436 str = NULL;
3437 } else {
3438 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3439 str = SysAllocStringLen(NULL, alloc_len);
3440 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3442 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3443 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3444 break;
3446 case VT_I2:
3447 case VT_UI2:
3448 case VT_I4:
3449 case VT_UI4:
3450 case VT_INT:
3451 case VT_UINT:
3452 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3453 *(INT*)(pBlk + pItem->byte_offs);
3454 break;
3455 default:
3456 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3460 else {
3461 TRACE_(typelib)("VAR_PERINSTANCE\n");
3462 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3463 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3466 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3467 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3469 if (pItem->flags & 0x80)
3470 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3472 bstrPrevName = (*ppVarDesc)->Name;
3473 ppVarDesc = &((*ppVarDesc)->next);
3475 pTI->TypeAttr.cVars = cVars;
3478 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3479 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3481 SLTG_Function *pFunc;
3482 unsigned short i;
3483 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3485 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3486 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3488 int param;
3489 WORD *pType, *pArg;
3491 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3492 sizeof(**ppFuncDesc));
3494 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3495 case SLTG_FUNCTION_MAGIC:
3496 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3497 break;
3498 case SLTG_DISPATCH_FUNCTION_MAGIC:
3499 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3500 break;
3501 case SLTG_STATIC_FUNCTION_MAGIC:
3502 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3503 break;
3504 default:
3505 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3506 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3507 *ppFuncDesc = NULL;
3508 return;
3510 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3512 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3513 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3514 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3515 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3516 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3517 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3519 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3520 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3522 if(pFunc->retnextopt & 0x80)
3523 pType = &pFunc->rettype;
3524 else
3525 pType = (WORD*)(pBlk + pFunc->rettype);
3527 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3529 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3530 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3531 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3532 (*ppFuncDesc)->pParamDesc =
3533 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3534 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3536 pArg = (WORD*)(pBlk + pFunc->arg_off);
3538 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3539 char *paramName = pNameTable + *pArg;
3540 BOOL HaveOffs;
3541 /* If arg type follows then paramName points to the 2nd
3542 letter of the name, else the next WORD is an offset to
3543 the arg type and paramName points to the first letter.
3544 So let's take one char off paramName and see if we're
3545 pointing at an alpha-numeric char. However if *pArg is
3546 0xffff or 0xfffe then the param has no name, the former
3547 meaning that the next WORD is the type, the latter
3548 meaning that the next WORD is an offset to the type. */
3550 HaveOffs = FALSE;
3551 if(*pArg == 0xffff)
3552 paramName = NULL;
3553 else if(*pArg == 0xfffe) {
3554 paramName = NULL;
3555 HaveOffs = TRUE;
3557 else if(paramName[-1] && !isalnum(paramName[-1]))
3558 HaveOffs = TRUE;
3560 pArg++;
3562 if(HaveOffs) { /* the next word is an offset to type */
3563 pType = (WORD*)(pBlk + *pArg);
3564 SLTG_DoElem(pType, pBlk,
3565 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3566 pArg++;
3567 } else {
3568 if(paramName)
3569 paramName--;
3570 pArg = SLTG_DoElem(pArg, pBlk,
3571 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3574 /* Are we an optional param ? */
3575 if((*ppFuncDesc)->funcdesc.cParams - param <=
3576 (*ppFuncDesc)->funcdesc.cParamsOpt)
3577 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3579 if(paramName) {
3580 (*ppFuncDesc)->pParamDesc[param].Name =
3581 TLB_MultiByteToBSTR(paramName);
3582 } else {
3583 (*ppFuncDesc)->pParamDesc[param].Name =
3584 SysAllocString((*ppFuncDesc)->Name);
3588 ppFuncDesc = &((*ppFuncDesc)->next);
3589 if(pFunc->next == 0xffff) break;
3591 pTI->TypeAttr.cFuncs = cFuncs;
3594 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3595 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3596 SLTG_TypeInfoTail *pTITail)
3598 char *pFirstItem;
3599 sltg_ref_lookup_t *ref_lookup = NULL;
3601 if(pTIHeader->href_table != 0xffffffff) {
3602 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3603 pNameTable);
3606 pFirstItem = pBlk;
3608 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3609 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3611 HeapFree(GetProcessHeap(), 0, ref_lookup);
3615 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3616 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3617 const SLTG_TypeInfoTail *pTITail)
3619 char *pFirstItem;
3620 sltg_ref_lookup_t *ref_lookup = NULL;
3622 if(pTIHeader->href_table != 0xffffffff) {
3623 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3624 pNameTable);
3627 pFirstItem = pBlk;
3629 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3630 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3633 if (pTITail->funcs_off != 0xffff)
3634 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3636 HeapFree(GetProcessHeap(), 0, ref_lookup);
3638 if (TRACE_ON(typelib))
3639 dump_TLBFuncDesc(pTI->funclist);
3642 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3643 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3644 const SLTG_TypeInfoTail *pTITail)
3646 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3649 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3650 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3651 const SLTG_TypeInfoTail *pTITail)
3653 WORD *pType;
3654 sltg_ref_lookup_t *ref_lookup = NULL;
3656 if (pTITail->simple_alias) {
3657 /* if simple alias, no more processing required */
3658 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3659 return;
3662 if(pTIHeader->href_table != 0xffffffff) {
3663 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3664 pNameTable);
3667 /* otherwise it is an offset to a type */
3668 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3670 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3672 HeapFree(GetProcessHeap(), 0, ref_lookup);
3675 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3676 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3677 const SLTG_TypeInfoTail *pTITail)
3679 sltg_ref_lookup_t *ref_lookup = NULL;
3680 if (pTIHeader->href_table != 0xffffffff)
3681 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3682 pNameTable);
3684 if (pTITail->vars_off != 0xffff)
3685 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3687 if (pTITail->funcs_off != 0xffff)
3688 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3690 if (pTITail->impls_off != 0xffff)
3691 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3693 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3694 * of dispinterface functions including the IDispatch ones, so
3695 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3696 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3698 HeapFree(GetProcessHeap(), 0, ref_lookup);
3699 if (TRACE_ON(typelib))
3700 dump_TLBFuncDesc(pTI->funclist);
3703 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3704 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3705 const SLTG_TypeInfoTail *pTITail)
3707 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3710 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3711 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3712 const SLTG_TypeInfoTail *pTITail)
3714 sltg_ref_lookup_t *ref_lookup = NULL;
3715 if (pTIHeader->href_table != 0xffffffff)
3716 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3717 pNameTable);
3719 if (pTITail->vars_off != 0xffff)
3720 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3722 if (pTITail->funcs_off != 0xffff)
3723 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3724 HeapFree(GetProcessHeap(), 0, ref_lookup);
3725 if (TRACE_ON(typelib))
3726 dump_TypeInfo(pTI);
3729 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3730 managable copy of it into this */
3731 typedef struct {
3732 WORD small_no;
3733 char *index_name;
3734 char *other_name;
3735 WORD res1a;
3736 WORD name_offs;
3737 WORD more_bytes;
3738 char *extra;
3739 WORD res20;
3740 DWORD helpcontext;
3741 WORD res26;
3742 GUID uuid;
3743 } SLTG_InternalOtherTypeInfo;
3745 /****************************************************************************
3746 * ITypeLib2_Constructor_SLTG
3748 * loading a SLTG typelib from an in-memory image
3750 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3752 ITypeLibImpl *pTypeLibImpl;
3753 SLTG_Header *pHeader;
3754 SLTG_BlkEntry *pBlkEntry;
3755 SLTG_Magic *pMagic;
3756 SLTG_Index *pIndex;
3757 SLTG_Pad9 *pPad9;
3758 LPVOID pBlk, pFirstBlk;
3759 SLTG_LibBlk *pLibBlk;
3760 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3761 char *pAfterOTIBlks = NULL;
3762 char *pNameTable, *ptr;
3763 int i;
3764 DWORD len, order;
3765 ITypeInfoImpl **ppTypeInfoImpl;
3767 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3770 pTypeLibImpl = TypeLibImpl_Constructor();
3771 if (!pTypeLibImpl) return NULL;
3773 pHeader = pLib;
3775 TRACE_(typelib)("header:\n");
3776 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3777 pHeader->nrOfFileBlks );
3778 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3779 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3780 pHeader->SLTG_magic);
3781 return NULL;
3784 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3785 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3787 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3788 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3790 /* Next we have a magic block */
3791 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3793 /* Let's see if we're still in sync */
3794 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3795 sizeof(SLTG_COMPOBJ_MAGIC))) {
3796 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3797 return NULL;
3799 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3800 sizeof(SLTG_DIR_MAGIC))) {
3801 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3802 return NULL;
3805 pIndex = (SLTG_Index*)(pMagic+1);
3807 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3809 pFirstBlk = pPad9 + 1;
3811 /* We'll set up a ptr to the main library block, which is the last one. */
3813 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3814 pBlkEntry[order].next != 0;
3815 order = pBlkEntry[order].next - 1, i++) {
3816 pBlk = (char*)pBlk + pBlkEntry[order].len;
3818 pLibBlk = pBlk;
3820 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3822 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3823 interspersed */
3825 len += 0x40;
3827 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3829 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3830 sizeof(*pOtherTypeInfoBlks) *
3831 pTypeLibImpl->TypeInfoCount);
3834 ptr = (char*)pLibBlk + len;
3836 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3837 WORD w, extra;
3838 len = 0;
3840 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3842 w = *(WORD*)(ptr + 2);
3843 if(w != 0xffff) {
3844 len += w;
3845 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3846 w+1);
3847 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3848 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3850 w = *(WORD*)(ptr + 4 + len);
3851 if(w != 0xffff) {
3852 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3853 len += w;
3854 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3855 w+1);
3856 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3857 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3859 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3860 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3861 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3862 if(extra) {
3863 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3864 extra);
3865 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3866 len += extra;
3868 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3869 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3870 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3871 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3872 len += sizeof(SLTG_OtherTypeInfo);
3873 ptr += len;
3876 pAfterOTIBlks = ptr;
3878 /* Skip this WORD and get the next DWORD */
3879 len = *(DWORD*)(pAfterOTIBlks + 2);
3881 /* Now add this to pLibBLk look at what we're pointing at and
3882 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3883 dust and we should be pointing at the beginning of the name
3884 table */
3886 pNameTable = (char*)pLibBlk + len;
3888 switch(*(WORD*)pNameTable) {
3889 case 0xffff:
3890 break;
3891 case 0x0200:
3892 pNameTable += 0x20;
3893 break;
3894 default:
3895 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3896 break;
3899 pNameTable += 0x216;
3901 pNameTable += 2;
3903 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3905 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3908 /* Hopefully we now have enough ptrs set up to actually read in
3909 some TypeInfos. It's not clear which order to do them in, so
3910 I'll just follow the links along the BlkEntry chain and read
3911 them in the order in which they are in the file */
3913 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3915 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3916 pBlkEntry[order].next != 0;
3917 order = pBlkEntry[order].next - 1, i++) {
3919 SLTG_TypeInfoHeader *pTIHeader;
3920 SLTG_TypeInfoTail *pTITail;
3921 SLTG_MemberHeader *pMemHeader;
3923 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3924 pOtherTypeInfoBlks[i].index_name)) {
3925 FIXME_(typelib)("Index strings don't match\n");
3926 return NULL;
3929 pTIHeader = pBlk;
3930 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3931 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3932 return NULL;
3934 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3935 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3936 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3938 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3939 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3940 (*ppTypeInfoImpl)->index = i;
3941 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3942 pOtherTypeInfoBlks[i].name_offs +
3943 pNameTable);
3944 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3945 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3946 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3947 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3948 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3949 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3950 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3952 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3953 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3955 if((pTIHeader->typeflags1 & 7) != 2)
3956 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3957 if(pTIHeader->typeflags3 != 2)
3958 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3960 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3961 debugstr_w((*ppTypeInfoImpl)->Name),
3962 typekind_desc[pTIHeader->typekind],
3963 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3964 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3966 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3968 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3970 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3971 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3972 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3974 switch(pTIHeader->typekind) {
3975 case TKIND_ENUM:
3976 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3977 pTIHeader, pTITail);
3978 break;
3980 case TKIND_RECORD:
3981 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3982 pTIHeader, pTITail);
3983 break;
3985 case TKIND_INTERFACE:
3986 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3987 pTIHeader, pTITail);
3988 break;
3990 case TKIND_COCLASS:
3991 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3992 pTIHeader, pTITail);
3993 break;
3995 case TKIND_ALIAS:
3996 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3997 pTIHeader, pTITail);
3998 break;
4000 case TKIND_DISPATCH:
4001 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4002 pTIHeader, pTITail);
4003 break;
4005 case TKIND_MODULE:
4006 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4007 pTIHeader, pTITail);
4008 break;
4010 default:
4011 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4012 break;
4016 /* could get cFuncs, cVars and cImplTypes from here
4017 but we've already set those */
4018 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4019 X(06);
4020 X(16);
4021 X(18);
4022 X(1a);
4023 X(1e);
4024 X(24);
4025 X(26);
4026 X(2a);
4027 X(2c);
4028 X(2e);
4029 X(30);
4030 X(32);
4031 X(34);
4032 #undef X
4033 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4034 pBlk = (char*)pBlk + pBlkEntry[order].len;
4037 if(i != pTypeLibImpl->TypeInfoCount) {
4038 FIXME("Somehow processed %d TypeInfos\n", i);
4039 return NULL;
4042 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4043 return (ITypeLib2*)pTypeLibImpl;
4046 /* ITypeLib::QueryInterface
4048 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4049 ITypeLib2 * iface,
4050 REFIID riid,
4051 VOID **ppvObject)
4053 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4055 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4057 *ppvObject=NULL;
4058 if(IsEqualIID(riid, &IID_IUnknown) ||
4059 IsEqualIID(riid,&IID_ITypeLib)||
4060 IsEqualIID(riid,&IID_ITypeLib2))
4062 *ppvObject = This;
4065 if(*ppvObject)
4067 ITypeLib2_AddRef(iface);
4068 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4069 return S_OK;
4071 TRACE("-- Interface: E_NOINTERFACE\n");
4072 return E_NOINTERFACE;
4075 /* ITypeLib::AddRef
4077 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4079 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4080 ULONG ref = InterlockedIncrement(&This->ref);
4082 TRACE("(%p)->ref was %u\n",This, ref - 1);
4084 return ref;
4087 /* ITypeLib::Release
4089 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4091 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4092 ULONG ref = InterlockedDecrement(&This->ref);
4094 TRACE("(%p)->(%u)\n",This, ref);
4096 if (!ref)
4098 TLBImpLib *pImpLib, *pImpLibNext;
4099 TLBCustData *pCustData, *pCustDataNext;
4100 TLBRefType *ref_type;
4101 void *cursor2;
4102 int i;
4103 ITypeInfoImpl *pTI, *pTINext;
4105 /* remove cache entry */
4106 if(This->path)
4108 TRACE("removing from cache list\n");
4109 EnterCriticalSection(&cache_section);
4110 if (This->next) This->next->prev = This->prev;
4111 if (This->prev) This->prev->next = This->next;
4112 else tlb_cache_first = This->next;
4113 LeaveCriticalSection(&cache_section);
4114 HeapFree(GetProcessHeap(), 0, This->path);
4116 TRACE(" destroying ITypeLib(%p)\n",This);
4118 SysFreeString(This->Name);
4119 This->Name = NULL;
4121 SysFreeString(This->DocString);
4122 This->DocString = NULL;
4124 SysFreeString(This->HelpFile);
4125 This->HelpFile = NULL;
4127 SysFreeString(This->HelpStringDll);
4128 This->HelpStringDll = NULL;
4130 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4132 VariantClear(&pCustData->data);
4134 pCustDataNext = pCustData->next;
4135 TLB_Free(pCustData);
4138 for (i = 0; i < This->ctTypeDesc; i++)
4139 if (This->pTypeDesc[i].vt == VT_CARRAY)
4140 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4142 TLB_Free(This->pTypeDesc);
4144 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4146 if (pImpLib->pImpTypeLib)
4147 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4148 SysFreeString(pImpLib->name);
4150 pImpLibNext = pImpLib->next;
4151 TLB_Free(pImpLib);
4154 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4156 list_remove(&ref_type->entry);
4157 TLB_Free(ref_type);
4160 for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
4162 pTINext = pTI->next;
4163 ITypeInfo_fnDestroy(pTI);
4165 HeapFree(GetProcessHeap(),0,This);
4166 return 0;
4169 return ref;
4172 /* ITypeLib::GetTypeInfoCount
4174 * Returns the number of type descriptions in the type library
4176 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4178 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4179 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4180 return This->TypeInfoCount;
4183 /* ITypeLib::GetTypeInfo
4185 * retrieves the specified type description in the library.
4187 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4188 ITypeLib2 *iface,
4189 UINT index,
4190 ITypeInfo **ppTInfo)
4192 UINT i;
4194 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4195 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4197 TRACE("(%p)->(index=%d)\n", This, index);
4199 if (!ppTInfo) return E_INVALIDARG;
4201 /* search element n in list */
4202 for(i=0; i < index; i++)
4204 pTypeInfo = pTypeInfo->next;
4205 if (!pTypeInfo)
4207 TRACE("-- element not found\n");
4208 return TYPE_E_ELEMENTNOTFOUND;
4212 *ppTInfo = (ITypeInfo *) pTypeInfo;
4214 ITypeInfo_AddRef(*ppTInfo);
4215 TRACE("-- found (%p)\n",*ppTInfo);
4216 return S_OK;
4220 /* ITypeLibs::GetTypeInfoType
4222 * Retrieves the type of a type description.
4224 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4225 ITypeLib2 *iface,
4226 UINT index,
4227 TYPEKIND *pTKind)
4229 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4230 UINT i;
4231 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4233 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4234 return TYPE_E_ELEMENTNOTFOUND;
4236 TRACE("(%p) index %d\n", This, index);
4238 if(!pTKind) return E_INVALIDARG;
4240 /* search element n in list */
4241 for(i=0; i < index; i++)
4243 if(!pTInfo)
4245 TRACE("-- element not found\n");
4246 return TYPE_E_ELEMENTNOTFOUND;
4248 pTInfo = pTInfo->next;
4251 *pTKind = pTInfo->TypeAttr.typekind;
4252 TRACE("-- found Type (%d)\n", *pTKind);
4253 return S_OK;
4256 /* ITypeLib::GetTypeInfoOfGuid
4258 * Retrieves the type description that corresponds to the specified GUID.
4261 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4262 ITypeLib2 *iface,
4263 REFGUID guid,
4264 ITypeInfo **ppTInfo)
4266 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4267 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4269 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4271 if (!pTypeInfo)
4273 WARN("-- element not found\n");
4274 return TYPE_E_ELEMENTNOTFOUND;
4277 /* search linked list for guid */
4278 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4280 pTypeInfo = pTypeInfo->next;
4282 if (!pTypeInfo)
4284 /* end of list reached */
4285 WARN("-- element not found\n");
4286 return TYPE_E_ELEMENTNOTFOUND;
4290 TRACE("-- found (%p, %s)\n",
4291 pTypeInfo,
4292 debugstr_w(pTypeInfo->Name));
4294 *ppTInfo = (ITypeInfo*)pTypeInfo;
4295 ITypeInfo_AddRef(*ppTInfo);
4296 return S_OK;
4299 /* ITypeLib::GetLibAttr
4301 * Retrieves the structure that contains the library's attributes.
4304 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4305 ITypeLib2 *iface,
4306 LPTLIBATTR *ppTLibAttr)
4308 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4309 TRACE("(%p)\n",This);
4310 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4311 **ppTLibAttr = This->LibAttr;
4312 return S_OK;
4315 /* ITypeLib::GetTypeComp
4317 * Enables a client compiler to bind to a library's types, variables,
4318 * constants, and global functions.
4321 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4322 ITypeLib2 *iface,
4323 ITypeComp **ppTComp)
4325 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4327 TRACE("(%p)->(%p)\n",This,ppTComp);
4328 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4329 ITypeComp_AddRef(*ppTComp);
4331 return S_OK;
4334 /* ITypeLib::GetDocumentation
4336 * Retrieves the library's documentation string, the complete Help file name
4337 * and path, and the context identifier for the library Help topic in the Help
4338 * file.
4340 * On a successful return all non-null BSTR pointers will have been set,
4341 * possibly to NULL.
4343 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4344 ITypeLib2 *iface,
4345 INT index,
4346 BSTR *pBstrName,
4347 BSTR *pBstrDocString,
4348 DWORD *pdwHelpContext,
4349 BSTR *pBstrHelpFile)
4351 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4353 HRESULT result = E_INVALIDARG;
4355 ITypeInfo *pTInfo;
4358 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4359 This, index,
4360 pBstrName, pBstrDocString,
4361 pdwHelpContext, pBstrHelpFile);
4363 if(index<0)
4365 /* documentation for the typelib */
4366 if(pBstrName)
4368 if (This->Name)
4370 if(!(*pBstrName = SysAllocString(This->Name)))
4371 goto memerr1;
4373 else
4374 *pBstrName = NULL;
4376 if(pBstrDocString)
4378 if (This->DocString)
4380 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4381 goto memerr2;
4383 else if (This->Name)
4385 if(!(*pBstrDocString = SysAllocString(This->Name)))
4386 goto memerr2;
4388 else
4389 *pBstrDocString = NULL;
4391 if(pdwHelpContext)
4393 *pdwHelpContext = This->dwHelpContext;
4395 if(pBstrHelpFile)
4397 if (This->HelpFile)
4399 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4400 goto memerr3;
4402 else
4403 *pBstrHelpFile = NULL;
4406 result = S_OK;
4408 else
4410 /* for a typeinfo */
4411 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4413 if(SUCCEEDED(result))
4415 result = ITypeInfo_GetDocumentation(pTInfo,
4416 MEMBERID_NIL,
4417 pBstrName,
4418 pBstrDocString,
4419 pdwHelpContext, pBstrHelpFile);
4421 ITypeInfo_Release(pTInfo);
4424 return result;
4425 memerr3:
4426 if (pBstrDocString) SysFreeString (*pBstrDocString);
4427 memerr2:
4428 if (pBstrName) SysFreeString (*pBstrName);
4429 memerr1:
4430 return STG_E_INSUFFICIENTMEMORY;
4433 /* ITypeLib::IsName
4435 * Indicates whether a passed-in string contains the name of a type or member
4436 * described in the library.
4439 static HRESULT WINAPI ITypeLib2_fnIsName(
4440 ITypeLib2 *iface,
4441 LPOLESTR szNameBuf,
4442 ULONG lHashVal,
4443 BOOL *pfName)
4445 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4446 ITypeInfoImpl *pTInfo;
4447 TLBFuncDesc *pFInfo;
4448 TLBVarDesc *pVInfo;
4449 int i;
4450 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4452 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4453 pfName);
4455 *pfName=TRUE;
4456 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4457 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4458 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4459 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4460 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4461 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4462 goto ITypeLib2_fnIsName_exit;
4464 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4465 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4468 *pfName=FALSE;
4470 ITypeLib2_fnIsName_exit:
4471 TRACE("(%p)slow! search for %s: %s found!\n", This,
4472 debugstr_w(szNameBuf), *pfName?"NOT":"");
4474 return S_OK;
4477 /* ITypeLib::FindName
4479 * Finds occurrences of a type description in a type library. This may be used
4480 * to quickly verify that a name exists in a type library.
4483 static HRESULT WINAPI ITypeLib2_fnFindName(
4484 ITypeLib2 *iface,
4485 LPOLESTR szNameBuf,
4486 ULONG lHashVal,
4487 ITypeInfo **ppTInfo,
4488 MEMBERID *rgMemId,
4489 UINT16 *pcFound)
4491 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4492 ITypeInfoImpl *pTInfo;
4493 TLBFuncDesc *pFInfo;
4494 TLBVarDesc *pVInfo;
4495 int i,j = 0;
4496 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4498 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4499 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4500 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4501 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4502 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4503 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4504 goto ITypeLib2_fnFindName_exit;
4507 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4508 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4509 continue;
4510 ITypeLib2_fnFindName_exit:
4511 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4512 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4513 j++;
4515 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4516 This, *pcFound, debugstr_w(szNameBuf), j);
4518 *pcFound=j;
4520 return S_OK;
4523 /* ITypeLib::ReleaseTLibAttr
4525 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4528 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4529 ITypeLib2 *iface,
4530 TLIBATTR *pTLibAttr)
4532 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4533 TRACE("freeing (%p)\n",This);
4534 HeapFree(GetProcessHeap(),0,pTLibAttr);
4538 /* ITypeLib2::GetCustData
4540 * gets the custom data
4542 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4543 ITypeLib2 * iface,
4544 REFGUID guid,
4545 VARIANT *pVarVal)
4547 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4548 TLBCustData *pCData;
4550 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4552 if( IsEqualIID(guid, &pCData->guid)) break;
4555 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4557 if(pCData)
4559 VariantInit( pVarVal);
4560 VariantCopy( pVarVal, &pCData->data);
4561 return S_OK;
4563 return E_INVALIDARG; /* FIXME: correct? */
4566 /* ITypeLib2::GetLibStatistics
4568 * Returns statistics about a type library that are required for efficient
4569 * sizing of hash tables.
4572 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4573 ITypeLib2 * iface,
4574 ULONG *pcUniqueNames,
4575 ULONG *pcchUniqueNames)
4577 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4579 FIXME("(%p): stub!\n", This);
4581 if(pcUniqueNames) *pcUniqueNames=1;
4582 if(pcchUniqueNames) *pcchUniqueNames=1;
4583 return S_OK;
4586 /* ITypeLib2::GetDocumentation2
4588 * Retrieves the library's documentation string, the complete Help file name
4589 * and path, the localization context to use, and the context ID for the
4590 * library Help topic in the Help file.
4593 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4594 ITypeLib2 * iface,
4595 INT index,
4596 LCID lcid,
4597 BSTR *pbstrHelpString,
4598 DWORD *pdwHelpStringContext,
4599 BSTR *pbstrHelpStringDll)
4601 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4602 HRESULT result;
4603 ITypeInfo *pTInfo;
4605 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4607 /* the help string should be obtained from the helpstringdll,
4608 * using the _DLLGetDocumentation function, based on the supplied
4609 * lcid. Nice to do sometime...
4611 if(index<0)
4613 /* documentation for the typelib */
4614 if(pbstrHelpString)
4615 *pbstrHelpString=SysAllocString(This->DocString);
4616 if(pdwHelpStringContext)
4617 *pdwHelpStringContext=This->dwHelpContext;
4618 if(pbstrHelpStringDll)
4619 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4621 result = S_OK;
4623 else
4625 /* for a typeinfo */
4626 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4628 if(SUCCEEDED(result))
4630 ITypeInfo2 * pTInfo2;
4631 result = ITypeInfo_QueryInterface(pTInfo,
4632 &IID_ITypeInfo2,
4633 (LPVOID*) &pTInfo2);
4635 if(SUCCEEDED(result))
4637 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4638 MEMBERID_NIL,
4639 lcid,
4640 pbstrHelpString,
4641 pdwHelpStringContext,
4642 pbstrHelpStringDll);
4644 ITypeInfo2_Release(pTInfo2);
4647 ITypeInfo_Release(pTInfo);
4650 return result;
4653 /* ITypeLib2::GetAllCustData
4655 * Gets all custom data items for the library.
4658 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4659 ITypeLib2 * iface,
4660 CUSTDATA *pCustData)
4662 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4663 TLBCustData *pCData;
4664 int i;
4665 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4666 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4667 if(pCustData->prgCustData ){
4668 pCustData->cCustData=This->ctCustData;
4669 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4670 pCustData->prgCustData[i].guid=pCData->guid;
4671 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4673 }else{
4674 ERR(" OUT OF MEMORY!\n");
4675 return E_OUTOFMEMORY;
4677 return S_OK;
4680 static const ITypeLib2Vtbl tlbvt = {
4681 ITypeLib2_fnQueryInterface,
4682 ITypeLib2_fnAddRef,
4683 ITypeLib2_fnRelease,
4684 ITypeLib2_fnGetTypeInfoCount,
4685 ITypeLib2_fnGetTypeInfo,
4686 ITypeLib2_fnGetTypeInfoType,
4687 ITypeLib2_fnGetTypeInfoOfGuid,
4688 ITypeLib2_fnGetLibAttr,
4689 ITypeLib2_fnGetTypeComp,
4690 ITypeLib2_fnGetDocumentation,
4691 ITypeLib2_fnIsName,
4692 ITypeLib2_fnFindName,
4693 ITypeLib2_fnReleaseTLibAttr,
4695 ITypeLib2_fnGetCustData,
4696 ITypeLib2_fnGetLibStatistics,
4697 ITypeLib2_fnGetDocumentation2,
4698 ITypeLib2_fnGetAllCustData
4702 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4704 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4706 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4709 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4711 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4713 return ITypeLib2_AddRef((ITypeLib2 *)This);
4716 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4718 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4720 return ITypeLib2_Release((ITypeLib2 *)This);
4723 static HRESULT WINAPI ITypeLibComp_fnBind(
4724 ITypeComp * iface,
4725 OLECHAR * szName,
4726 ULONG lHash,
4727 WORD wFlags,
4728 ITypeInfo ** ppTInfo,
4729 DESCKIND * pDescKind,
4730 BINDPTR * pBindPtr)
4732 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4733 ITypeInfoImpl *pTypeInfo;
4734 int typemismatch=0;
4736 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4738 *pDescKind = DESCKIND_NONE;
4739 pBindPtr->lptcomp = NULL;
4740 *ppTInfo = NULL;
4742 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4744 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4746 /* FIXME: check wFlags here? */
4747 /* FIXME: we should use a hash table to look this info up using lHash
4748 * instead of an O(n) search */
4749 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4750 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4752 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4754 *pDescKind = DESCKIND_TYPECOMP;
4755 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4756 ITypeComp_AddRef(pBindPtr->lptcomp);
4757 TRACE("module or enum: %s\n", debugstr_w(szName));
4758 return S_OK;
4762 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4763 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4765 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4766 HRESULT hr;
4768 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4769 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4771 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4772 return S_OK;
4774 else if (hr == TYPE_E_TYPEMISMATCH)
4775 typemismatch = 1;
4778 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4779 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4781 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4782 HRESULT hr;
4783 ITypeInfo *subtypeinfo;
4784 BINDPTR subbindptr;
4785 DESCKIND subdesckind;
4787 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4788 &subtypeinfo, &subdesckind, &subbindptr);
4789 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4791 TYPEDESC tdesc_appobject;
4792 const VARDESC vardesc_appobject =
4794 -2, /* memid */
4795 NULL, /* lpstrSchema */
4797 0 /* oInst */
4800 /* ELEMDESC */
4802 /* TYPEDESC */
4804 &tdesc_appobject
4806 VT_PTR
4809 0, /* wVarFlags */
4810 VAR_STATIC /* varkind */
4813 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4814 tdesc_appobject.vt = VT_USERDEFINED;
4816 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4818 /* cleanup things filled in by Bind call so we can put our
4819 * application object data in there instead */
4820 switch (subdesckind)
4822 case DESCKIND_FUNCDESC:
4823 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4824 break;
4825 case DESCKIND_VARDESC:
4826 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4827 break;
4828 default:
4829 break;
4831 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4833 if (pTypeInfo->hreftype == -1)
4834 FIXME("no hreftype for interface %p\n", pTypeInfo);
4836 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4837 if (FAILED(hr))
4838 return hr;
4840 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4841 *ppTInfo = (ITypeInfo *)pTypeInfo;
4842 ITypeInfo_AddRef(*ppTInfo);
4843 return S_OK;
4845 else if (hr == TYPE_E_TYPEMISMATCH)
4846 typemismatch = 1;
4850 if (typemismatch)
4852 TRACE("type mismatch %s\n", debugstr_w(szName));
4853 return TYPE_E_TYPEMISMATCH;
4855 else
4857 TRACE("name not found %s\n", debugstr_w(szName));
4858 return S_OK;
4862 static HRESULT WINAPI ITypeLibComp_fnBindType(
4863 ITypeComp * iface,
4864 OLECHAR * szName,
4865 ULONG lHash,
4866 ITypeInfo ** ppTInfo,
4867 ITypeComp ** ppTComp)
4869 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4870 ITypeInfoImpl *pTypeInfo;
4872 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4874 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4876 /* FIXME: should use lHash to do the search */
4877 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4879 TRACE("returning %p\n", pTypeInfo);
4880 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4881 ITypeInfo_AddRef(*ppTInfo);
4882 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4883 ITypeComp_AddRef(*ppTComp);
4884 return S_OK;
4888 TRACE("not found\n");
4889 *ppTInfo = NULL;
4890 *ppTComp = NULL;
4891 return S_OK;
4894 static const ITypeCompVtbl tlbtcvt =
4897 ITypeLibComp_fnQueryInterface,
4898 ITypeLibComp_fnAddRef,
4899 ITypeLibComp_fnRelease,
4901 ITypeLibComp_fnBind,
4902 ITypeLibComp_fnBindType
4905 /*================== ITypeInfo(2) Methods ===================================*/
4906 static ITypeInfo2 * ITypeInfo_Constructor(void)
4908 ITypeInfoImpl * pTypeInfoImpl;
4910 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4911 if (pTypeInfoImpl)
4913 pTypeInfoImpl->lpVtbl = &tinfvt;
4914 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4915 pTypeInfoImpl->ref = 0;
4916 pTypeInfoImpl->hreftype = -1;
4917 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4918 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4920 TRACE("(%p)\n", pTypeInfoImpl);
4921 return (ITypeInfo2*) pTypeInfoImpl;
4924 /* ITypeInfo::QueryInterface
4926 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4927 ITypeInfo2 *iface,
4928 REFIID riid,
4929 VOID **ppvObject)
4931 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4933 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4935 *ppvObject=NULL;
4936 if(IsEqualIID(riid, &IID_IUnknown) ||
4937 IsEqualIID(riid,&IID_ITypeInfo)||
4938 IsEqualIID(riid,&IID_ITypeInfo2))
4939 *ppvObject = This;
4941 if(*ppvObject){
4942 ITypeInfo_AddRef(iface);
4943 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4944 return S_OK;
4946 TRACE("-- Interface: E_NOINTERFACE\n");
4947 return E_NOINTERFACE;
4950 /* ITypeInfo::AddRef
4952 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4954 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4955 ULONG ref = InterlockedIncrement(&This->ref);
4957 TRACE("(%p)->ref is %u\n",This, ref);
4959 if (ref == 1 /* incremented from 0 */)
4960 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4962 return ref;
4965 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This)
4967 TLBFuncDesc *pFInfo, *pFInfoNext;
4968 TLBVarDesc *pVInfo, *pVInfoNext;
4969 TLBImplType *pImpl, *pImplNext;
4971 TRACE("destroying ITypeInfo(%p)\n",This);
4973 SysFreeString(This->Name);
4974 This->Name = NULL;
4976 SysFreeString(This->DocString);
4977 This->DocString = NULL;
4979 SysFreeString(This->DllName);
4980 This->DllName = NULL;
4982 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4984 INT i;
4985 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4987 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4988 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4990 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4991 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4993 SysFreeString(pFInfo->pParamDesc[i].Name);
4995 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4996 TLB_Free(pFInfo->pParamDesc);
4997 TLB_FreeCustData(pFInfo->pCustData);
4998 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
4999 SysFreeString(pFInfo->Entry);
5000 SysFreeString(pFInfo->HelpString);
5001 SysFreeString(pFInfo->Name);
5003 pFInfoNext = pFInfo->next;
5004 TLB_Free(pFInfo);
5006 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5008 if (pVInfo->vardesc.varkind == VAR_CONST)
5010 VariantClear(pVInfo->vardesc.u.lpvarValue);
5011 TLB_Free(pVInfo->vardesc.u.lpvarValue);
5013 TLB_FreeCustData(pVInfo->pCustData);
5014 SysFreeString(pVInfo->Name);
5015 pVInfoNext = pVInfo->next;
5016 TLB_Free(pVInfo);
5018 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5020 TLB_FreeCustData(pImpl->pCustData);
5021 pImplNext = pImpl->next;
5022 TLB_Free(pImpl);
5024 TLB_FreeCustData(This->pCustData);
5026 HeapFree(GetProcessHeap(), 0, This);
5029 /* ITypeInfo::Release
5031 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5033 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5034 ULONG ref = InterlockedDecrement(&This->ref);
5036 TRACE("(%p)->(%u)\n",This, ref);
5038 if (!ref)
5040 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5041 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5042 if (not_attached_to_typelib)
5043 HeapFree(GetProcessHeap(), 0, This);
5044 /* otherwise This will be freed when typelib is freed */
5047 return ref;
5050 /* ITypeInfo::GetTypeAttr
5052 * Retrieves a TYPEATTR structure that contains the attributes of the type
5053 * description.
5056 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5057 LPTYPEATTR *ppTypeAttr)
5059 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5060 SIZE_T size;
5062 TRACE("(%p)\n",This);
5064 size = sizeof(**ppTypeAttr);
5065 if (This->TypeAttr.typekind == TKIND_ALIAS)
5066 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5068 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5069 if (!*ppTypeAttr)
5070 return E_OUTOFMEMORY;
5072 **ppTypeAttr = This->TypeAttr;
5074 if (This->TypeAttr.typekind == TKIND_ALIAS)
5075 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5076 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5078 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5079 /* This should include all the inherited funcs */
5080 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5081 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5082 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5084 return S_OK;
5087 /* ITypeInfo::GetTypeComp
5089 * Retrieves the ITypeComp interface for the type description, which enables a
5090 * client compiler to bind to the type description's members.
5093 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5094 ITypeComp * *ppTComp)
5096 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5098 TRACE("(%p)->(%p)\n", This, ppTComp);
5100 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5101 ITypeComp_AddRef(*ppTComp);
5102 return S_OK;
5105 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5107 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5108 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5109 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5110 return size;
5113 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5115 *dest = *src;
5116 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5117 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5119 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5120 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5121 *buffer += sizeof(PARAMDESCEX);
5122 *pparamdescex_dest = *pparamdescex_src;
5123 VariantInit(&pparamdescex_dest->varDefaultValue);
5124 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5125 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5127 else
5128 dest->u.paramdesc.pparamdescex = NULL;
5129 return S_OK;
5132 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5134 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5135 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5138 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5140 FUNCDESC *dest;
5141 char *buffer;
5142 SIZE_T size = sizeof(*src);
5143 SHORT i;
5144 HRESULT hr;
5146 size += sizeof(*src->lprgscode) * src->cScodes;
5147 size += TLB_SizeElemDesc(&src->elemdescFunc);
5148 for (i = 0; i < src->cParams; i++)
5150 size += sizeof(ELEMDESC);
5151 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5154 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5155 if (!dest) return E_OUTOFMEMORY;
5157 *dest = *src;
5158 if (dispinterface) /* overwrite funckind */
5159 dest->funckind = FUNC_DISPATCH;
5160 buffer = (char *)(dest + 1);
5162 dest->lprgscode = (SCODE *)buffer;
5163 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5164 buffer += sizeof(*src->lprgscode) * src->cScodes;
5166 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5167 if (FAILED(hr))
5169 SysFreeString((BSTR)dest);
5170 return hr;
5173 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5174 buffer += sizeof(ELEMDESC) * src->cParams;
5175 for (i = 0; i < src->cParams; i++)
5177 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5178 if (FAILED(hr))
5179 break;
5181 if (FAILED(hr))
5183 /* undo the above actions */
5184 for (i = i - 1; i >= 0; i--)
5185 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5186 TLB_FreeElemDesc(&dest->elemdescFunc);
5187 SysFreeString((BSTR)dest);
5188 return hr;
5191 /* special treatment for dispinterfaces: this makes functions appear
5192 * to return their [retval] value when it is really returning an
5193 * HRESULT */
5194 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5196 if (dest->cParams &&
5197 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5199 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5200 if (elemdesc->tdesc.vt != VT_PTR)
5202 ERR("elemdesc should have started with VT_PTR instead of:\n");
5203 if (ERR_ON(ole))
5204 dump_ELEMDESC(elemdesc);
5205 return E_UNEXPECTED;
5208 /* copy last parameter to the return value. we are using a flat
5209 * buffer so there is no danger of leaking memory in
5210 * elemdescFunc */
5211 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5213 /* remove the last parameter */
5214 dest->cParams--;
5216 else
5217 /* otherwise this function is made to appear to have no return
5218 * value */
5219 dest->elemdescFunc.tdesc.vt = VT_VOID;
5223 *dest_ptr = dest;
5224 return S_OK;
5227 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5229 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5230 const TLBFuncDesc *pFDesc;
5231 UINT i;
5233 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5236 if (pFDesc)
5238 *ppFuncDesc = &pFDesc->funcdesc;
5239 return S_OK;
5242 return TYPE_E_ELEMENTNOTFOUND;
5245 /* internal function to make the inherited interfaces' methods appear
5246 * part of the interface */
5247 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5248 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5250 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5251 HRESULT hr;
5252 UINT implemented_funcs = 0;
5254 if (funcs)
5255 *funcs = 0;
5256 else
5257 *hrefoffset = DISPATCH_HREF_OFFSET;
5259 if(This->impltypelist)
5261 ITypeInfo *pSubTypeInfo;
5262 UINT sub_funcs;
5264 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5265 if (FAILED(hr))
5266 return hr;
5268 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5269 index,
5270 ppFuncDesc,
5271 &sub_funcs, hrefoffset);
5272 implemented_funcs += sub_funcs;
5273 ITypeInfo_Release(pSubTypeInfo);
5274 if (SUCCEEDED(hr))
5275 return hr;
5276 *hrefoffset += DISPATCH_HREF_OFFSET;
5279 if (funcs)
5280 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5281 else
5282 *hrefoffset = 0;
5284 if (index < implemented_funcs)
5285 return E_INVALIDARG;
5286 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5287 ppFuncDesc);
5290 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5292 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5293 while (TRUE)
5295 switch (pTypeDesc->vt)
5297 case VT_USERDEFINED:
5298 pTypeDesc->u.hreftype += hrefoffset;
5299 return;
5300 case VT_PTR:
5301 case VT_SAFEARRAY:
5302 pTypeDesc = pTypeDesc->u.lptdesc;
5303 break;
5304 case VT_CARRAY:
5305 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5306 break;
5307 default:
5308 return;
5313 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5315 SHORT i;
5316 for (i = 0; i < pFuncDesc->cParams; i++)
5317 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5318 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5321 /* ITypeInfo::GetFuncDesc
5323 * Retrieves the FUNCDESC structure that contains information about a
5324 * specified function.
5327 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5328 LPFUNCDESC *ppFuncDesc)
5330 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5331 const FUNCDESC *internal_funcdesc;
5332 HRESULT hr;
5333 UINT hrefoffset = 0;
5335 TRACE("(%p) index %d\n", This, index);
5337 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5338 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5339 &internal_funcdesc, NULL,
5340 &hrefoffset);
5341 else
5342 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5343 &internal_funcdesc);
5344 if (FAILED(hr))
5346 WARN("description for function %d not found\n", index);
5347 return hr;
5350 hr = TLB_AllocAndInitFuncDesc(
5351 internal_funcdesc,
5352 ppFuncDesc,
5353 This->TypeAttr.typekind == TKIND_DISPATCH);
5355 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5356 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5358 TRACE("-- 0x%08x\n", hr);
5359 return hr;
5362 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5364 VARDESC *dest;
5365 char *buffer;
5366 SIZE_T size = sizeof(*src);
5367 HRESULT hr;
5369 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5370 if (src->varkind == VAR_CONST)
5371 size += sizeof(VARIANT);
5372 size += TLB_SizeElemDesc(&src->elemdescVar);
5374 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5375 if (!dest) return E_OUTOFMEMORY;
5377 *dest = *src;
5378 buffer = (char *)(dest + 1);
5379 if (src->lpstrSchema)
5381 int len;
5382 dest->lpstrSchema = (LPOLESTR)buffer;
5383 len = strlenW(src->lpstrSchema);
5384 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5385 buffer += (len + 1) * sizeof(WCHAR);
5388 if (src->varkind == VAR_CONST)
5390 HRESULT hr;
5392 dest->u.lpvarValue = (VARIANT *)buffer;
5393 *dest->u.lpvarValue = *src->u.lpvarValue;
5394 buffer += sizeof(VARIANT);
5395 VariantInit(dest->u.lpvarValue);
5396 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5397 if (FAILED(hr))
5399 SysFreeString((BSTR)dest);
5400 return hr;
5403 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5404 if (FAILED(hr))
5406 if (src->varkind == VAR_CONST)
5407 VariantClear(dest->u.lpvarValue);
5408 SysFreeString((BSTR)dest);
5409 return hr;
5411 *dest_ptr = dest;
5412 return S_OK;
5415 /* ITypeInfo::GetVarDesc
5417 * Retrieves a VARDESC structure that describes the specified variable.
5420 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5421 LPVARDESC *ppVarDesc)
5423 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5424 UINT i;
5425 const TLBVarDesc *pVDesc;
5427 TRACE("(%p) index %d\n", This, index);
5429 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5432 if (pVDesc)
5433 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5435 return E_INVALIDARG;
5438 /* ITypeInfo_GetNames
5440 * Retrieves the variable with the specified member ID (or the name of the
5441 * property or method and its parameters) that correspond to the specified
5442 * function ID.
5444 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5445 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5447 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5448 const TLBFuncDesc *pFDesc;
5449 const TLBVarDesc *pVDesc;
5450 int i;
5451 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5452 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5453 if(pFDesc)
5455 /* function found, now return function and parameter names */
5456 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5458 if(!i)
5459 *rgBstrNames=SysAllocString(pFDesc->Name);
5460 else
5461 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5463 *pcNames=i;
5465 else
5467 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5468 if(pVDesc)
5470 *rgBstrNames=SysAllocString(pVDesc->Name);
5471 *pcNames=1;
5473 else
5475 if(This->impltypelist &&
5476 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5477 /* recursive search */
5478 ITypeInfo *pTInfo;
5479 HRESULT result;
5480 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5481 &pTInfo);
5482 if(SUCCEEDED(result))
5484 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5485 ITypeInfo_Release(pTInfo);
5486 return result;
5488 WARN("Could not search inherited interface!\n");
5490 else
5492 WARN("no names found\n");
5494 *pcNames=0;
5495 return TYPE_E_ELEMENTNOTFOUND;
5498 return S_OK;
5502 /* ITypeInfo::GetRefTypeOfImplType
5504 * If a type description describes a COM class, it retrieves the type
5505 * description of the implemented interface types. For an interface,
5506 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5507 * if any exist.
5510 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5511 ITypeInfo2 *iface,
5512 UINT index,
5513 HREFTYPE *pRefType)
5515 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5516 UINT i;
5517 HRESULT hr = S_OK;
5518 const TLBImplType *pImpl = This->impltypelist;
5520 TRACE("(%p) index %d\n", This, index);
5521 if (TRACE_ON(ole)) dump_TypeInfo(This);
5523 if(index==(UINT)-1)
5525 /* only valid on dual interfaces;
5526 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5528 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5530 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5532 *pRefType = -1;
5534 else
5536 hr = TYPE_E_ELEMENTNOTFOUND;
5539 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5541 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5542 *pRefType = This->pTypeLib->dispatch_href;
5544 else
5546 /* get element n from linked list */
5547 for(i=0; pImpl && i<index; i++)
5549 pImpl = pImpl->next;
5552 if (pImpl)
5553 *pRefType = pImpl->hRef;
5554 else
5555 hr = TYPE_E_ELEMENTNOTFOUND;
5558 if(TRACE_ON(ole))
5560 if(SUCCEEDED(hr))
5561 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5562 else
5563 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5566 return hr;
5569 /* ITypeInfo::GetImplTypeFlags
5571 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5572 * or base interface in a type description.
5574 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5575 UINT index, INT *pImplTypeFlags)
5577 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5578 UINT i;
5579 TLBImplType *pImpl;
5581 TRACE("(%p) index %d\n", This, index);
5582 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5583 i++, pImpl=pImpl->next)
5585 if(i==index && pImpl){
5586 *pImplTypeFlags=pImpl->implflags;
5587 return S_OK;
5589 *pImplTypeFlags=0;
5591 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5592 return S_OK;
5594 WARN("ImplType %d not found\n", index);
5595 return TYPE_E_ELEMENTNOTFOUND;
5598 /* GetIDsOfNames
5599 * Maps between member names and member IDs, and parameter names and
5600 * parameter IDs.
5602 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5603 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5605 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5606 const TLBFuncDesc *pFDesc;
5607 const TLBVarDesc *pVDesc;
5608 HRESULT ret=S_OK;
5609 UINT i;
5611 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5612 cNames);
5614 /* init out parameters in case of failure */
5615 for (i = 0; i < cNames; i++)
5616 pMemId[i] = MEMBERID_NIL;
5618 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5619 int j;
5620 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5621 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5622 for(i=1; i < cNames; i++){
5623 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5624 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5625 break;
5626 if( j<pFDesc->funcdesc.cParams)
5627 pMemId[i]=j;
5628 else
5629 ret=DISP_E_UNKNOWNNAME;
5631 TRACE("-- 0x%08x\n", ret);
5632 return ret;
5635 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5636 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5637 if(cNames) *pMemId=pVDesc->vardesc.memid;
5638 return ret;
5641 /* not found, see if it can be found in an inherited interface */
5642 if(This->impltypelist) {
5643 /* recursive search */
5644 ITypeInfo *pTInfo;
5645 ret=ITypeInfo_GetRefTypeInfo(iface,
5646 This->impltypelist->hRef, &pTInfo);
5647 if(SUCCEEDED(ret)){
5648 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5649 ITypeInfo_Release(pTInfo);
5650 return ret;
5652 WARN("Could not search inherited interface!\n");
5653 } else
5654 WARN("no names found\n");
5655 return DISP_E_UNKNOWNNAME;
5659 #ifdef __i386__
5661 extern DWORD CDECL call_method( void *func, int nb_args, const DWORD *args );
5662 __ASM_GLOBAL_FUNC( call_method,
5663 "pushl %ebp\n\t"
5664 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5665 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5666 "movl %esp,%ebp\n\t"
5667 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5668 "pushl %esi\n\t"
5669 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5670 "pushl %edi\n\t"
5671 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5672 "movl 12(%ebp),%edx\n\t"
5673 "shll $2,%edx\n\t"
5674 "jz 1f\n\t"
5675 "subl %edx,%esp\n\t"
5676 "andl $~15,%esp\n\t"
5677 "movl 12(%ebp),%ecx\n\t"
5678 "movl 16(%ebp),%esi\n\t"
5679 "movl %esp,%edi\n\t"
5680 "cld\n\t"
5681 "rep; movsl\n"
5682 "1:\tcall *8(%ebp)\n\t"
5683 "leal -8(%ebp),%esp\n\t"
5684 "popl %edi\n\t"
5685 __ASM_CFI(".cfi_same_value %edi\n\t")
5686 "popl %esi\n\t"
5687 __ASM_CFI(".cfi_same_value %esi\n\t")
5688 "popl %ebp\n\t"
5689 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5690 __ASM_CFI(".cfi_same_value %ebp\n\t")
5691 "ret" )
5693 /* ITypeInfo::Invoke
5695 * Invokes a method, or accesses a property of an object, that implements the
5696 * interface described by the type description.
5698 DWORD
5699 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5700 DWORD res;
5702 if (TRACE_ON(ole)) {
5703 int i;
5704 TRACE("Calling %p(",func);
5705 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5706 if (nrargs > 30) TRACE("...");
5707 TRACE(")\n");
5710 switch (callconv) {
5711 case CC_STDCALL:
5712 case CC_CDECL:
5713 res = call_method( func, nrargs, args );
5714 break;
5715 default:
5716 FIXME("unsupported calling convention %d\n",callconv);
5717 res = -1;
5718 break;
5720 TRACE("returns %08x\n",res);
5721 return res;
5724 /* The size of the argument on the stack in DWORD units (in all x86 call
5725 * convetions the arguments on the stack are DWORD-aligned)
5727 static int _dispargsize(VARTYPE vt)
5729 switch (vt) {
5730 case VT_I8:
5731 case VT_UI8:
5732 return 8/sizeof(DWORD);
5733 case VT_R8:
5734 return sizeof(double)/sizeof(DWORD);
5735 case VT_DECIMAL:
5736 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5737 case VT_CY:
5738 return sizeof(CY)/sizeof(DWORD);
5739 case VT_DATE:
5740 return sizeof(DATE)/sizeof(DWORD);
5741 case VT_VARIANT:
5742 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5743 case VT_RECORD:
5744 FIXME("VT_RECORD not implemented\n");
5745 return 1;
5746 default:
5747 return 1;
5750 #endif /* __i386__ */
5752 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5754 HRESULT hr = S_OK;
5755 ITypeInfo *tinfo2 = NULL;
5756 TYPEATTR *tattr = NULL;
5758 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5759 if (hr)
5761 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5762 "hr = 0x%08x\n",
5763 tdesc->u.hreftype, hr);
5764 return hr;
5766 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5767 if (hr)
5769 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5770 ITypeInfo_Release(tinfo2);
5771 return hr;
5774 switch (tattr->typekind)
5776 case TKIND_ENUM:
5777 *vt |= VT_I4;
5778 break;
5780 case TKIND_ALIAS:
5781 tdesc = &tattr->tdescAlias;
5782 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5783 break;
5785 case TKIND_INTERFACE:
5786 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5787 *vt |= VT_DISPATCH;
5788 else
5789 *vt |= VT_UNKNOWN;
5790 break;
5792 case TKIND_DISPATCH:
5793 *vt |= VT_DISPATCH;
5794 break;
5796 case TKIND_COCLASS:
5797 *vt |= VT_DISPATCH;
5798 break;
5800 case TKIND_RECORD:
5801 FIXME("TKIND_RECORD unhandled.\n");
5802 hr = E_NOTIMPL;
5803 break;
5805 case TKIND_UNION:
5806 FIXME("TKIND_UNION unhandled.\n");
5807 hr = E_NOTIMPL;
5808 break;
5810 default:
5811 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5812 hr = E_NOTIMPL;
5813 break;
5815 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5816 ITypeInfo_Release(tinfo2);
5817 return hr;
5820 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5822 HRESULT hr = S_OK;
5824 /* enforce only one level of pointer indirection */
5825 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5827 tdesc = tdesc->u.lptdesc;
5829 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5830 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5831 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5832 if ((tdesc->vt == VT_USERDEFINED) ||
5833 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5835 VARTYPE vt_userdefined = 0;
5836 const TYPEDESC *tdesc_userdefined = tdesc;
5837 if (tdesc->vt == VT_PTR)
5839 vt_userdefined = VT_BYREF;
5840 tdesc_userdefined = tdesc->u.lptdesc;
5842 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5843 if ((hr == S_OK) &&
5844 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5845 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5847 *vt |= vt_userdefined;
5848 return S_OK;
5851 *vt = VT_BYREF;
5854 switch (tdesc->vt)
5856 case VT_HRESULT:
5857 *vt |= VT_ERROR;
5858 break;
5859 case VT_USERDEFINED:
5860 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5861 break;
5862 case VT_VOID:
5863 case VT_CARRAY:
5864 case VT_PTR:
5865 case VT_LPSTR:
5866 case VT_LPWSTR:
5867 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5868 hr = DISP_E_BADVARTYPE;
5869 break;
5870 case VT_SAFEARRAY:
5871 *vt |= VT_ARRAY;
5872 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5873 break;
5874 case VT_INT:
5875 *vt |= VT_I4;
5876 break;
5877 case VT_UINT:
5878 *vt |= VT_UI4;
5879 break;
5880 default:
5881 *vt |= tdesc->vt;
5882 break;
5884 return hr;
5887 /***********************************************************************
5888 * DispCallFunc (OLEAUT32.@)
5890 * Invokes a function of the specified calling convention, passing the
5891 * specified arguments and returns the result.
5893 * PARAMS
5894 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5895 * oVft [I] The offset in the vtable. See notes.
5896 * cc [I] Calling convention of the function to call.
5897 * vtReturn [I] The return type of the function.
5898 * cActuals [I] Number of parameters.
5899 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5900 * prgpvarg [I] The arguments to pass.
5901 * pvargResult [O] The return value of the function. Can be NULL.
5903 * RETURNS
5904 * Success: S_OK.
5905 * Failure: HRESULT code.
5907 * NOTES
5908 * The HRESULT return value of this function is not affected by the return
5909 * value of the user supplied function, which is returned in pvargResult.
5911 * If pvInstance is NULL then a non-object function is to be called and oVft
5912 * is the address of the function to call.
5914 * The cc parameter can be one of the following values:
5915 *|CC_FASTCALL
5916 *|CC_CDECL
5917 *|CC_PASCAL
5918 *|CC_STDCALL
5919 *|CC_FPFASTCALL
5920 *|CC_SYSCALL
5921 *|CC_MPWCDECL
5922 *|CC_MPWPASCAL
5925 HRESULT WINAPI
5926 DispCallFunc(
5927 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5928 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5930 #ifdef __i386__
5931 int argsize, argspos;
5932 UINT i;
5933 DWORD *args;
5934 HRESULT hres;
5936 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5937 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5938 pvargResult, V_VT(pvargResult));
5940 argsize = 0;
5941 if (pvInstance)
5942 argsize++; /* for This pointer */
5944 for (i=0;i<cActuals;i++)
5946 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5947 dump_Variant(prgpvarg[i]);
5948 argsize += _dispargsize(prgvt[i]);
5950 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5952 argspos = 0;
5953 if (pvInstance)
5955 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5956 argspos++;
5959 for (i=0;i<cActuals;i++)
5961 VARIANT *arg = prgpvarg[i];
5962 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5963 if (prgvt[i] == VT_VARIANT)
5964 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5965 else
5966 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5967 argspos += _dispargsize(prgvt[i]);
5970 if (pvInstance)
5972 FARPROC *vtable = *(FARPROC**)pvInstance;
5973 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5975 else
5976 /* if we aren't invoking an object then the function pointer is stored
5977 * in oVft */
5978 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5980 if (pvargResult && (vtReturn != VT_EMPTY))
5982 TRACE("Method returned 0x%08x\n",hres);
5983 V_VT(pvargResult) = vtReturn;
5984 V_UI4(pvargResult) = hres;
5986 HeapFree(GetProcessHeap(),0,args);
5987 return S_OK;
5988 #else
5989 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
5990 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
5991 return E_NOTIMPL;
5992 #endif
5995 #define INVBUF_ELEMENT_SIZE \
5996 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5997 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5998 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5999 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6000 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6001 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6002 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6003 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6005 static HRESULT WINAPI ITypeInfo_fnInvoke(
6006 ITypeInfo2 *iface,
6007 VOID *pIUnk,
6008 MEMBERID memid,
6009 UINT16 wFlags,
6010 DISPPARAMS *pDispParams,
6011 VARIANT *pVarResult,
6012 EXCEPINFO *pExcepInfo,
6013 UINT *pArgErr)
6015 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6016 int i;
6017 unsigned int var_index;
6018 TYPEKIND type_kind;
6019 HRESULT hres;
6020 const TLBFuncDesc *pFuncInfo;
6022 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6023 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6026 if (!pDispParams)
6028 ERR("NULL pDispParams not allowed\n");
6029 return E_INVALIDARG;
6032 dump_DispParms(pDispParams);
6034 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6036 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6037 pDispParams->cNamedArgs, pDispParams->cArgs);
6038 return E_INVALIDARG;
6041 /* we do this instead of using GetFuncDesc since it will return a fake
6042 * FUNCDESC for dispinterfaces and we want the real function description */
6043 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6044 if ((memid == pFuncInfo->funcdesc.memid) &&
6045 (wFlags & pFuncInfo->funcdesc.invkind))
6046 break;
6048 if (pFuncInfo) {
6049 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6051 if (TRACE_ON(ole))
6053 TRACE("invoking:\n");
6054 dump_TLBFuncDescOne(pFuncInfo);
6057 switch (func_desc->funckind) {
6058 case FUNC_PUREVIRTUAL:
6059 case FUNC_VIRTUAL: {
6060 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6061 VARIANT varresult;
6062 VARIANT retval; /* pointer for storing byref retvals in */
6063 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6064 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6065 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6066 UINT cNamedArgs = pDispParams->cNamedArgs;
6067 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6068 UINT vargs_converted=0;
6070 hres = S_OK;
6072 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6074 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6076 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6077 hres = DISP_E_PARAMNOTFOUND;
6078 goto func_fail;
6082 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6084 ERR("functions with the vararg attribute do not support named arguments\n");
6085 hres = DISP_E_NONAMEDARGS;
6086 goto func_fail;
6089 for (i = 0; i < func_desc->cParams; i++)
6091 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6092 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6093 if (FAILED(hres))
6094 goto func_fail;
6097 TRACE("changing args\n");
6098 for (i = 0; i < func_desc->cParams; i++)
6100 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6101 VARIANTARG *src_arg;
6103 if (wParamFlags & PARAMFLAG_FLCID)
6105 VARIANTARG *arg;
6106 arg = prgpvarg[i] = &rgvarg[i];
6107 V_VT(arg) = VT_I4;
6108 V_I4(arg) = This->pTypeLib->lcid;
6109 continue;
6112 src_arg = NULL;
6114 if (cNamedArgs)
6116 USHORT j;
6117 for (j = 0; j < cNamedArgs; j++)
6118 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6120 src_arg = &pDispParams->rgvarg[j];
6121 break;
6125 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6127 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6128 vargs_converted++;
6131 if (wParamFlags & PARAMFLAG_FRETVAL)
6133 /* under most conditions the caller is not allowed to
6134 * pass in a dispparam arg in the index of what would be
6135 * the retval parameter. however, there is an exception
6136 * where the extra parameter is used in an extra
6137 * IDispatch::Invoke below */
6138 if ((i < pDispParams->cArgs) &&
6139 ((func_desc->cParams != 1) || !pVarResult ||
6140 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6142 hres = DISP_E_BADPARAMCOUNT;
6143 break;
6146 /* note: this check is placed so that if the caller passes
6147 * in a VARIANTARG for the retval we just ignore it, like
6148 * native does */
6149 if (i == func_desc->cParams - 1)
6151 VARIANTARG *arg;
6152 arg = prgpvarg[i] = &rgvarg[i];
6153 memset(arg, 0, sizeof(*arg));
6154 V_VT(arg) = rgvt[i];
6155 memset(&retval, 0, sizeof(retval));
6156 V_BYREF(arg) = &retval;
6158 else
6160 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6161 hres = E_UNEXPECTED;
6162 break;
6165 else if (src_arg)
6167 dump_Variant(src_arg);
6169 if (rgvt[i] == VT_VARIANT)
6170 hres = VariantCopy(&rgvarg[i], src_arg);
6171 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6173 if (rgvt[i] == V_VT(src_arg))
6174 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6175 else
6177 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6178 if (wParamFlags & PARAMFLAG_FIN)
6179 hres = VariantCopy(&missing_arg[i], src_arg);
6180 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6182 V_VT(&rgvarg[i]) = rgvt[i];
6184 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6186 SAFEARRAY *a;
6187 SAFEARRAYBOUND bound;
6188 VARIANT *v;
6189 LONG j;
6190 bound.lLbound = 0;
6191 bound.cElements = pDispParams->cArgs-i;
6192 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6194 ERR("SafeArrayCreate failed\n");
6195 break;
6197 hres = SafeArrayAccessData(a, (LPVOID)&v);
6198 if (hres != S_OK)
6200 ERR("SafeArrayAccessData failed with %x\n", hres);
6201 break;
6203 for (j = 0; j < bound.cElements; j++)
6204 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6205 hres = SafeArrayUnaccessData(a);
6206 if (hres != S_OK)
6208 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6209 break;
6211 V_ARRAY(&rgvarg[i]) = a;
6212 V_VT(&rgvarg[i]) = rgvt[i];
6214 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6216 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6217 if (wParamFlags & PARAMFLAG_FIN)
6218 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6219 else
6220 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6221 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6222 V_VT(&rgvarg[i]) = rgvt[i];
6224 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6226 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6227 V_VT(&rgvarg[i]) = rgvt[i];
6229 else
6231 /* FIXME: this doesn't work for VT_BYREF arguments if
6232 * they are not the same type as in the paramdesc */
6233 V_VT(&rgvarg[i]) = V_VT(src_arg);
6234 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6235 V_VT(&rgvarg[i]) = rgvt[i];
6238 if (FAILED(hres))
6240 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6241 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6242 debugstr_VT(src_arg), debugstr_VF(src_arg));
6243 break;
6245 prgpvarg[i] = &rgvarg[i];
6247 else if (wParamFlags & PARAMFLAG_FOPT)
6249 VARIANTARG *arg;
6250 arg = prgpvarg[i] = &rgvarg[i];
6251 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6253 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6254 if (FAILED(hres))
6255 break;
6257 else
6259 VARIANTARG *missing_arg;
6260 /* if the function wants a pointer to a variant then
6261 * set that up, otherwise just pass the VT_ERROR in
6262 * the argument by value */
6263 if (rgvt[i] & VT_BYREF)
6265 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6266 V_VT(arg) = VT_VARIANT | VT_BYREF;
6267 V_VARIANTREF(arg) = missing_arg;
6269 else
6270 missing_arg = arg;
6271 V_VT(missing_arg) = VT_ERROR;
6272 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6275 else
6277 hres = DISP_E_BADPARAMCOUNT;
6278 break;
6281 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6283 /* VT_VOID is a special case for return types, so it is not
6284 * handled in the general function */
6285 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6286 V_VT(&varresult) = VT_EMPTY;
6287 else
6289 V_VT(&varresult) = 0;
6290 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6291 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6294 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6295 V_VT(&varresult), func_desc->cParams, rgvt,
6296 prgpvarg, &varresult);
6298 vargs_converted = 0;
6300 for (i = 0; i < func_desc->cParams; i++)
6302 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6303 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6305 if (wParamFlags & PARAMFLAG_FLCID)
6306 continue;
6307 else if (wParamFlags & PARAMFLAG_FRETVAL)
6309 if (TRACE_ON(ole))
6311 TRACE("[retval] value: ");
6312 dump_Variant(prgpvarg[i]);
6315 if (pVarResult)
6317 VariantInit(pVarResult);
6318 /* deref return value */
6319 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6322 VARIANT_ClearInd(prgpvarg[i]);
6324 else if (vargs_converted < pDispParams->cArgs)
6326 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6327 if (wParamFlags & PARAMFLAG_FOUT)
6329 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6331 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6333 if (FAILED(hres))
6335 ERR("failed to convert param %d to vt %d\n", i,
6336 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6337 break;
6341 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6342 func_desc->cParamsOpt < 0 &&
6343 i == func_desc->cParams-1)
6345 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6346 LONG j, ubound;
6347 VARIANT *v;
6348 hres = SafeArrayGetUBound(a, 1, &ubound);
6349 if (hres != S_OK)
6351 ERR("SafeArrayGetUBound failed with %x\n", hres);
6352 break;
6354 hres = SafeArrayAccessData(a, (LPVOID)&v);
6355 if (hres != S_OK)
6357 ERR("SafeArrayAccessData failed with %x\n", hres);
6358 break;
6360 for (j = 0; j <= ubound; j++)
6361 VariantClear(&v[j]);
6362 hres = SafeArrayUnaccessData(a);
6363 if (hres != S_OK)
6365 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6366 break;
6369 VariantClear(&rgvarg[i]);
6370 vargs_converted++;
6372 else if (wParamFlags & PARAMFLAG_FOPT)
6374 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6375 VariantClear(&rgvarg[i]);
6378 VariantClear(&missing_arg[i]);
6381 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6383 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6384 hres = DISP_E_EXCEPTION;
6385 if (pExcepInfo)
6387 IErrorInfo *pErrorInfo;
6388 pExcepInfo->scode = V_ERROR(&varresult);
6389 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6391 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6392 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6393 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6394 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6396 IErrorInfo_Release(pErrorInfo);
6400 if (V_VT(&varresult) != VT_ERROR)
6402 TRACE("varresult value: ");
6403 dump_Variant(&varresult);
6405 if (pVarResult)
6407 VariantClear(pVarResult);
6408 *pVarResult = varresult;
6410 else
6411 VariantClear(&varresult);
6414 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6415 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6416 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6417 (pDispParams->cArgs != 0))
6419 if (V_VT(pVarResult) == VT_DISPATCH)
6421 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6422 /* Note: not VariantClear; we still need the dispatch
6423 * pointer to be valid */
6424 VariantInit(pVarResult);
6425 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6426 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6427 pDispParams, pVarResult, pExcepInfo, pArgErr);
6428 IDispatch_Release(pDispatch);
6430 else
6432 VariantClear(pVarResult);
6433 hres = DISP_E_NOTACOLLECTION;
6437 func_fail:
6438 HeapFree(GetProcessHeap(), 0, buffer);
6439 break;
6441 case FUNC_DISPATCH: {
6442 IDispatch *disp;
6444 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6445 if (SUCCEEDED(hres)) {
6446 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6447 hres = IDispatch_Invoke(
6448 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6449 pVarResult,pExcepInfo,pArgErr
6451 if (FAILED(hres))
6452 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6453 IDispatch_Release(disp);
6454 } else
6455 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6456 break;
6458 default:
6459 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6460 hres = E_FAIL;
6461 break;
6464 TRACE("-- 0x%08x\n", hres);
6465 return hres;
6467 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6468 VARDESC *var_desc;
6470 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6471 if(FAILED(hres)) return hres;
6473 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6474 dump_VARDESC(var_desc);
6475 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6476 return E_NOTIMPL;
6479 /* not found, look for it in inherited interfaces */
6480 ITypeInfo2_GetTypeKind(iface, &type_kind);
6481 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6482 if(This->impltypelist) {
6483 /* recursive search */
6484 ITypeInfo *pTInfo;
6485 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6486 if(SUCCEEDED(hres)){
6487 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6488 ITypeInfo_Release(pTInfo);
6489 return hres;
6491 WARN("Could not search inherited interface!\n");
6494 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6495 return DISP_E_MEMBERNOTFOUND;
6498 /* ITypeInfo::GetDocumentation
6500 * Retrieves the documentation string, the complete Help file name and path,
6501 * and the context ID for the Help topic for a specified type description.
6503 * (Can be tested by the Visual Basic Editor in Word for instance.)
6505 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6506 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6507 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6509 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6510 const TLBFuncDesc *pFDesc;
6511 const TLBVarDesc *pVDesc;
6512 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6513 " HelpContext(%p) HelpFile(%p)\n",
6514 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6515 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6516 if(pBstrName)
6517 *pBstrName=SysAllocString(This->Name);
6518 if(pBstrDocString)
6519 *pBstrDocString=SysAllocString(This->DocString);
6520 if(pdwHelpContext)
6521 *pdwHelpContext=This->dwHelpContext;
6522 if(pBstrHelpFile)
6523 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6524 return S_OK;
6525 }else {/* for a member */
6526 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6527 if(pFDesc->funcdesc.memid==memid){
6528 if(pBstrName)
6529 *pBstrName = SysAllocString(pFDesc->Name);
6530 if(pBstrDocString)
6531 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6532 if(pdwHelpContext)
6533 *pdwHelpContext=pFDesc->helpcontext;
6534 return S_OK;
6536 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6537 if(pVDesc->vardesc.memid==memid){
6538 if(pBstrName)
6539 *pBstrName = SysAllocString(pVDesc->Name);
6540 if(pBstrDocString)
6541 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6542 if(pdwHelpContext)
6543 *pdwHelpContext=pVDesc->HelpContext;
6544 return S_OK;
6548 if(This->impltypelist &&
6549 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6550 /* recursive search */
6551 ITypeInfo *pTInfo;
6552 HRESULT result;
6553 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6554 &pTInfo);
6555 if(SUCCEEDED(result)) {
6556 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6557 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6558 ITypeInfo_Release(pTInfo);
6559 return result;
6561 WARN("Could not search inherited interface!\n");
6564 WARN("member %d not found\n", memid);
6565 return TYPE_E_ELEMENTNOTFOUND;
6568 /* ITypeInfo::GetDllEntry
6570 * Retrieves a description or specification of an entry point for a function
6571 * in a DLL.
6573 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6574 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6575 WORD *pwOrdinal)
6577 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6578 const TLBFuncDesc *pFDesc;
6580 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6582 if (pBstrDllName) *pBstrDllName = NULL;
6583 if (pBstrName) *pBstrName = NULL;
6584 if (pwOrdinal) *pwOrdinal = 0;
6586 if (This->TypeAttr.typekind != TKIND_MODULE)
6587 return TYPE_E_BADMODULEKIND;
6589 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6590 if(pFDesc->funcdesc.memid==memid){
6591 dump_TypeInfo(This);
6592 if (TRACE_ON(ole))
6593 dump_TLBFuncDescOne(pFDesc);
6595 if (pBstrDllName)
6596 *pBstrDllName = SysAllocString(This->DllName);
6598 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6599 if (pBstrName)
6600 *pBstrName = SysAllocString(pFDesc->Entry);
6601 if (pwOrdinal)
6602 *pwOrdinal = -1;
6603 return S_OK;
6605 if (pBstrName)
6606 *pBstrName = NULL;
6607 if (pwOrdinal)
6608 *pwOrdinal = LOWORD(pFDesc->Entry);
6609 return S_OK;
6611 return TYPE_E_ELEMENTNOTFOUND;
6614 /* internal function to make the inherited interfaces' methods appear
6615 * part of the interface */
6616 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6617 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6619 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6620 HRESULT hr;
6622 TRACE("%p, 0x%x\n", iface, *hRefType);
6624 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6626 ITypeInfo *pSubTypeInfo;
6628 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6629 if (FAILED(hr))
6630 return hr;
6632 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6633 hRefType, ppTInfo);
6634 ITypeInfo_Release(pSubTypeInfo);
6635 if (SUCCEEDED(hr))
6636 return hr;
6638 *hRefType -= DISPATCH_HREF_OFFSET;
6640 if (!(*hRefType & DISPATCH_HREF_MASK))
6641 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6642 else
6643 return E_FAIL;
6646 /* ITypeInfo::GetRefTypeInfo
6648 * If a type description references other type descriptions, it retrieves
6649 * the referenced type descriptions.
6651 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6652 ITypeInfo2 *iface,
6653 HREFTYPE hRefType,
6654 ITypeInfo **ppTInfo)
6656 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6657 HRESULT result = E_FAIL;
6659 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6661 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6662 ITypeInfo_AddRef(*ppTInfo);
6663 result = S_OK;
6665 else if (hRefType == -1 &&
6666 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6667 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6669 /* when we meet a DUAL dispinterface, we must create the interface
6670 * version of it.
6672 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6675 /* the interface version contains the same information as the dispinterface
6676 * copy the contents of the structs.
6678 *pTypeInfoImpl = *This;
6679 pTypeInfoImpl->ref = 0;
6681 /* change the type to interface */
6682 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6684 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6686 /* the AddRef implicitly adds a reference to the parent typelib, which
6687 * stops the copied data from being destroyed until the new typeinfo's
6688 * refcount goes to zero, but we need to signal to the new instance to
6689 * not free its data structures when it is destroyed */
6690 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6692 ITypeInfo_AddRef(*ppTInfo);
6694 result = S_OK;
6696 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6697 (This->TypeAttr.typekind == TKIND_DISPATCH))
6699 HREFTYPE href_dispatch = hRefType;
6700 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6701 } else {
6702 TLBRefType *ref_type;
6703 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6705 if(ref_type->reference == hRefType)
6706 break;
6708 if(&ref_type->entry == &This->pTypeLib->ref_list)
6710 FIXME("Can't find pRefType for ref %x\n", hRefType);
6711 goto end;
6713 if(hRefType != -1) {
6714 ITypeLib *pTLib = NULL;
6716 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6717 UINT Index;
6718 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6719 } else {
6720 if(ref_type->pImpTLInfo->pImpTypeLib) {
6721 TRACE("typeinfo in imported typelib that is already loaded\n");
6722 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6723 ITypeLib2_AddRef(pTLib);
6724 result = S_OK;
6725 } else {
6726 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6727 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6728 ref_type->pImpTLInfo->wVersionMajor,
6729 ref_type->pImpTLInfo->wVersionMinor,
6730 ref_type->pImpTLInfo->lcid,
6731 &pTLib);
6733 if(FAILED(result)) {
6734 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6735 result=LoadTypeLib(libnam, &pTLib);
6736 SysFreeString(libnam);
6738 if(SUCCEEDED(result)) {
6739 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6740 ITypeLib2_AddRef(pTLib);
6744 if(SUCCEEDED(result)) {
6745 if(ref_type->index == TLB_REF_USE_GUID)
6746 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6747 &ref_type->guid,
6748 ppTInfo);
6749 else
6750 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6751 ppTInfo);
6753 if (pTLib != NULL)
6754 ITypeLib2_Release(pTLib);
6758 end:
6759 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6760 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6761 return result;
6764 /* ITypeInfo::AddressOfMember
6766 * Retrieves the addresses of static functions or variables, such as those
6767 * defined in a DLL.
6769 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6770 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6772 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6773 HRESULT hr;
6774 BSTR dll, entry;
6775 WORD ordinal;
6776 HMODULE module;
6778 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6780 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6781 if (FAILED(hr))
6782 return hr;
6784 module = LoadLibraryW(dll);
6785 if (!module)
6787 ERR("couldn't load %s\n", debugstr_w(dll));
6788 SysFreeString(dll);
6789 SysFreeString(entry);
6790 return STG_E_FILENOTFOUND;
6792 /* FIXME: store library somewhere where we can free it */
6794 if (entry)
6796 LPSTR entryA;
6797 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6798 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6799 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6801 *ppv = GetProcAddress(module, entryA);
6802 if (!*ppv)
6803 ERR("function not found %s\n", debugstr_a(entryA));
6805 HeapFree(GetProcessHeap(), 0, entryA);
6807 else
6809 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6810 if (!*ppv)
6811 ERR("function not found %d\n", ordinal);
6814 SysFreeString(dll);
6815 SysFreeString(entry);
6817 if (!*ppv)
6818 return TYPE_E_DLLFUNCTIONNOTFOUND;
6820 return S_OK;
6823 /* ITypeInfo::CreateInstance
6825 * Creates a new instance of a type that describes a component object class
6826 * (coclass).
6828 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6829 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6831 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6832 HRESULT hr;
6833 TYPEATTR *pTA;
6835 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6837 *ppvObj = NULL;
6839 if(pOuterUnk)
6841 WARN("Not able to aggregate\n");
6842 return CLASS_E_NOAGGREGATION;
6845 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6846 if(FAILED(hr)) return hr;
6848 if(pTA->typekind != TKIND_COCLASS)
6850 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6851 hr = E_INVALIDARG;
6852 goto end;
6855 hr = S_FALSE;
6856 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6858 IUnknown *pUnk;
6859 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6860 TRACE("GetActiveObject rets %08x\n", hr);
6861 if(hr == S_OK)
6863 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6864 IUnknown_Release(pUnk);
6868 if(hr != S_OK)
6869 hr = CoCreateInstance(&pTA->guid, NULL,
6870 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6871 riid, ppvObj);
6873 end:
6874 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6875 return hr;
6878 /* ITypeInfo::GetMops
6880 * Retrieves marshalling information.
6882 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6883 BSTR *pBstrMops)
6885 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6886 FIXME("(%p %d) stub!\n", This, memid);
6887 *pBstrMops = NULL;
6888 return S_OK;
6891 /* ITypeInfo::GetContainingTypeLib
6893 * Retrieves the containing type library and the index of the type description
6894 * within that type library.
6896 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6897 ITypeLib * *ppTLib, UINT *pIndex)
6899 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6901 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6902 if (pIndex) {
6903 *pIndex=This->index;
6904 TRACE("returning pIndex=%d\n", *pIndex);
6907 if (ppTLib) {
6908 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6909 ITypeLib2_AddRef(*ppTLib);
6910 TRACE("returning ppTLib=%p\n", *ppTLib);
6913 return S_OK;
6916 /* ITypeInfo::ReleaseTypeAttr
6918 * Releases a TYPEATTR previously returned by GetTypeAttr.
6921 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6922 TYPEATTR* pTypeAttr)
6924 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6925 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6926 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6929 /* ITypeInfo::ReleaseFuncDesc
6931 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6933 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6934 ITypeInfo2 *iface,
6935 FUNCDESC *pFuncDesc)
6937 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6938 SHORT i;
6940 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6942 for (i = 0; i < pFuncDesc->cParams; i++)
6943 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6944 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6946 SysFreeString((BSTR)pFuncDesc);
6949 /* ITypeInfo::ReleaseVarDesc
6951 * Releases a VARDESC previously returned by GetVarDesc.
6953 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6954 VARDESC *pVarDesc)
6956 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6957 TRACE("(%p)->(%p)\n", This, pVarDesc);
6959 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6960 if (pVarDesc->varkind == VAR_CONST)
6961 VariantClear(pVarDesc->u.lpvarValue);
6962 SysFreeString((BSTR)pVarDesc);
6965 /* ITypeInfo2::GetTypeKind
6967 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6970 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6971 TYPEKIND *pTypeKind)
6973 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6974 *pTypeKind=This->TypeAttr.typekind;
6975 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6976 return S_OK;
6979 /* ITypeInfo2::GetTypeFlags
6981 * Returns the type flags without any allocations. This returns a DWORD type
6982 * flag, which expands the type flags without growing the TYPEATTR (type
6983 * attribute).
6986 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6988 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6989 *pTypeFlags=This->TypeAttr.wTypeFlags;
6990 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6991 return S_OK;
6994 /* ITypeInfo2::GetFuncIndexOfMemId
6995 * Binds to a specific member based on a known DISPID, where the member name
6996 * is not known (for example, when binding to a default member).
6999 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7000 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7002 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7003 const TLBFuncDesc *pFuncInfo;
7004 int i;
7005 HRESULT result;
7007 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7008 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7009 break;
7010 if(pFuncInfo) {
7011 *pFuncIndex = i;
7012 result = S_OK;
7013 } else
7014 result = TYPE_E_ELEMENTNOTFOUND;
7016 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7017 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7018 return result;
7021 /* TypeInfo2::GetVarIndexOfMemId
7023 * Binds to a specific member based on a known DISPID, where the member name
7024 * is not known (for example, when binding to a default member).
7027 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7028 MEMBERID memid, UINT *pVarIndex)
7030 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7031 TLBVarDesc *pVarInfo;
7032 int i;
7033 HRESULT result;
7034 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7035 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7037 if(pVarInfo) {
7038 *pVarIndex = i;
7039 result = S_OK;
7040 } else
7041 result = TYPE_E_ELEMENTNOTFOUND;
7043 TRACE("(%p) memid 0x%08x -> %s\n", This,
7044 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7045 return result;
7048 /* ITypeInfo2::GetCustData
7050 * Gets the custom data
7052 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7053 ITypeInfo2 * iface,
7054 REFGUID guid,
7055 VARIANT *pVarVal)
7057 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7058 TLBCustData *pCData;
7060 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7061 if( IsEqualIID(guid, &pCData->guid)) break;
7063 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7065 VariantInit( pVarVal);
7066 if (pCData)
7067 VariantCopy( pVarVal, &pCData->data);
7068 else
7069 VariantClear( pVarVal );
7070 return S_OK;
7073 /* ITypeInfo2::GetFuncCustData
7075 * Gets the custom data
7077 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7078 ITypeInfo2 * iface,
7079 UINT index,
7080 REFGUID guid,
7081 VARIANT *pVarVal)
7083 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7084 TLBCustData *pCData=NULL;
7085 TLBFuncDesc * pFDesc;
7086 UINT i;
7087 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7088 pFDesc=pFDesc->next);
7090 if(pFDesc)
7091 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7092 if( IsEqualIID(guid, &pCData->guid)) break;
7094 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7096 if(pCData){
7097 VariantInit( pVarVal);
7098 VariantCopy( pVarVal, &pCData->data);
7099 return S_OK;
7101 return E_INVALIDARG; /* FIXME: correct? */
7104 /* ITypeInfo2::GetParamCustData
7106 * Gets the custom data
7108 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7109 ITypeInfo2 * iface,
7110 UINT indexFunc,
7111 UINT indexParam,
7112 REFGUID guid,
7113 VARIANT *pVarVal)
7115 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7116 TLBCustData *pCData=NULL;
7117 TLBFuncDesc * pFDesc;
7118 UINT i;
7120 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7122 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7123 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7124 pCData = pCData->next)
7125 if( IsEqualIID(guid, &pCData->guid)) break;
7127 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7129 if(pCData)
7131 VariantInit( pVarVal);
7132 VariantCopy( pVarVal, &pCData->data);
7133 return S_OK;
7135 return E_INVALIDARG; /* FIXME: correct? */
7138 /* ITypeInfo2::GetVarCustData
7140 * Gets the custom data
7142 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7143 ITypeInfo2 * iface,
7144 UINT index,
7145 REFGUID guid,
7146 VARIANT *pVarVal)
7148 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7149 TLBCustData *pCData=NULL;
7150 TLBVarDesc * pVDesc;
7151 UINT i;
7153 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7155 if(pVDesc)
7157 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7159 if( IsEqualIID(guid, &pCData->guid)) break;
7163 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7165 if(pCData)
7167 VariantInit( pVarVal);
7168 VariantCopy( pVarVal, &pCData->data);
7169 return S_OK;
7171 return E_INVALIDARG; /* FIXME: correct? */
7174 /* ITypeInfo2::GetImplCustData
7176 * Gets the custom data
7178 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7179 ITypeInfo2 * iface,
7180 UINT index,
7181 REFGUID guid,
7182 VARIANT *pVarVal)
7184 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7185 TLBCustData *pCData=NULL;
7186 TLBImplType * pRDesc;
7187 UINT i;
7189 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7191 if(pRDesc)
7193 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7195 if( IsEqualIID(guid, &pCData->guid)) break;
7199 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7201 if(pCData)
7203 VariantInit( pVarVal);
7204 VariantCopy( pVarVal, &pCData->data);
7205 return S_OK;
7207 return E_INVALIDARG; /* FIXME: correct? */
7210 /* ITypeInfo2::GetDocumentation2
7212 * Retrieves the documentation string, the complete Help file name and path,
7213 * the localization context to use, and the context ID for the library Help
7214 * topic in the Help file.
7217 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7218 ITypeInfo2 * iface,
7219 MEMBERID memid,
7220 LCID lcid,
7221 BSTR *pbstrHelpString,
7222 DWORD *pdwHelpStringContext,
7223 BSTR *pbstrHelpStringDll)
7225 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7226 const TLBFuncDesc *pFDesc;
7227 const TLBVarDesc *pVDesc;
7228 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7229 "HelpStringContext(%p) HelpStringDll(%p)\n",
7230 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7231 pbstrHelpStringDll );
7232 /* the help string should be obtained from the helpstringdll,
7233 * using the _DLLGetDocumentation function, based on the supplied
7234 * lcid. Nice to do sometime...
7236 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7237 if(pbstrHelpString)
7238 *pbstrHelpString=SysAllocString(This->Name);
7239 if(pdwHelpStringContext)
7240 *pdwHelpStringContext=This->dwHelpStringContext;
7241 if(pbstrHelpStringDll)
7242 *pbstrHelpStringDll=
7243 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7244 return S_OK;
7245 }else {/* for a member */
7246 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7247 if(pFDesc->funcdesc.memid==memid){
7248 if(pbstrHelpString)
7249 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7250 if(pdwHelpStringContext)
7251 *pdwHelpStringContext=pFDesc->HelpStringContext;
7252 if(pbstrHelpStringDll)
7253 *pbstrHelpStringDll=
7254 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7255 return S_OK;
7257 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7258 if(pVDesc->vardesc.memid==memid){
7259 if(pbstrHelpString)
7260 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7261 if(pdwHelpStringContext)
7262 *pdwHelpStringContext=pVDesc->HelpStringContext;
7263 if(pbstrHelpStringDll)
7264 *pbstrHelpStringDll=
7265 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7266 return S_OK;
7269 return TYPE_E_ELEMENTNOTFOUND;
7272 /* ITypeInfo2::GetAllCustData
7274 * Gets all custom data items for the Type info.
7277 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7278 ITypeInfo2 * iface,
7279 CUSTDATA *pCustData)
7281 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7282 TLBCustData *pCData;
7283 int i;
7285 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7287 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7288 if(pCustData->prgCustData ){
7289 pCustData->cCustData=This->ctCustData;
7290 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7291 pCustData->prgCustData[i].guid=pCData->guid;
7292 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7294 }else{
7295 ERR(" OUT OF MEMORY!\n");
7296 return E_OUTOFMEMORY;
7298 return S_OK;
7301 /* ITypeInfo2::GetAllFuncCustData
7303 * Gets all custom data items for the specified Function
7306 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7307 ITypeInfo2 * iface,
7308 UINT index,
7309 CUSTDATA *pCustData)
7311 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7312 TLBCustData *pCData;
7313 TLBFuncDesc * pFDesc;
7314 UINT i;
7315 TRACE("(%p) index %d\n", This, index);
7316 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7317 pFDesc=pFDesc->next)
7319 if(pFDesc){
7320 pCustData->prgCustData =
7321 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7322 if(pCustData->prgCustData ){
7323 pCustData->cCustData=pFDesc->ctCustData;
7324 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7325 pCData = pCData->next){
7326 pCustData->prgCustData[i].guid=pCData->guid;
7327 VariantCopy(& pCustData->prgCustData[i].varValue,
7328 & pCData->data);
7330 }else{
7331 ERR(" OUT OF MEMORY!\n");
7332 return E_OUTOFMEMORY;
7334 return S_OK;
7336 return TYPE_E_ELEMENTNOTFOUND;
7339 /* ITypeInfo2::GetAllParamCustData
7341 * Gets all custom data items for the Functions
7344 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7345 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7347 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7348 TLBCustData *pCData=NULL;
7349 TLBFuncDesc * pFDesc;
7350 UINT i;
7351 TRACE("(%p) index %d\n", This, indexFunc);
7352 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7353 pFDesc=pFDesc->next)
7355 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7356 pCustData->prgCustData =
7357 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7358 sizeof(CUSTDATAITEM));
7359 if(pCustData->prgCustData ){
7360 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7361 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7362 pCData; i++, pCData = pCData->next){
7363 pCustData->prgCustData[i].guid=pCData->guid;
7364 VariantCopy(& pCustData->prgCustData[i].varValue,
7365 & pCData->data);
7367 }else{
7368 ERR(" OUT OF MEMORY!\n");
7369 return E_OUTOFMEMORY;
7371 return S_OK;
7373 return TYPE_E_ELEMENTNOTFOUND;
7376 /* ITypeInfo2::GetAllVarCustData
7378 * Gets all custom data items for the specified Variable
7381 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7382 UINT index, CUSTDATA *pCustData)
7384 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7385 TLBCustData *pCData;
7386 TLBVarDesc * pVDesc;
7387 UINT i;
7388 TRACE("(%p) index %d\n", This, index);
7389 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7390 pVDesc=pVDesc->next)
7392 if(pVDesc){
7393 pCustData->prgCustData =
7394 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7395 if(pCustData->prgCustData ){
7396 pCustData->cCustData=pVDesc->ctCustData;
7397 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7398 pCData = pCData->next){
7399 pCustData->prgCustData[i].guid=pCData->guid;
7400 VariantCopy(& pCustData->prgCustData[i].varValue,
7401 & pCData->data);
7403 }else{
7404 ERR(" OUT OF MEMORY!\n");
7405 return E_OUTOFMEMORY;
7407 return S_OK;
7409 return TYPE_E_ELEMENTNOTFOUND;
7412 /* ITypeInfo2::GetAllImplCustData
7414 * Gets all custom data items for the specified implementation type
7417 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7418 ITypeInfo2 * iface,
7419 UINT index,
7420 CUSTDATA *pCustData)
7422 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7423 TLBCustData *pCData;
7424 TLBImplType * pRDesc;
7425 UINT i;
7426 TRACE("(%p) index %d\n", This, index);
7427 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7428 pRDesc=pRDesc->next)
7430 if(pRDesc){
7431 pCustData->prgCustData =
7432 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7433 if(pCustData->prgCustData ){
7434 pCustData->cCustData=pRDesc->ctCustData;
7435 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7436 pCData = pCData->next){
7437 pCustData->prgCustData[i].guid=pCData->guid;
7438 VariantCopy(& pCustData->prgCustData[i].varValue,
7439 & pCData->data);
7441 }else{
7442 ERR(" OUT OF MEMORY!\n");
7443 return E_OUTOFMEMORY;
7445 return S_OK;
7447 return TYPE_E_ELEMENTNOTFOUND;
7450 static const ITypeInfo2Vtbl tinfvt =
7453 ITypeInfo_fnQueryInterface,
7454 ITypeInfo_fnAddRef,
7455 ITypeInfo_fnRelease,
7457 ITypeInfo_fnGetTypeAttr,
7458 ITypeInfo_fnGetTypeComp,
7459 ITypeInfo_fnGetFuncDesc,
7460 ITypeInfo_fnGetVarDesc,
7461 ITypeInfo_fnGetNames,
7462 ITypeInfo_fnGetRefTypeOfImplType,
7463 ITypeInfo_fnGetImplTypeFlags,
7464 ITypeInfo_fnGetIDsOfNames,
7465 ITypeInfo_fnInvoke,
7466 ITypeInfo_fnGetDocumentation,
7467 ITypeInfo_fnGetDllEntry,
7468 ITypeInfo_fnGetRefTypeInfo,
7469 ITypeInfo_fnAddressOfMember,
7470 ITypeInfo_fnCreateInstance,
7471 ITypeInfo_fnGetMops,
7472 ITypeInfo_fnGetContainingTypeLib,
7473 ITypeInfo_fnReleaseTypeAttr,
7474 ITypeInfo_fnReleaseFuncDesc,
7475 ITypeInfo_fnReleaseVarDesc,
7477 ITypeInfo2_fnGetTypeKind,
7478 ITypeInfo2_fnGetTypeFlags,
7479 ITypeInfo2_fnGetFuncIndexOfMemId,
7480 ITypeInfo2_fnGetVarIndexOfMemId,
7481 ITypeInfo2_fnGetCustData,
7482 ITypeInfo2_fnGetFuncCustData,
7483 ITypeInfo2_fnGetParamCustData,
7484 ITypeInfo2_fnGetVarCustData,
7485 ITypeInfo2_fnGetImplTypeCustData,
7486 ITypeInfo2_fnGetDocumentation2,
7487 ITypeInfo2_fnGetAllCustData,
7488 ITypeInfo2_fnGetAllFuncCustData,
7489 ITypeInfo2_fnGetAllParamCustData,
7490 ITypeInfo2_fnGetAllVarCustData,
7491 ITypeInfo2_fnGetAllImplTypeCustData,
7494 /******************************************************************************
7495 * CreateDispTypeInfo [OLEAUT32.31]
7497 * Build type information for an object so it can be called through an
7498 * IDispatch interface.
7500 * RETURNS
7501 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7502 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7504 * NOTES
7505 * This call allows an objects methods to be accessed through IDispatch, by
7506 * building an ITypeInfo object that IDispatch can use to call through.
7508 HRESULT WINAPI CreateDispTypeInfo(
7509 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7510 LCID lcid, /* [I] Locale Id */
7511 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7513 ITypeInfoImpl *pTIClass, *pTIIface;
7514 ITypeLibImpl *pTypeLibImpl;
7515 unsigned int param, func;
7516 TLBFuncDesc **ppFuncDesc;
7517 TLBRefType *ref;
7519 TRACE("\n");
7520 pTypeLibImpl = TypeLibImpl_Constructor();
7521 if (!pTypeLibImpl) return E_FAIL;
7523 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7524 pTIIface->pTypeLib = pTypeLibImpl;
7525 pTIIface->index = 0;
7526 pTIIface->Name = NULL;
7527 pTIIface->dwHelpContext = -1;
7528 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7529 pTIIface->TypeAttr.lcid = lcid;
7530 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7531 pTIIface->TypeAttr.wMajorVerNum = 0;
7532 pTIIface->TypeAttr.wMinorVerNum = 0;
7533 pTIIface->TypeAttr.cbAlignment = 2;
7534 pTIIface->TypeAttr.cbSizeInstance = -1;
7535 pTIIface->TypeAttr.cbSizeVft = -1;
7536 pTIIface->TypeAttr.cFuncs = 0;
7537 pTIIface->TypeAttr.cImplTypes = 0;
7538 pTIIface->TypeAttr.cVars = 0;
7539 pTIIface->TypeAttr.wTypeFlags = 0;
7541 ppFuncDesc = &pTIIface->funclist;
7542 for(func = 0; func < pidata->cMembers; func++) {
7543 METHODDATA *md = pidata->pmethdata + func;
7544 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7545 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7546 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7547 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7548 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7549 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7550 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7551 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7552 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7553 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7554 (*ppFuncDesc)->funcdesc.cScodes = 0;
7555 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7556 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7557 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7558 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7559 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7560 md->cArgs * sizeof(ELEMDESC));
7561 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7562 md->cArgs * sizeof(TLBParDesc));
7563 for(param = 0; param < md->cArgs; param++) {
7564 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7565 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7567 (*ppFuncDesc)->helpcontext = 0;
7568 (*ppFuncDesc)->HelpStringContext = 0;
7569 (*ppFuncDesc)->HelpString = NULL;
7570 (*ppFuncDesc)->Entry = NULL;
7571 (*ppFuncDesc)->ctCustData = 0;
7572 (*ppFuncDesc)->pCustData = NULL;
7573 (*ppFuncDesc)->next = NULL;
7574 pTIIface->TypeAttr.cFuncs++;
7575 ppFuncDesc = &(*ppFuncDesc)->next;
7578 dump_TypeInfo(pTIIface);
7580 pTypeLibImpl->pTypeInfo = pTIIface;
7581 pTypeLibImpl->TypeInfoCount++;
7583 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7584 pTIClass->pTypeLib = pTypeLibImpl;
7585 pTIClass->index = 1;
7586 pTIClass->Name = NULL;
7587 pTIClass->dwHelpContext = -1;
7588 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7589 pTIClass->TypeAttr.lcid = lcid;
7590 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7591 pTIClass->TypeAttr.wMajorVerNum = 0;
7592 pTIClass->TypeAttr.wMinorVerNum = 0;
7593 pTIClass->TypeAttr.cbAlignment = 2;
7594 pTIClass->TypeAttr.cbSizeInstance = -1;
7595 pTIClass->TypeAttr.cbSizeVft = -1;
7596 pTIClass->TypeAttr.cFuncs = 0;
7597 pTIClass->TypeAttr.cImplTypes = 1;
7598 pTIClass->TypeAttr.cVars = 0;
7599 pTIClass->TypeAttr.wTypeFlags = 0;
7601 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7602 pTIClass->impltypelist->hRef = 0;
7604 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7605 ref->index = 0;
7606 ref->reference = 0;
7607 ref->pImpTLInfo = TLB_REF_INTERNAL;
7608 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7610 dump_TypeInfo(pTIClass);
7612 pTIIface->next = pTIClass;
7613 pTypeLibImpl->TypeInfoCount++;
7615 *pptinfo = (ITypeInfo*)pTIClass;
7617 ITypeInfo_AddRef(*pptinfo);
7618 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7620 return S_OK;
7624 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7626 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7628 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7631 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7633 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7635 return ITypeInfo_AddRef((ITypeInfo *)This);
7638 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7640 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7642 return ITypeInfo_Release((ITypeInfo *)This);
7645 static HRESULT WINAPI ITypeComp_fnBind(
7646 ITypeComp * iface,
7647 OLECHAR * szName,
7648 ULONG lHash,
7649 WORD wFlags,
7650 ITypeInfo ** ppTInfo,
7651 DESCKIND * pDescKind,
7652 BINDPTR * pBindPtr)
7654 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7655 const TLBFuncDesc *pFDesc;
7656 const TLBVarDesc *pVDesc;
7657 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7659 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7661 *pDescKind = DESCKIND_NONE;
7662 pBindPtr->lpfuncdesc = NULL;
7663 *ppTInfo = NULL;
7665 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7666 if (!strcmpiW(pFDesc->Name, szName)) {
7667 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7668 break;
7669 else
7670 /* name found, but wrong flags */
7671 hr = TYPE_E_TYPEMISMATCH;
7674 if (pFDesc)
7676 HRESULT hr = TLB_AllocAndInitFuncDesc(
7677 &pFDesc->funcdesc,
7678 &pBindPtr->lpfuncdesc,
7679 This->TypeAttr.typekind == TKIND_DISPATCH);
7680 if (FAILED(hr))
7681 return hr;
7682 *pDescKind = DESCKIND_FUNCDESC;
7683 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7684 ITypeInfo_AddRef(*ppTInfo);
7685 return S_OK;
7686 } else {
7687 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7688 if (!strcmpiW(pVDesc->Name, szName)) {
7689 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7690 if (FAILED(hr))
7691 return hr;
7692 *pDescKind = DESCKIND_VARDESC;
7693 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7694 ITypeInfo_AddRef(*ppTInfo);
7695 return S_OK;
7699 /* FIXME: search each inherited interface, not just the first */
7700 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7701 /* recursive search */
7702 ITypeInfo *pTInfo;
7703 ITypeComp *pTComp;
7704 HRESULT hr;
7705 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7706 if (SUCCEEDED(hr))
7708 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7709 ITypeInfo_Release(pTInfo);
7711 if (SUCCEEDED(hr))
7713 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7714 ITypeComp_Release(pTComp);
7715 return hr;
7717 WARN("Could not search inherited interface!\n");
7719 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7720 return hr;
7723 static HRESULT WINAPI ITypeComp_fnBindType(
7724 ITypeComp * iface,
7725 OLECHAR * szName,
7726 ULONG lHash,
7727 ITypeInfo ** ppTInfo,
7728 ITypeComp ** ppTComp)
7730 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7732 /* strange behaviour (does nothing) but like the
7733 * original */
7735 if (!ppTInfo || !ppTComp)
7736 return E_POINTER;
7738 *ppTInfo = NULL;
7739 *ppTComp = NULL;
7741 return S_OK;
7744 static const ITypeCompVtbl tcompvt =
7747 ITypeComp_fnQueryInterface,
7748 ITypeComp_fnAddRef,
7749 ITypeComp_fnRelease,
7751 ITypeComp_fnBind,
7752 ITypeComp_fnBindType