push 5bc4839baba05cc4333240c25295b8dd6e351557
[wine/hacks.git] / dlls / oleaut32 / typelib.c
blob07447f2c5a20933104e56bc1ead5deb7f2072617
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 /****************************************************************************
287 * QueryPathOfRegTypeLib [OLEAUT32.164]
289 * Gets the path to a registered type library.
291 * PARAMS
292 * guid [I] referenced guid
293 * wMaj [I] major version
294 * wMin [I] minor version
295 * lcid [I] locale id
296 * path [O] path of typelib
298 * RETURNS
299 * Success: S_OK.
300 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
301 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
302 * opened.
304 HRESULT WINAPI QueryPathOfRegTypeLib(
305 REFGUID guid,
306 WORD wMaj,
307 WORD wMin,
308 LCID lcid,
309 LPBSTR path )
311 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
312 LCID myLCID = lcid;
313 HKEY hkey;
314 WCHAR buffer[60];
315 WCHAR Path[MAX_PATH];
316 LONG res;
318 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
320 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
321 get_typelib_key( guid, wMaj, wMin, buffer );
323 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
324 if (res == ERROR_FILE_NOT_FOUND)
326 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
327 return TYPE_E_LIBNOTREGISTERED;
329 else if (res != ERROR_SUCCESS)
331 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
332 return TYPE_E_REGISTRYACCESS;
335 while (hr != S_OK)
337 LONG dwPathLen = sizeof(Path);
339 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
341 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
343 if (!lcid)
344 break;
345 else if (myLCID == lcid)
347 /* try with sub-langid */
348 myLCID = SUBLANGID(lcid);
350 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
352 /* try with system langid */
353 myLCID = 0;
355 else
357 break;
360 else
362 *path = SysAllocString( Path );
363 hr = S_OK;
366 RegCloseKey( hkey );
367 TRACE_(typelib)("-- 0x%08x\n", hr);
368 return hr;
371 /******************************************************************************
372 * CreateTypeLib [OLEAUT32.160] creates a typelib
374 * RETURNS
375 * Success: S_OK
376 * Failure: Status
378 HRESULT WINAPI CreateTypeLib(
379 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
381 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
382 return E_FAIL;
385 /******************************************************************************
386 * LoadTypeLib [OLEAUT32.161]
388 * Loads a type library
390 * PARAMS
391 * szFile [I] Name of file to load from.
392 * pptLib [O] Pointer that receives ITypeLib object on success.
394 * RETURNS
395 * Success: S_OK
396 * Failure: Status
398 * SEE
399 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
401 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
403 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
404 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
407 /******************************************************************************
408 * LoadTypeLibEx [OLEAUT32.183]
410 * Loads and optionally registers a type library
412 * RETURNS
413 * Success: S_OK
414 * Failure: Status
416 HRESULT WINAPI LoadTypeLibEx(
417 LPCOLESTR szFile, /* [in] Name of file to load from */
418 REGKIND regkind, /* [in] Specify kind of registration */
419 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
421 WCHAR szPath[MAX_PATH+1];
422 HRESULT res;
424 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
426 *pptLib = NULL;
428 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
430 if (SUCCEEDED(res))
431 switch(regkind)
433 case REGKIND_DEFAULT:
434 /* don't register typelibs supplied with full path. Experimentation confirms the following */
435 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
436 (szFile[0] && (szFile[1] == ':'))) break;
437 /* else fall-through */
439 case REGKIND_REGISTER:
440 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
442 IUnknown_Release(*pptLib);
443 *pptLib = 0;
445 break;
446 case REGKIND_NONE:
447 break;
450 TRACE(" returns %08x\n",res);
451 return res;
454 /******************************************************************************
455 * LoadRegTypeLib [OLEAUT32.162]
457 * Loads a registered type library.
459 * PARAMS
460 * rguid [I] GUID of the registered type library.
461 * wVerMajor [I] major version.
462 * wVerMinor [I] minor version.
463 * lcid [I] locale ID.
464 * ppTLib [O] pointer that receives an ITypeLib object on success.
466 * RETURNS
467 * Success: S_OK.
468 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
469 * LoadTypeLib.
471 HRESULT WINAPI LoadRegTypeLib(
472 REFGUID rguid,
473 WORD wVerMajor,
474 WORD wVerMinor,
475 LCID lcid,
476 ITypeLib **ppTLib)
478 BSTR bstr=NULL;
479 HRESULT res;
481 *ppTLib = NULL;
483 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
485 if(SUCCEEDED(res))
487 res= LoadTypeLib(bstr, ppTLib);
488 SysFreeString(bstr);
491 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
493 return res;
497 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
498 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
499 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
500 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
501 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
502 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
504 /******************************************************************************
505 * RegisterTypeLib [OLEAUT32.163]
506 * Adds information about a type library to the System Registry
507 * NOTES
508 * Docs: ITypeLib FAR * ptlib
509 * Docs: OLECHAR FAR* szFullPath
510 * Docs: OLECHAR FAR* szHelpDir
512 * RETURNS
513 * Success: S_OK
514 * Failure: Status
516 HRESULT WINAPI RegisterTypeLib(
517 ITypeLib * ptlib, /* [in] Pointer to the library*/
518 OLECHAR * szFullPath, /* [in] full Path of the library*/
519 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
520 may be NULL*/
522 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
523 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
524 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
525 HRESULT res;
526 TLIBATTR *attr;
527 WCHAR keyName[60];
528 WCHAR tmp[16];
529 HKEY key, subKey;
530 UINT types, tidx;
531 TYPEKIND kind;
532 DWORD disposition;
534 if (ptlib == NULL || szFullPath == NULL)
535 return E_INVALIDARG;
537 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
538 return E_FAIL;
540 #ifdef _WIN64
541 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
542 #else
543 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
544 #endif
546 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
548 res = S_OK;
549 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
550 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
552 LPOLESTR doc;
554 /* Set the human-readable name of the typelib */
555 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
557 if (RegSetValueExW(key, NULL, 0, REG_SZ,
558 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
559 res = E_FAIL;
561 SysFreeString(doc);
563 else
564 res = E_FAIL;
566 /* Make up the name of the typelib path subkey */
567 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
569 /* Create the typelib path subkey */
570 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
571 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
573 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
574 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
575 res = E_FAIL;
577 RegCloseKey(subKey);
579 else
580 res = E_FAIL;
582 /* Create the flags subkey */
583 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
584 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
586 /* FIXME: is %u correct? */
587 static const WCHAR formatW[] = {'%','u',0};
588 WCHAR buf[20];
589 sprintfW(buf, formatW, attr->wLibFlags);
590 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
591 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
592 res = E_FAIL;
594 RegCloseKey(subKey);
596 else
597 res = E_FAIL;
599 /* create the helpdir subkey */
600 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
601 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
603 BOOL freeHelpDir = FALSE;
604 OLECHAR* pIndexStr;
606 /* if we created a new key, and helpDir was null, set the helpdir
607 to the directory which contains the typelib. However,
608 if we just opened an existing key, we leave the helpdir alone */
609 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
610 szHelpDir = SysAllocString(szFullPath);
611 pIndexStr = strrchrW(szHelpDir, '\\');
612 if (pIndexStr) {
613 *pIndexStr = 0;
615 freeHelpDir = TRUE;
618 /* if we have an szHelpDir, set it! */
619 if (szHelpDir != NULL) {
620 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
621 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
622 res = E_FAIL;
626 /* tidy up */
627 if (freeHelpDir) SysFreeString(szHelpDir);
628 RegCloseKey(subKey);
630 } else {
631 res = E_FAIL;
634 RegCloseKey(key);
636 else
637 res = E_FAIL;
639 /* register OLE Automation-compatible interfaces for this typelib */
640 types = ITypeLib_GetTypeInfoCount(ptlib);
641 for (tidx=0; tidx<types; tidx++) {
642 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
643 LPOLESTR name = NULL;
644 ITypeInfo *tinfo = NULL;
646 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
648 switch (kind) {
649 case TKIND_INTERFACE:
650 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
651 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
652 break;
654 case TKIND_DISPATCH:
655 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
656 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
657 break;
659 default:
660 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
661 break;
664 if (tinfo) {
665 TYPEATTR *tattr = NULL;
666 ITypeInfo_GetTypeAttr(tinfo, &tattr);
668 if (tattr) {
669 TRACE_(typelib)("guid=%s, flags=%04x (",
670 debugstr_guid(&tattr->guid),
671 tattr->wTypeFlags);
673 if (TRACE_ON(typelib)) {
674 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
675 XX(FAPPOBJECT);
676 XX(FCANCREATE);
677 XX(FLICENSED);
678 XX(FPREDECLID);
679 XX(FHIDDEN);
680 XX(FCONTROL);
681 XX(FDUAL);
682 XX(FNONEXTENSIBLE);
683 XX(FOLEAUTOMATION);
684 XX(FRESTRICTED);
685 XX(FAGGREGATABLE);
686 XX(FREPLACEABLE);
687 XX(FDISPATCHABLE);
688 XX(FREVERSEBIND);
689 XX(FPROXY);
690 #undef XX
691 MESSAGE("\n");
694 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
696 /* register interface<->typelib coupling */
697 get_interface_key( &tattr->guid, keyName );
698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
699 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
701 if (name)
702 RegSetValueExW(key, NULL, 0, REG_SZ,
703 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
705 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
706 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
707 RegSetValueExW(subKey, NULL, 0, REG_SZ,
708 (const BYTE *)PSOA, sizeof PSOA);
709 RegCloseKey(subKey);
712 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
713 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
714 RegSetValueExW(subKey, NULL, 0, REG_SZ,
715 (const BYTE *)PSOA, sizeof PSOA);
716 RegCloseKey(subKey);
719 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
720 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
722 WCHAR buffer[40];
723 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
724 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
726 StringFromGUID2(&attr->guid, buffer, 40);
727 RegSetValueExW(subKey, NULL, 0, REG_SZ,
728 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
729 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
730 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
731 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
732 RegCloseKey(subKey);
735 RegCloseKey(key);
739 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
742 ITypeInfo_Release(tinfo);
745 SysFreeString(name);
749 ITypeLib_ReleaseTLibAttr(ptlib, attr);
751 return res;
755 /******************************************************************************
756 * UnRegisterTypeLib [OLEAUT32.186]
757 * Removes information about a type library from the System Registry
758 * NOTES
760 * RETURNS
761 * Success: S_OK
762 * Failure: Status
764 HRESULT WINAPI UnRegisterTypeLib(
765 REFGUID libid, /* [in] Guid of the library */
766 WORD wVerMajor, /* [in] major version */
767 WORD wVerMinor, /* [in] minor version */
768 LCID lcid, /* [in] locale id */
769 SYSKIND syskind)
771 BSTR tlibPath = NULL;
772 DWORD tmpLength;
773 WCHAR keyName[60];
774 WCHAR subKeyName[50];
775 int result = S_OK;
776 DWORD i = 0;
777 BOOL deleteOtherStuff;
778 HKEY key = NULL;
779 HKEY subKey = NULL;
780 TYPEATTR* typeAttr = NULL;
781 TYPEKIND kind;
782 ITypeInfo* typeInfo = NULL;
783 ITypeLib* typeLib = NULL;
784 int numTypes;
786 TRACE("(IID: %s)\n",debugstr_guid(libid));
788 /* Create the path to the key */
789 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
791 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
793 TRACE("Unsupported syskind %i\n", syskind);
794 result = E_INVALIDARG;
795 goto end;
798 /* get the path to the typelib on disk */
799 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
800 result = E_INVALIDARG;
801 goto end;
804 /* Try and open the key to the type library. */
805 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
806 result = E_INVALIDARG;
807 goto end;
810 /* Try and load the type library */
811 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
812 result = TYPE_E_INVALIDSTATE;
813 goto end;
816 /* remove any types registered with this typelib */
817 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
818 for (i=0; i<numTypes; i++) {
819 /* get the kind of type */
820 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
821 goto enddeleteloop;
824 /* skip non-interfaces, and get type info for the type */
825 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
826 goto enddeleteloop;
828 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
829 goto enddeleteloop;
831 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
832 goto enddeleteloop;
835 /* the path to the type */
836 get_interface_key( &typeAttr->guid, subKeyName );
838 /* Delete its bits */
839 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
840 goto enddeleteloop;
842 RegDeleteKeyW(subKey, ProxyStubClsidW);
843 RegDeleteKeyW(subKey, ProxyStubClsid32W);
844 RegDeleteKeyW(subKey, TypeLibW);
845 RegCloseKey(subKey);
846 subKey = NULL;
847 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
849 enddeleteloop:
850 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
851 typeAttr = NULL;
852 if (typeInfo) ITypeInfo_Release(typeInfo);
853 typeInfo = NULL;
856 /* Now, delete the type library path subkey */
857 get_lcid_subkey( lcid, syskind, subKeyName );
858 RegDeleteKeyW(key, subKeyName);
859 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
860 RegDeleteKeyW(key, subKeyName);
862 /* check if there is anything besides the FLAGS/HELPDIR keys.
863 If there is, we don't delete them */
864 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
865 deleteOtherStuff = TRUE;
866 i = 0;
867 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
868 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
870 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
871 if (!strcmpW(subKeyName, FLAGSW)) continue;
872 if (!strcmpW(subKeyName, HELPDIRW)) continue;
873 deleteOtherStuff = FALSE;
874 break;
877 /* only delete the other parts of the key if we're absolutely sure */
878 if (deleteOtherStuff) {
879 RegDeleteKeyW(key, FLAGSW);
880 RegDeleteKeyW(key, HELPDIRW);
881 RegCloseKey(key);
882 key = NULL;
884 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
885 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
886 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
889 end:
890 SysFreeString(tlibPath);
891 if (typeLib) ITypeLib_Release(typeLib);
892 if (subKey) RegCloseKey(subKey);
893 if (key) RegCloseKey(key);
894 return result;
897 /*======================= ITypeLib implementation =======================*/
899 typedef struct tagTLBCustData
901 GUID guid;
902 VARIANT data;
903 struct tagTLBCustData* next;
904 } TLBCustData;
906 /* data structure for import typelibs */
907 typedef struct tagTLBImpLib
909 int offset; /* offset in the file (MSFT)
910 offset in nametable (SLTG)
911 just used to identify library while reading
912 data from file */
913 GUID guid; /* libid */
914 BSTR name; /* name */
916 LCID lcid; /* lcid of imported typelib */
918 WORD wVersionMajor; /* major version number */
919 WORD wVersionMinor; /* minor version number */
921 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
922 NULL if not yet loaded */
923 struct tagTLBImpLib * next;
924 } TLBImpLib;
926 /* internal ITypeLib data */
927 typedef struct tagITypeLibImpl
929 const ITypeLib2Vtbl *lpVtbl;
930 const ITypeCompVtbl *lpVtblTypeComp;
931 LONG ref;
932 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
933 LCID lcid;
935 /* strings can be stored in tlb as multibyte strings BUT they are *always*
936 * exported to the application as a UNICODE string.
938 BSTR Name;
939 BSTR DocString;
940 BSTR HelpFile;
941 BSTR HelpStringDll;
942 DWORD dwHelpContext;
943 int TypeInfoCount; /* nr of typeinfo's in librarry */
944 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
945 int ctCustData; /* number of items in cust data list */
946 TLBCustData * pCustData; /* linked list to cust data */
947 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
948 int ctTypeDesc; /* number of items in type desc array */
949 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
950 library. Only used while reading MSFT
951 typelibs */
952 struct list ref_list; /* list of ref types in this typelib */
953 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
956 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
957 struct tagITypeLibImpl *next, *prev;
958 WCHAR *path;
959 INT index;
960 } ITypeLibImpl;
962 static const ITypeLib2Vtbl tlbvt;
963 static const ITypeCompVtbl tlbtcvt;
965 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
967 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
970 /* ITypeLib methods */
971 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
972 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
974 /*======================= ITypeInfo implementation =======================*/
976 /* data for referenced types */
977 typedef struct tagTLBRefType
979 INT index; /* Type index for internal ref or for external ref
980 it the format is SLTG. -2 indicates to
981 use guid */
983 GUID guid; /* guid of the referenced type */
984 /* if index == TLB_REF_USE_GUID */
986 HREFTYPE reference; /* The href of this ref */
987 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
988 TLB_REF_INTERNAL for internal refs
989 TLB_REF_NOT_FOUND for broken refs */
991 struct list entry;
992 } TLBRefType;
994 #define TLB_REF_USE_GUID -2
996 #define TLB_REF_INTERNAL (void*)-2
997 #define TLB_REF_NOT_FOUND (void*)-1
999 /* internal Parameter data */
1000 typedef struct tagTLBParDesc
1002 BSTR Name;
1003 int ctCustData;
1004 TLBCustData * pCustData; /* linked list to cust data */
1005 } TLBParDesc;
1007 /* internal Function data */
1008 typedef struct tagTLBFuncDesc
1010 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1011 BSTR Name; /* the name of this function */
1012 TLBParDesc *pParamDesc; /* array with param names and custom data */
1013 int helpcontext;
1014 int HelpStringContext;
1015 BSTR HelpString;
1016 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
1017 int ctCustData;
1018 TLBCustData * pCustData; /* linked list to cust data; */
1019 struct tagTLBFuncDesc * next;
1020 } TLBFuncDesc;
1022 /* internal Variable data */
1023 typedef struct tagTLBVarDesc
1025 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1026 BSTR Name; /* the name of this variable */
1027 int HelpContext;
1028 int HelpStringContext; /* FIXME: where? */
1029 BSTR HelpString;
1030 int ctCustData;
1031 TLBCustData * pCustData;/* linked list to cust data; */
1032 struct tagTLBVarDesc * next;
1033 } TLBVarDesc;
1035 /* internal implemented interface data */
1036 typedef struct tagTLBImplType
1038 HREFTYPE hRef; /* hRef of interface */
1039 int implflags; /* IMPLFLAG_*s */
1040 int ctCustData;
1041 TLBCustData * pCustData;/* linked list to custom data; */
1042 struct tagTLBImplType *next;
1043 } TLBImplType;
1045 /* internal TypeInfo data */
1046 typedef struct tagITypeInfoImpl
1048 const ITypeInfo2Vtbl *lpVtbl;
1049 const ITypeCompVtbl *lpVtblTypeComp;
1050 LONG ref;
1051 BOOL no_free_data; /* don't free data structures */
1052 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1053 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1054 int index; /* index in this typelib; */
1055 HREFTYPE hreftype; /* hreftype for app object binding */
1056 /* type libs seem to store the doc strings in ascii
1057 * so why should we do it in unicode?
1059 BSTR Name;
1060 BSTR DocString;
1061 BSTR DllName;
1062 DWORD dwHelpContext;
1063 DWORD dwHelpStringContext;
1065 /* functions */
1066 TLBFuncDesc * funclist; /* linked list with function descriptions */
1068 /* variables */
1069 TLBVarDesc * varlist; /* linked list with variable descriptions */
1071 /* Implemented Interfaces */
1072 TLBImplType * impltypelist;
1074 int ctCustData;
1075 TLBCustData * pCustData; /* linked list to cust data; */
1076 struct tagITypeInfoImpl * next;
1077 } ITypeInfoImpl;
1079 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1081 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1084 static const ITypeInfo2Vtbl tinfvt;
1085 static const ITypeCompVtbl tcompvt;
1087 static ITypeInfo2 * ITypeInfo_Constructor(void);
1089 typedef struct tagTLBContext
1091 unsigned int oStart; /* start of TLB in file */
1092 unsigned int pos; /* current pos */
1093 unsigned int length; /* total length */
1094 void *mapping; /* memory mapping */
1095 MSFT_SegDir * pTblDir;
1096 ITypeLibImpl* pLibInfo;
1097 } TLBContext;
1100 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1103 debug
1105 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1106 if (pTD->vt & VT_RESERVED)
1107 szVarType += strlen(strcpy(szVarType, "reserved | "));
1108 if (pTD->vt & VT_BYREF)
1109 szVarType += strlen(strcpy(szVarType, "ref to "));
1110 if (pTD->vt & VT_ARRAY)
1111 szVarType += strlen(strcpy(szVarType, "array of "));
1112 if (pTD->vt & VT_VECTOR)
1113 szVarType += strlen(strcpy(szVarType, "vector of "));
1114 switch(pTD->vt & VT_TYPEMASK) {
1115 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1116 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1117 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1118 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1119 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1120 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1121 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1122 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1123 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1124 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1125 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1126 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1127 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1128 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1129 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1130 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1131 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1132 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1133 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1134 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1135 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1136 pTD->u.hreftype); break;
1137 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1138 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1139 case VT_PTR: sprintf(szVarType, "ptr to ");
1140 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1141 break;
1142 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1143 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1144 break;
1145 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1146 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1147 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1148 break;
1150 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1154 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1155 char buf[200];
1156 USHORT flags = edesc->u.paramdesc.wParamFlags;
1157 dump_TypeDesc(&edesc->tdesc,buf);
1158 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1159 MESSAGE("\t\tu.paramdesc.wParamFlags");
1160 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1161 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1162 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1163 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1164 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1165 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1166 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1167 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1168 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1170 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1171 int i;
1172 MESSAGE("memid is %08x\n",funcdesc->memid);
1173 for (i=0;i<funcdesc->cParams;i++) {
1174 MESSAGE("Param %d:\n",i);
1175 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1177 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1178 switch (funcdesc->funckind) {
1179 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1180 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1181 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1182 case FUNC_STATIC: MESSAGE("static");break;
1183 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1184 default: MESSAGE("unknown");break;
1186 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1187 switch (funcdesc->invkind) {
1188 case INVOKE_FUNC: MESSAGE("func");break;
1189 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1190 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1191 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1193 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1194 switch (funcdesc->callconv) {
1195 case CC_CDECL: MESSAGE("cdecl");break;
1196 case CC_PASCAL: MESSAGE("pascal");break;
1197 case CC_STDCALL: MESSAGE("stdcall");break;
1198 case CC_SYSCALL: MESSAGE("syscall");break;
1199 default:break;
1201 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1202 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1203 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1205 MESSAGE("\telemdescFunc (return value type):\n");
1206 dump_ELEMDESC(&funcdesc->elemdescFunc);
1209 static const char * const typekind_desc[] =
1211 "TKIND_ENUM",
1212 "TKIND_RECORD",
1213 "TKIND_MODULE",
1214 "TKIND_INTERFACE",
1215 "TKIND_DISPATCH",
1216 "TKIND_COCLASS",
1217 "TKIND_ALIAS",
1218 "TKIND_UNION",
1219 "TKIND_MAX"
1222 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1224 int i;
1225 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1226 for (i=0;i<pfd->funcdesc.cParams;i++)
1227 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1230 dump_FUNCDESC(&(pfd->funcdesc));
1232 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1233 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1235 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1237 while (pfd)
1239 dump_TLBFuncDescOne(pfd);
1240 pfd = pfd->next;
1243 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1245 while (pvd)
1247 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1248 pvd = pvd->next;
1252 static void dump_TLBImpLib(const TLBImpLib *import)
1254 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1255 debugstr_w(import->name));
1256 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1257 import->wVersionMinor, import->lcid, import->offset);
1260 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1262 TLBRefType *ref;
1264 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1266 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1267 if(ref->index == -1)
1268 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1269 else
1270 TRACE_(typelib)("type no: %d\n", ref->index);
1272 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1274 TRACE_(typelib)("in lib\n");
1275 dump_TLBImpLib(ref->pImpTLInfo);
1280 static void dump_TLBImplType(const TLBImplType * impl)
1282 while (impl) {
1283 TRACE_(typelib)(
1284 "implementing/inheriting interface hRef = %x implflags %x\n",
1285 impl->hRef, impl->implflags);
1286 impl = impl->next;
1290 static void dump_Variant(const VARIANT * pvar)
1292 SYSTEMTIME st;
1294 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1296 if (pvar)
1298 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1299 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1301 TRACE(",%p", V_BYREF(pvar));
1303 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1305 TRACE(",%p", V_ARRAY(pvar));
1307 else switch (V_TYPE(pvar))
1309 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1310 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1311 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1312 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1313 case VT_INT:
1314 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1315 case VT_UINT:
1316 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1317 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1318 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1319 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1320 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1321 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1322 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1323 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1324 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1325 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1326 V_CY(pvar).s.Lo); break;
1327 case VT_DATE:
1328 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1329 TRACE(",<invalid>");
1330 else
1331 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1332 st.wHour, st.wMinute, st.wSecond);
1333 break;
1334 case VT_ERROR:
1335 case VT_VOID:
1336 case VT_USERDEFINED:
1337 case VT_EMPTY:
1338 case VT_NULL: break;
1339 default: TRACE(",?"); break;
1342 TRACE("}\n");
1345 static void dump_DispParms(const DISPPARAMS * pdp)
1347 unsigned int index;
1349 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1351 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1353 TRACE("named args:\n");
1354 for (index = 0; index < pdp->cNamedArgs; index++)
1355 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1358 if (pdp->cArgs && pdp->rgvarg)
1360 TRACE("args:\n");
1361 for (index = 0; index < pdp->cArgs; index++)
1362 dump_Variant( &pdp->rgvarg[index] );
1366 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1368 TRACE("%p ref=%u\n", pty, pty->ref);
1369 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1370 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1371 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1372 TRACE("fct:%u var:%u impl:%u\n",
1373 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1374 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1375 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1376 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1377 if (TRACE_ON(ole))
1378 dump_TLBFuncDesc(pty->funclist);
1379 dump_TLBVarDesc(pty->varlist);
1380 dump_TLBImplType(pty->impltypelist);
1383 static void dump_VARDESC(const VARDESC *v)
1385 MESSAGE("memid %d\n",v->memid);
1386 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1387 MESSAGE("oInst %d\n",v->u.oInst);
1388 dump_ELEMDESC(&(v->elemdescVar));
1389 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1390 MESSAGE("varkind %d\n",v->varkind);
1393 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1395 /* VT_LPWSTR is largest type that */
1396 /* may appear in type description*/
1397 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1398 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1399 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1400 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1401 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1402 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1403 {{0},30},{{0},31}
1406 static void TLB_abort(void)
1408 DebugBreak();
1411 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1412 static void * TLB_Alloc(unsigned size)
1414 void * ret;
1415 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1416 /* FIXME */
1417 ERR("cannot allocate memory\n");
1419 return ret;
1422 static void TLB_Free(void * ptr)
1424 HeapFree(GetProcessHeap(), 0, ptr);
1427 /* returns the size required for a deep copy of a typedesc into a
1428 * flat buffer */
1429 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1431 SIZE_T size = 0;
1433 if (alloc_initial_space)
1434 size += sizeof(TYPEDESC);
1436 switch (tdesc->vt)
1438 case VT_PTR:
1439 case VT_SAFEARRAY:
1440 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1441 break;
1442 case VT_CARRAY:
1443 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1444 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1445 break;
1447 return size;
1450 /* deep copy a typedesc into a flat buffer */
1451 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1453 if (!dest)
1455 dest = buffer;
1456 buffer = (char *)buffer + sizeof(TYPEDESC);
1459 *dest = *src;
1461 switch (src->vt)
1463 case VT_PTR:
1464 case VT_SAFEARRAY:
1465 dest->u.lptdesc = buffer;
1466 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1467 break;
1468 case VT_CARRAY:
1469 dest->u.lpadesc = buffer;
1470 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1471 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1472 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1473 break;
1475 return buffer;
1478 /* free custom data allocated by MSFT_CustData */
1479 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1481 TLBCustData *pCustDataNext;
1482 for (; pCustData; pCustData = pCustDataNext)
1484 VariantClear(&pCustData->data);
1486 pCustDataNext = pCustData->next;
1487 TLB_Free(pCustData);
1491 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1493 DWORD len;
1494 BSTR ret;
1496 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1497 ret = SysAllocStringLen(NULL, len - 1);
1498 if (!ret) return ret;
1499 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1500 return ret;
1503 /**********************************************************************
1505 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1507 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1509 return pcx->pos;
1512 static inline void MSFT_Seek(TLBContext *pcx, long where)
1514 if (where != DO_NOT_SEEK)
1516 where += pcx->oStart;
1517 if (where > pcx->length)
1519 /* FIXME */
1520 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1521 TLB_abort();
1523 pcx->pos = where;
1527 /* read function */
1528 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1530 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1531 pcx->pos, count, pcx->oStart, pcx->length, where);
1533 MSFT_Seek(pcx, where);
1534 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1535 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1536 pcx->pos += count;
1537 return count;
1540 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1541 long where )
1543 DWORD ret;
1545 ret = MSFT_Read(buffer, count, pcx, where);
1546 FromLEDWords(buffer, ret);
1548 return ret;
1551 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1552 long where )
1554 DWORD ret;
1556 ret = MSFT_Read(buffer, count, pcx, where);
1557 FromLEWords(buffer, ret);
1559 return ret;
1562 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1564 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1565 memset(pGuid,0, sizeof(GUID));
1566 return;
1568 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1569 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1570 pGuid->Data2 = FromLEWord(pGuid->Data2);
1571 pGuid->Data3 = FromLEWord(pGuid->Data3);
1572 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1575 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1577 MSFT_NameIntro niName;
1579 if (offset < 0)
1581 ERR_(typelib)("bad offset %d\n", offset);
1582 return -1;
1585 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1586 pcx->pTblDir->pNametab.offset+offset);
1588 return niName.hreftype;
1591 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1593 char * name;
1594 MSFT_NameIntro niName;
1595 int lengthInChars;
1596 BSTR bstrName = NULL;
1598 if (offset < 0)
1600 ERR_(typelib)("bad offset %d\n", offset);
1601 return NULL;
1603 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1604 pcx->pTblDir->pNametab.offset+offset);
1605 niName.namelen &= 0xFF; /* FIXME: correct ? */
1606 name=TLB_Alloc((niName.namelen & 0xff) +1);
1607 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1608 name[niName.namelen & 0xff]='\0';
1610 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1611 name, -1, NULL, 0);
1613 /* no invalid characters in string */
1614 if (lengthInChars)
1616 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1618 /* don't check for invalid character since this has been done previously */
1619 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1621 TLB_Free(name);
1623 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1624 return bstrName;
1627 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1629 char * string;
1630 INT16 length;
1631 int lengthInChars;
1632 BSTR bstr = NULL;
1634 if(offset<0) return NULL;
1635 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1636 if(length <= 0) return 0;
1637 string=TLB_Alloc(length +1);
1638 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1639 string[length]='\0';
1641 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1642 string, -1, NULL, 0);
1644 /* no invalid characters in string */
1645 if (lengthInChars)
1647 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1649 /* don't check for invalid character since this has been done previously */
1650 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1652 TLB_Free(string);
1654 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1655 return bstr;
1658 * read a value and fill a VARIANT structure
1660 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1662 int size;
1664 TRACE_(typelib)("\n");
1666 if(offset <0) { /* data are packed in here */
1667 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1668 V_I4(pVar) = offset & 0x3ffffff;
1669 return;
1671 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1672 pcx->pTblDir->pCustData.offset + offset );
1673 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1674 switch (V_VT(pVar)){
1675 case VT_EMPTY: /* FIXME: is this right? */
1676 case VT_NULL: /* FIXME: is this right? */
1677 case VT_I2 : /* this should not happen */
1678 case VT_I4 :
1679 case VT_R4 :
1680 case VT_ERROR :
1681 case VT_BOOL :
1682 case VT_I1 :
1683 case VT_UI1 :
1684 case VT_UI2 :
1685 case VT_UI4 :
1686 case VT_INT :
1687 case VT_UINT :
1688 case VT_VOID : /* FIXME: is this right? */
1689 case VT_HRESULT :
1690 size=4; break;
1691 case VT_R8 :
1692 case VT_CY :
1693 case VT_DATE :
1694 case VT_I8 :
1695 case VT_UI8 :
1696 case VT_DECIMAL : /* FIXME: is this right? */
1697 case VT_FILETIME :
1698 size=8;break;
1699 /* pointer types with known behaviour */
1700 case VT_BSTR :{
1701 char * ptr;
1702 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1703 if(size < 0) {
1704 char next;
1705 DWORD origPos = MSFT_Tell(pcx), nullPos;
1707 do {
1708 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1709 } while (next);
1710 nullPos = MSFT_Tell(pcx);
1711 size = nullPos - origPos;
1712 MSFT_Seek(pcx, origPos);
1714 ptr=TLB_Alloc(size);/* allocate temp buffer */
1715 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1716 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1717 /* FIXME: do we need a AtoW conversion here? */
1718 V_UNION(pVar, bstrVal[size])='\0';
1719 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1720 TLB_Free(ptr);
1722 size=-4; break;
1723 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1724 case VT_DISPATCH :
1725 case VT_VARIANT :
1726 case VT_UNKNOWN :
1727 case VT_PTR :
1728 case VT_SAFEARRAY :
1729 case VT_CARRAY :
1730 case VT_USERDEFINED :
1731 case VT_LPSTR :
1732 case VT_LPWSTR :
1733 case VT_BLOB :
1734 case VT_STREAM :
1735 case VT_STORAGE :
1736 case VT_STREAMED_OBJECT :
1737 case VT_STORED_OBJECT :
1738 case VT_BLOB_OBJECT :
1739 case VT_CF :
1740 case VT_CLSID :
1741 default:
1742 size=0;
1743 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1744 V_VT(pVar));
1747 if(size>0) /* (big|small) endian correct? */
1748 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1749 return;
1752 * create a linked list with custom data
1754 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1756 MSFT_CDGuid entry;
1757 TLBCustData* pNew;
1758 int count=0;
1760 TRACE_(typelib)("\n");
1762 while(offset >=0){
1763 count++;
1764 pNew=TLB_Alloc(sizeof(TLBCustData));
1765 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1766 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1767 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1768 /* add new custom data at head of the list */
1769 pNew->next=*ppCustData;
1770 *ppCustData=pNew;
1771 offset = entry.next;
1773 return count;
1776 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1777 ITypeInfoImpl *pTI)
1779 if(type <0)
1780 pTd->vt=type & VT_TYPEMASK;
1781 else
1782 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1784 if(pTd->vt == VT_USERDEFINED)
1785 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1787 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1790 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1792 /* resolve referenced type if any */
1793 while (lpTypeDesc)
1795 switch (lpTypeDesc->vt)
1797 case VT_PTR:
1798 lpTypeDesc = lpTypeDesc->u.lptdesc;
1799 break;
1801 case VT_CARRAY:
1802 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1803 break;
1805 case VT_USERDEFINED:
1806 MSFT_DoRefType(pcx, pTI->pTypeLib,
1807 lpTypeDesc->u.hreftype);
1809 lpTypeDesc = NULL;
1810 break;
1812 default:
1813 lpTypeDesc = NULL;
1818 static void
1819 MSFT_DoFuncs(TLBContext* pcx,
1820 ITypeInfoImpl* pTI,
1821 int cFuncs,
1822 int cVars,
1823 int offset,
1824 TLBFuncDesc** pptfd)
1827 * member information is stored in a data structure at offset
1828 * indicated by the memoffset field of the typeinfo structure
1829 * There are several distinctive parts.
1830 * The first part starts with a field that holds the total length
1831 * of this (first) part excluding this field. Then follow the records,
1832 * for each member there is one record.
1834 * The first entry is always the length of the record (including this
1835 * length word).
1836 * The rest of the record depends on the type of the member. If there is
1837 * a field indicating the member type (function, variable, interface, etc)
1838 * I have not found it yet. At this time we depend on the information
1839 * in the type info and the usual order how things are stored.
1841 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1842 * for each member;
1844 * Third is an equal sized array with file offsets to the name entry
1845 * of each member.
1847 * The fourth and last (?) part is an array with offsets to the records
1848 * in the first part of this file segment.
1851 int infolen, nameoffset, reclength, nrattributes, i;
1852 int recoffset = offset + sizeof(INT);
1854 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1855 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1856 TLBFuncDesc *ptfd_prev = NULL;
1858 TRACE_(typelib)("\n");
1860 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1862 for ( i = 0; i < cFuncs ; i++ )
1864 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1866 /* name, eventually add to a hash table */
1867 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1868 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1870 /* nameoffset is sometimes -1 on the second half of a propget/propput
1871 * pair of functions */
1872 if ((nameoffset == -1) && (i > 0))
1873 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1874 else
1875 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1877 /* read the function information record */
1878 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1880 reclength &= 0xffff;
1882 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1884 /* do the attributes */
1885 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1886 / sizeof(int);
1888 if ( nrattributes > 0 )
1890 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1892 if ( nrattributes > 1 )
1894 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1895 pFuncRec->OptAttr[1]) ;
1897 if ( nrattributes > 2 )
1899 if ( pFuncRec->FKCCIC & 0x2000 )
1901 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1902 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1903 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1905 else
1907 (*pptfd)->Entry = MSFT_ReadString(pcx,
1908 pFuncRec->OptAttr[2]);
1910 if( nrattributes > 5 )
1912 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1914 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1916 MSFT_CustData(pcx,
1917 pFuncRec->OptAttr[6],
1918 &(*pptfd)->pCustData);
1922 else
1924 (*pptfd)->Entry = (BSTR)-1;
1929 /* fill the FuncDesc Structure */
1930 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1931 offset + infolen + ( i + 1) * sizeof(INT));
1933 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1934 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1935 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1936 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1937 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1938 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1939 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1941 MSFT_GetTdesc(pcx,
1942 pFuncRec->DataType,
1943 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1944 pTI);
1945 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1947 /* do the parameters/arguments */
1948 if(pFuncRec->nrargs)
1950 int j = 0;
1951 MSFT_ParameterInfo paraminfo;
1953 (*pptfd)->funcdesc.lprgelemdescParam =
1954 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1956 (*pptfd)->pParamDesc =
1957 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1959 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1960 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1962 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1964 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1966 MSFT_GetTdesc(pcx,
1967 paraminfo.DataType,
1968 &elemdesc->tdesc,
1969 pTI);
1971 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1973 /* name */
1974 if (paraminfo.oName == -1)
1975 /* this occurs for [propput] or [propget] methods, so
1976 * we should just set the name of the parameter to the
1977 * name of the method. */
1978 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1979 else
1980 (*pptfd)->pParamDesc[j].Name =
1981 MSFT_ReadName( pcx, paraminfo.oName );
1982 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1984 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1986 /* default value */
1987 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1988 (pFuncRec->FKCCIC & 0x1000) )
1990 INT* pInt = (INT *)((char *)pFuncRec +
1991 reclength -
1992 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1994 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1996 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1997 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1999 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2000 pInt[j], pcx);
2002 else
2003 elemdesc->u.paramdesc.pparamdescex = NULL;
2004 /* custom info */
2005 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2007 MSFT_CustData(pcx,
2008 pFuncRec->OptAttr[7+j],
2009 &(*pptfd)->pParamDesc[j].pCustData);
2012 /* SEEK value = jump to offset,
2013 * from there jump to the end of record,
2014 * go back by (j-1) arguments
2016 MSFT_ReadLEDWords( &paraminfo ,
2017 sizeof(MSFT_ParameterInfo), pcx,
2018 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2019 * sizeof(MSFT_ParameterInfo)));
2023 /* scode is not used: archaic win16 stuff FIXME: right? */
2024 (*pptfd)->funcdesc.cScodes = 0 ;
2025 (*pptfd)->funcdesc.lprgscode = NULL ;
2027 ptfd_prev = *pptfd;
2028 pptfd = & ((*pptfd)->next);
2029 recoffset += reclength;
2031 HeapFree(GetProcessHeap(), 0, recbuf);
2034 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2035 int cVars, int offset, TLBVarDesc ** pptvd)
2037 int infolen, nameoffset, reclength;
2038 char recbuf[256];
2039 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2040 int i;
2041 int recoffset;
2043 TRACE_(typelib)("\n");
2045 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2046 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2047 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2048 recoffset += offset+sizeof(INT);
2049 for(i=0;i<cVars;i++){
2050 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2051 /* name, eventually add to a hash table */
2052 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2053 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2054 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2055 /* read the variable information record */
2056 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2057 reclength &=0xff;
2058 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2059 /* Optional data */
2060 if(reclength >(6*sizeof(INT)) )
2061 (*pptvd)->HelpContext=pVarRec->HelpContext;
2062 if(reclength >(7*sizeof(INT)) )
2063 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2064 if(reclength >(8*sizeof(INT)) )
2065 if(reclength >(9*sizeof(INT)) )
2066 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2067 /* fill the VarDesc Structure */
2068 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2069 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2070 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2071 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2072 MSFT_GetTdesc(pcx, pVarRec->DataType,
2073 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2074 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2075 if(pVarRec->VarKind == VAR_CONST ){
2076 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2077 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2078 pVarRec->OffsValue, pcx);
2079 } else
2080 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2081 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2082 pptvd=&((*pptvd)->next);
2083 recoffset += reclength;
2086 /* fill in data for a hreftype (offset). When the referenced type is contained
2087 * in the typelib, it's just an (file) offset in the type info base dir.
2088 * If comes from import, it's an offset+1 in the ImpInfo table
2089 * */
2090 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2091 int offset)
2093 TLBRefType *ref;
2095 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2097 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2099 if(ref->reference == offset) return;
2102 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2103 list_add_tail(&pTL->ref_list, &ref->entry);
2105 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2106 /* external typelib */
2107 MSFT_ImpInfo impinfo;
2108 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2110 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2112 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2113 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2114 while (pImpLib){ /* search the known offsets of all import libraries */
2115 if(pImpLib->offset==impinfo.oImpFile) break;
2116 pImpLib=pImpLib->next;
2118 if(pImpLib){
2119 ref->reference = offset;
2120 ref->pImpTLInfo = pImpLib;
2121 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2122 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2123 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2124 ref->index = TLB_REF_USE_GUID;
2125 } else
2126 ref->index = impinfo.oGuid;
2127 }else{
2128 ERR("Cannot find a reference\n");
2129 ref->reference = -1;
2130 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2132 }else{
2133 /* in this typelib */
2134 ref->index = MSFT_HREFTYPE_INDEX(offset);
2135 ref->reference = offset;
2136 ref->pImpTLInfo = TLB_REF_INTERNAL;
2140 /* process Implemented Interfaces of a com class */
2141 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2142 int offset)
2144 int i;
2145 MSFT_RefRecord refrec;
2146 TLBImplType **ppImpl = &pTI->impltypelist;
2148 TRACE_(typelib)("\n");
2150 for(i=0;i<count;i++){
2151 if(offset<0) break; /* paranoia */
2152 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2153 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2154 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2155 (*ppImpl)->hRef = refrec.reftype;
2156 (*ppImpl)->implflags=refrec.flags;
2157 (*ppImpl)->ctCustData=
2158 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2159 offset=refrec.onext;
2160 ppImpl=&((*ppImpl)->next);
2164 * process a typeinfo record
2166 static ITypeInfoImpl * MSFT_DoTypeInfo(
2167 TLBContext *pcx,
2168 int count,
2169 ITypeLibImpl * pLibInfo)
2171 MSFT_TypeInfoBase tiBase;
2172 ITypeInfoImpl *ptiRet;
2174 TRACE_(typelib)("count=%u\n", count);
2176 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2177 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2178 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2180 /* this is where we are coming from */
2181 ptiRet->pTypeLib = pLibInfo;
2182 ptiRet->index=count;
2183 /* fill in the typeattr fields */
2185 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2186 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2187 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2188 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2189 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2190 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2191 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2192 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2193 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2194 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2195 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2196 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2197 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2198 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2199 MSFT_GetTdesc(pcx, tiBase.datatype1,
2200 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2202 /* FIXME: */
2203 /* IDLDESC idldescType; *//* never saw this one != zero */
2205 /* name, eventually add to a hash table */
2206 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2207 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2208 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2209 /* help info */
2210 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2211 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2212 ptiRet->dwHelpContext=tiBase.helpcontext;
2214 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2215 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2217 /* note: InfoType's Help file and HelpStringDll come from the containing
2218 * library. Further HelpString and Docstring appear to be the same thing :(
2220 /* functions */
2221 if(ptiRet->TypeAttr.cFuncs >0 )
2222 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2223 ptiRet->TypeAttr.cVars,
2224 tiBase.memoffset, & ptiRet->funclist);
2225 /* variables */
2226 if(ptiRet->TypeAttr.cVars >0 )
2227 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2228 ptiRet->TypeAttr.cVars,
2229 tiBase.memoffset, & ptiRet->varlist);
2230 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2231 switch(ptiRet->TypeAttr.typekind)
2233 case TKIND_COCLASS:
2234 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2235 tiBase.datatype1);
2236 break;
2237 case TKIND_DISPATCH:
2238 /* This is not -1 when the interface is a non-base dual interface or
2239 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2240 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2241 not this interface.
2244 if (tiBase.datatype1 != -1)
2246 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2247 ptiRet->impltypelist->hRef = tiBase.datatype1;
2248 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2250 break;
2251 default:
2252 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2253 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2254 ptiRet->impltypelist->hRef = tiBase.datatype1;
2255 break;
2258 ptiRet->ctCustData=
2259 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2261 TRACE_(typelib)("%s guid: %s kind:%s\n",
2262 debugstr_w(ptiRet->Name),
2263 debugstr_guid(&ptiRet->TypeAttr.guid),
2264 typekind_desc[ptiRet->TypeAttr.typekind]);
2265 if (TRACE_ON(typelib))
2266 dump_TypeInfo(ptiRet);
2268 return ptiRet;
2271 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2272 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2273 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2274 * tradeoff here.
2276 static ITypeLibImpl *tlb_cache_first;
2277 static CRITICAL_SECTION cache_section;
2278 static CRITICAL_SECTION_DEBUG cache_section_debug =
2280 0, 0, &cache_section,
2281 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2282 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2284 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2287 typedef struct TLB_PEFile
2289 const IUnknownVtbl *lpvtbl;
2290 LONG refs;
2291 HMODULE dll;
2292 HRSRC typelib_resource;
2293 HGLOBAL typelib_global;
2294 LPVOID typelib_base;
2295 } TLB_PEFile;
2297 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2299 if (IsEqualIID(riid, &IID_IUnknown))
2301 *ppv = iface;
2302 IUnknown_AddRef(iface);
2303 return S_OK;
2305 *ppv = NULL;
2306 return E_NOINTERFACE;
2309 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2311 TLB_PEFile *This = (TLB_PEFile *)iface;
2312 return InterlockedIncrement(&This->refs);
2315 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2317 TLB_PEFile *This = (TLB_PEFile *)iface;
2318 ULONG refs = InterlockedDecrement(&This->refs);
2319 if (!refs)
2321 if (This->typelib_global)
2322 FreeResource(This->typelib_global);
2323 if (This->dll)
2324 FreeLibrary(This->dll);
2325 HeapFree(GetProcessHeap(), 0, This);
2327 return refs;
2330 static const IUnknownVtbl TLB_PEFile_Vtable =
2332 TLB_PEFile_QueryInterface,
2333 TLB_PEFile_AddRef,
2334 TLB_PEFile_Release
2337 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2339 TLB_PEFile *This;
2341 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2342 if (!This)
2343 return E_OUTOFMEMORY;
2345 This->lpvtbl = &TLB_PEFile_Vtable;
2346 This->refs = 1;
2347 This->dll = NULL;
2348 This->typelib_resource = NULL;
2349 This->typelib_global = NULL;
2350 This->typelib_base = NULL;
2352 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2353 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2355 if (This->dll)
2357 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2358 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2359 if (This->typelib_resource)
2361 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2362 if (This->typelib_global)
2364 This->typelib_base = LockResource(This->typelib_global);
2366 if (This->typelib_base)
2368 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2369 *ppBase = This->typelib_base;
2370 *ppFile = (IUnknown *)&This->lpvtbl;
2371 return S_OK;
2377 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2378 return TYPE_E_CANTLOADLIBRARY;
2381 typedef struct TLB_NEFile
2383 const IUnknownVtbl *lpvtbl;
2384 LONG refs;
2385 LPVOID typelib_base;
2386 } TLB_NEFile;
2388 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2390 if (IsEqualIID(riid, &IID_IUnknown))
2392 *ppv = iface;
2393 IUnknown_AddRef(iface);
2394 return S_OK;
2396 *ppv = NULL;
2397 return E_NOINTERFACE;
2400 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2402 TLB_NEFile *This = (TLB_NEFile *)iface;
2403 return InterlockedIncrement(&This->refs);
2406 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2408 TLB_NEFile *This = (TLB_NEFile *)iface;
2409 ULONG refs = InterlockedDecrement(&This->refs);
2410 if (!refs)
2412 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2413 HeapFree(GetProcessHeap(), 0, This);
2415 return refs;
2418 static const IUnknownVtbl TLB_NEFile_Vtable =
2420 TLB_NEFile_QueryInterface,
2421 TLB_NEFile_AddRef,
2422 TLB_NEFile_Release
2425 /***********************************************************************
2426 * read_xx_header [internal]
2428 static int read_xx_header( HFILE lzfd )
2430 IMAGE_DOS_HEADER mzh;
2431 char magic[3];
2433 LZSeek( lzfd, 0, SEEK_SET );
2434 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2435 return 0;
2436 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2437 return 0;
2439 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2440 if ( 2 != LZRead( lzfd, magic, 2 ) )
2441 return 0;
2443 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2445 if ( magic[0] == 'N' && magic[1] == 'E' )
2446 return IMAGE_OS2_SIGNATURE;
2447 if ( magic[0] == 'P' && magic[1] == 'E' )
2448 return IMAGE_NT_SIGNATURE;
2450 magic[2] = '\0';
2451 WARN("Can't handle %s files.\n", magic );
2452 return 0;
2456 /***********************************************************************
2457 * find_ne_resource [internal]
2459 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2460 DWORD *resLen, DWORD *resOff )
2462 IMAGE_OS2_HEADER nehd;
2463 NE_TYPEINFO *typeInfo;
2464 NE_NAMEINFO *nameInfo;
2465 DWORD nehdoffset;
2466 LPBYTE resTab;
2467 DWORD resTabSize;
2468 int count;
2470 /* Read in NE header */
2471 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2472 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2474 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2475 if ( !resTabSize )
2477 TRACE("No resources in NE dll\n" );
2478 return FALSE;
2481 /* Read in resource table */
2482 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2483 if ( !resTab ) return FALSE;
2485 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2486 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2488 HeapFree( GetProcessHeap(), 0, resTab );
2489 return FALSE;
2492 /* Find resource */
2493 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2495 if (HIWORD(typeid) != 0) /* named type */
2497 BYTE len = strlen( typeid );
2498 while (typeInfo->type_id)
2500 if (!(typeInfo->type_id & 0x8000))
2502 BYTE *p = resTab + typeInfo->type_id;
2503 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2505 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2506 typeInfo->count * sizeof(NE_NAMEINFO));
2509 else /* numeric type id */
2511 WORD id = LOWORD(typeid) | 0x8000;
2512 while (typeInfo->type_id)
2514 if (typeInfo->type_id == id) goto found_type;
2515 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2516 typeInfo->count * sizeof(NE_NAMEINFO));
2519 TRACE("No typeid entry found for %p\n", typeid );
2520 HeapFree( GetProcessHeap(), 0, resTab );
2521 return FALSE;
2523 found_type:
2524 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2526 if (HIWORD(resid) != 0) /* named resource */
2528 BYTE len = strlen( resid );
2529 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2531 BYTE *p = resTab + nameInfo->id;
2532 if (nameInfo->id & 0x8000) continue;
2533 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2536 else /* numeric resource id */
2538 WORD id = LOWORD(resid) | 0x8000;
2539 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2540 if (nameInfo->id == id) goto found_name;
2542 TRACE("No resid entry found for %p\n", typeid );
2543 HeapFree( GetProcessHeap(), 0, resTab );
2544 return FALSE;
2546 found_name:
2547 /* Return resource data */
2548 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2549 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2551 HeapFree( GetProcessHeap(), 0, resTab );
2552 return TRUE;
2555 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2557 HFILE lzfd = -1;
2558 OFSTRUCT ofs;
2559 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2560 TLB_NEFile *This = NULL;
2562 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2563 if (!This) return E_OUTOFMEMORY;
2565 This->lpvtbl = &TLB_NEFile_Vtable;
2566 This->refs = 1;
2567 This->typelib_base = NULL;
2569 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2570 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2572 DWORD reslen, offset;
2573 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2575 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2576 if( !This->typelib_base )
2577 hr = E_OUTOFMEMORY;
2578 else
2580 LZSeek( lzfd, offset, SEEK_SET );
2581 reslen = LZRead( lzfd, This->typelib_base, reslen );
2582 LZClose( lzfd );
2583 *ppBase = This->typelib_base;
2584 *pdwTLBLength = reslen;
2585 *ppFile = (IUnknown *)&This->lpvtbl;
2586 return S_OK;
2591 if( lzfd >= 0) LZClose( lzfd );
2592 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2593 return hr;
2596 typedef struct TLB_Mapping
2598 const IUnknownVtbl *lpvtbl;
2599 LONG refs;
2600 HANDLE file;
2601 HANDLE mapping;
2602 LPVOID typelib_base;
2603 } TLB_Mapping;
2605 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2607 if (IsEqualIID(riid, &IID_IUnknown))
2609 *ppv = iface;
2610 IUnknown_AddRef(iface);
2611 return S_OK;
2613 *ppv = NULL;
2614 return E_NOINTERFACE;
2617 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2619 TLB_Mapping *This = (TLB_Mapping *)iface;
2620 return InterlockedIncrement(&This->refs);
2623 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2625 TLB_Mapping *This = (TLB_Mapping *)iface;
2626 ULONG refs = InterlockedDecrement(&This->refs);
2627 if (!refs)
2629 if (This->typelib_base)
2630 UnmapViewOfFile(This->typelib_base);
2631 if (This->mapping)
2632 CloseHandle(This->mapping);
2633 if (This->file != INVALID_HANDLE_VALUE)
2634 CloseHandle(This->file);
2635 HeapFree(GetProcessHeap(), 0, This);
2637 return refs;
2640 static const IUnknownVtbl TLB_Mapping_Vtable =
2642 TLB_Mapping_QueryInterface,
2643 TLB_Mapping_AddRef,
2644 TLB_Mapping_Release
2647 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2649 TLB_Mapping *This;
2651 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2652 if (!This)
2653 return E_OUTOFMEMORY;
2655 This->lpvtbl = &TLB_Mapping_Vtable;
2656 This->refs = 1;
2657 This->file = INVALID_HANDLE_VALUE;
2658 This->mapping = NULL;
2659 This->typelib_base = NULL;
2661 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2662 if (INVALID_HANDLE_VALUE != This->file)
2664 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2665 if (This->mapping)
2667 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2668 if(This->typelib_base)
2670 /* retrieve file size */
2671 *pdwTLBLength = GetFileSize(This->file, NULL);
2672 *ppBase = This->typelib_base;
2673 *ppFile = (IUnknown *)&This->lpvtbl;
2674 return S_OK;
2679 IUnknown_Release((IUnknown *)&This->lpvtbl);
2680 return TYPE_E_CANTLOADLIBRARY;
2683 /****************************************************************************
2684 * TLB_ReadTypeLib
2686 * find the type of the typelib file and map the typelib resource into
2687 * the memory
2689 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2690 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2691 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2693 ITypeLibImpl *entry;
2694 HRESULT ret;
2695 INT index = 1;
2696 LPWSTR index_str, file = (LPWSTR)pszFileName;
2697 LPVOID pBase = NULL;
2698 DWORD dwTLBLength = 0;
2699 IUnknown *pFile = NULL;
2701 *ppTypeLib = NULL;
2703 index_str = strrchrW(pszFileName, '\\');
2704 if(index_str && *++index_str != '\0')
2706 LPWSTR end_ptr;
2707 long idx = strtolW(index_str, &end_ptr, 10);
2708 if(*end_ptr == '\0')
2710 int str_len = index_str - pszFileName - 1;
2711 index = idx;
2712 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2713 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2714 file[str_len] = 0;
2718 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2720 if(strchrW(file, '\\'))
2722 lstrcpyW(pszPath, file);
2724 else
2726 int len = GetSystemDirectoryW(pszPath, cchPath);
2727 pszPath[len] = '\\';
2728 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2732 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2734 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2736 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2737 EnterCriticalSection(&cache_section);
2738 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2740 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2742 TRACE("cache hit\n");
2743 *ppTypeLib = (ITypeLib2*)entry;
2744 ITypeLib_AddRef(*ppTypeLib);
2745 LeaveCriticalSection(&cache_section);
2746 return S_OK;
2749 LeaveCriticalSection(&cache_section);
2751 /* now actually load and parse the typelib */
2753 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2754 if (ret == TYPE_E_CANTLOADLIBRARY)
2755 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2756 if (ret == TYPE_E_CANTLOADLIBRARY)
2757 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2758 if (SUCCEEDED(ret))
2760 if (dwTLBLength >= 4)
2762 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2763 if (dwSignature == MSFT_SIGNATURE)
2764 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2765 else if (dwSignature == SLTG_SIGNATURE)
2766 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2767 else
2769 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2770 ret = TYPE_E_CANTLOADLIBRARY;
2773 else
2774 ret = TYPE_E_CANTLOADLIBRARY;
2775 IUnknown_Release(pFile);
2778 if(*ppTypeLib) {
2779 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2781 TRACE("adding to cache\n");
2782 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2783 lstrcpyW(impl->path, pszPath);
2784 /* We should really canonicalise the path here. */
2785 impl->index = index;
2787 /* FIXME: check if it has added already in the meantime */
2788 EnterCriticalSection(&cache_section);
2789 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2790 impl->prev = NULL;
2791 tlb_cache_first = impl;
2792 LeaveCriticalSection(&cache_section);
2793 ret = S_OK;
2794 } else
2795 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2797 return ret;
2800 /*================== ITypeLib(2) Methods ===================================*/
2802 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2804 ITypeLibImpl* pTypeLibImpl;
2806 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2807 if (!pTypeLibImpl) return NULL;
2809 pTypeLibImpl->lpVtbl = &tlbvt;
2810 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2811 pTypeLibImpl->ref = 1;
2813 list_init(&pTypeLibImpl->ref_list);
2814 pTypeLibImpl->dispatch_href = -1;
2816 return pTypeLibImpl;
2819 /****************************************************************************
2820 * ITypeLib2_Constructor_MSFT
2822 * loading an MSFT typelib from an in-memory image
2824 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2826 TLBContext cx;
2827 long lPSegDir;
2828 MSFT_Header tlbHeader;
2829 MSFT_SegDir tlbSegDir;
2830 ITypeLibImpl * pTypeLibImpl;
2832 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2834 pTypeLibImpl = TypeLibImpl_Constructor();
2835 if (!pTypeLibImpl) return NULL;
2837 /* get pointer to beginning of typelib data */
2838 cx.pos = 0;
2839 cx.oStart=0;
2840 cx.mapping = pLib;
2841 cx.pLibInfo = pTypeLibImpl;
2842 cx.length = dwTLBLength;
2844 /* read header */
2845 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2846 TRACE_(typelib)("header:\n");
2847 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2848 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2849 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2850 return NULL;
2852 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2854 /* there is a small amount of information here until the next important
2855 * part:
2856 * the segment directory . Try to calculate the amount of data */
2857 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2859 /* now read the segment directory */
2860 TRACE("read segment directory (at %ld)\n",lPSegDir);
2861 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2862 cx.pTblDir = &tlbSegDir;
2864 /* just check two entries */
2865 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2867 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2868 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2869 return NULL;
2872 /* now fill our internal data */
2873 /* TLIBATTR fields */
2874 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2876 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2877 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2878 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2879 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2880 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2882 pTypeLibImpl->lcid = tlbHeader.lcid;
2884 /* name, eventually add to a hash table */
2885 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2887 /* help info */
2888 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2889 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2891 if( tlbHeader.varflags & HELPDLLFLAG)
2893 int offset;
2894 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2895 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2898 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2900 /* custom data */
2901 if(tlbHeader.CustomDataOffset >= 0)
2903 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2906 /* fill in type descriptions */
2907 if(tlbSegDir.pTypdescTab.length > 0)
2909 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2910 INT16 td[4];
2911 pTypeLibImpl->ctTypeDesc = cTD;
2912 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2913 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2914 for(i=0; i<cTD; )
2916 /* FIXME: add several sanity checks here */
2917 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2918 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2920 /* FIXME: check safearray */
2921 if(td[3] < 0)
2922 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2923 else
2924 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2926 else if(td[0] == VT_CARRAY)
2928 /* array descr table here */
2929 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2931 else if(td[0] == VT_USERDEFINED)
2933 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2935 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2938 /* second time around to fill the array subscript info */
2939 for(i=0;i<cTD;i++)
2941 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2942 if(tlbSegDir.pArrayDescriptions.offset>0)
2944 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2945 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2947 if(td[1]<0)
2948 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2949 else
2950 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
2952 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2954 for(j = 0; j<td[2]; j++)
2956 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2957 sizeof(INT), &cx, DO_NOT_SEEK);
2958 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2959 sizeof(INT), &cx, DO_NOT_SEEK);
2962 else
2964 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2965 ERR("didn't find array description data\n");
2970 /* imported type libs */
2971 if(tlbSegDir.pImpFiles.offset>0)
2973 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2974 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2975 UINT16 size;
2977 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2979 char *name;
2981 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2982 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2983 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2985 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2986 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2987 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2988 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2990 size >>= 2;
2991 name = TLB_Alloc(size+1);
2992 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2993 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2995 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2996 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2998 ppImpLib = &(*ppImpLib)->next;
3002 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3003 if(pTypeLibImpl->dispatch_href != -1)
3004 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3006 /* type info's */
3007 if(tlbHeader.nrtypeinfos >= 0 )
3009 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3010 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3011 int i;
3013 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3015 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3017 ppTI = &((*ppTI)->next);
3018 (pTypeLibImpl->TypeInfoCount)++;
3022 TRACE("(%p)\n", pTypeLibImpl);
3023 return (ITypeLib2*) pTypeLibImpl;
3027 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3029 char b[3];
3030 int i;
3031 short s;
3033 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3034 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3035 return FALSE;
3038 guid->Data4[0] = s >> 8;
3039 guid->Data4[1] = s & 0xff;
3041 b[2] = '\0';
3042 for(i = 0; i < 6; i++) {
3043 memcpy(b, str + 24 + 2 * i, 2);
3044 guid->Data4[i + 2] = strtol(b, NULL, 16);
3046 return TRUE;
3049 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3051 WORD bytelen;
3052 DWORD len;
3054 *pBstr = NULL;
3055 bytelen = *(const WORD*)ptr;
3056 if(bytelen == 0xffff) return 2;
3057 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3058 *pBstr = SysAllocStringLen(NULL, len);
3059 if (*pBstr)
3060 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3061 return bytelen + 2;
3064 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3066 WORD bytelen;
3068 *str = NULL;
3069 bytelen = *(const WORD*)ptr;
3070 if(bytelen == 0xffff) return 2;
3071 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3072 memcpy(*str, ptr + 2, bytelen);
3073 (*str)[bytelen] = '\0';
3074 return bytelen + 2;
3077 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3079 char *ptr = pLibBlk;
3080 WORD w;
3082 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3083 FIXME("libblk magic = %04x\n", w);
3084 return 0;
3087 ptr += 6;
3088 if((w = *(WORD*)ptr) != 0xffff) {
3089 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3090 ptr += w;
3092 ptr += 2;
3094 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3096 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3098 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3099 ptr += 4;
3101 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3102 ptr += 2;
3104 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3105 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3106 else
3107 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3108 ptr += 2;
3110 ptr += 4; /* skip res12 */
3112 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3113 ptr += 2;
3115 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3116 ptr += 2;
3118 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3119 ptr += 2;
3121 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3122 ptr += sizeof(GUID);
3124 return ptr - (char*)pLibBlk;
3127 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3128 typedef struct
3130 unsigned int num;
3131 HREFTYPE refs[1];
3132 } sltg_ref_lookup_t;
3134 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3135 HREFTYPE *typelib_ref)
3137 if(table && typeinfo_ref < table->num)
3139 *typelib_ref = table->refs[typeinfo_ref];
3140 return S_OK;
3143 ERR_(typelib)("Unable to find reference\n");
3144 *typelib_ref = -1;
3145 return E_FAIL;
3148 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3150 BOOL done = FALSE;
3152 while(!done) {
3153 if((*pType & 0xe00) == 0xe00) {
3154 pTD->vt = VT_PTR;
3155 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3156 sizeof(TYPEDESC));
3157 pTD = pTD->u.lptdesc;
3159 switch(*pType & 0x3f) {
3160 case VT_PTR:
3161 pTD->vt = VT_PTR;
3162 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3163 sizeof(TYPEDESC));
3164 pTD = pTD->u.lptdesc;
3165 break;
3167 case VT_USERDEFINED:
3168 pTD->vt = VT_USERDEFINED;
3169 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3170 done = TRUE;
3171 break;
3173 case VT_CARRAY:
3175 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3176 array */
3178 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3180 pTD->vt = VT_CARRAY;
3181 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3182 sizeof(ARRAYDESC) +
3183 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3184 pTD->u.lpadesc->cDims = pSA->cDims;
3185 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3186 pSA->cDims * sizeof(SAFEARRAYBOUND));
3188 pTD = &pTD->u.lpadesc->tdescElem;
3189 break;
3192 case VT_SAFEARRAY:
3194 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3195 useful? */
3197 pType++;
3198 pTD->vt = VT_SAFEARRAY;
3199 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3200 sizeof(TYPEDESC));
3201 pTD = pTD->u.lptdesc;
3202 break;
3204 default:
3205 pTD->vt = *pType & 0x3f;
3206 done = TRUE;
3207 break;
3209 pType++;
3211 return pType;
3214 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3215 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3217 /* Handle [in/out] first */
3218 if((*pType & 0xc000) == 0xc000)
3219 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3220 else if(*pType & 0x8000)
3221 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3222 else if(*pType & 0x4000)
3223 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3224 else
3225 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3227 if(*pType & 0x2000)
3228 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3230 if(*pType & 0x80)
3231 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3233 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3237 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3238 char *pNameTable)
3240 unsigned int ref;
3241 char *name;
3242 TLBRefType *ref_type;
3243 sltg_ref_lookup_t *table;
3244 HREFTYPE typelib_ref;
3246 if(pRef->magic != SLTG_REF_MAGIC) {
3247 FIXME("Ref magic = %x\n", pRef->magic);
3248 return NULL;
3250 name = ( (char*)pRef->names + pRef->number);
3252 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3253 table->num = pRef->number >> 3;
3255 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3257 /* We don't want the first href to be 0 */
3258 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3260 for(ref = 0; ref < pRef->number >> 3; ref++) {
3261 char *refname;
3262 unsigned int lib_offs, type_num;
3264 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3266 name += SLTG_ReadStringA(name, &refname);
3267 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3268 FIXME_(typelib)("Can't sscanf ref\n");
3269 if(lib_offs != 0xffff) {
3270 TLBImpLib **import = &pTL->pImpLibs;
3272 while(*import) {
3273 if((*import)->offset == lib_offs)
3274 break;
3275 import = &(*import)->next;
3277 if(!*import) {
3278 char fname[MAX_PATH+1];
3279 int len;
3281 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3282 sizeof(**import));
3283 (*import)->offset = lib_offs;
3284 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3285 &(*import)->guid);
3286 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3287 &(*import)->wVersionMajor,
3288 &(*import)->wVersionMinor,
3289 &(*import)->lcid, fname) != 4) {
3290 FIXME_(typelib)("can't sscanf ref %s\n",
3291 pNameTable + lib_offs + 40);
3293 len = strlen(fname);
3294 if(fname[len-1] != '#')
3295 FIXME("fname = %s\n", fname);
3296 fname[len-1] = '\0';
3297 (*import)->name = TLB_MultiByteToBSTR(fname);
3299 ref_type->pImpTLInfo = *import;
3301 /* Store a reference to IDispatch */
3302 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3303 pTL->dispatch_href = typelib_ref;
3305 } else { /* internal ref */
3306 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3308 ref_type->reference = typelib_ref;
3309 ref_type->index = type_num;
3311 HeapFree(GetProcessHeap(), 0, refname);
3312 list_add_tail(&pTL->ref_list, &ref_type->entry);
3314 table->refs[ref] = typelib_ref;
3315 typelib_ref += 4;
3317 if((BYTE)*name != SLTG_REF_MAGIC)
3318 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3319 dump_TLBRefType(pTL);
3320 return table;
3323 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3324 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3326 SLTG_ImplInfo *info;
3327 TLBImplType **ppImplType = &pTI->impltypelist;
3328 /* I don't really get this structure, usually it's 0x16 bytes
3329 long, but iuser.tlb contains some that are 0x18 bytes long.
3330 That's ok because we can use the next ptr to jump to the next
3331 one. But how do we know the length of the last one? The WORD
3332 at offs 0x8 might be the clue. For now I'm just assuming that
3333 the last one is the regular 0x16 bytes. */
3335 info = (SLTG_ImplInfo*)pBlk;
3336 while(1) {
3337 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3338 sizeof(**ppImplType));
3339 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3340 (*ppImplType)->implflags = info->impltypeflags;
3341 pTI->TypeAttr.cImplTypes++;
3342 ppImplType = &(*ppImplType)->next;
3344 if(info->next == 0xffff)
3345 break;
3346 if(OneOnly)
3347 FIXME_(typelib)("Interface inheriting more than one interface\n");
3348 info = (SLTG_ImplInfo*)(pBlk + info->next);
3350 info++; /* see comment at top of function */
3351 return (char*)info;
3354 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3355 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3357 TLBVarDesc **ppVarDesc = &pTI->varlist;
3358 BSTR bstrPrevName = NULL;
3359 SLTG_Variable *pItem;
3360 unsigned short i;
3361 WORD *pType;
3363 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3364 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3366 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3367 sizeof(**ppVarDesc));
3368 (*ppVarDesc)->vardesc.memid = pItem->memid;
3370 if (pItem->magic != SLTG_VAR_MAGIC &&
3371 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3372 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3373 return;
3376 if (pItem->name == 0xfffe)
3377 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3378 else
3379 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3381 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3382 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3383 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3385 if(pItem->flags & 0x02)
3386 pType = &pItem->type;
3387 else
3388 pType = (WORD*)(pBlk + pItem->type);
3390 if (pItem->flags & ~0xda)
3391 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3393 SLTG_DoElem(pType, pBlk,
3394 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3396 if (TRACE_ON(typelib)) {
3397 char buf[300];
3398 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3399 TRACE_(typelib)("elemdescVar: %s\n", buf);
3402 if (pItem->flags & 0x40) {
3403 TRACE_(typelib)("VAR_DISPATCH\n");
3404 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3406 else if (pItem->flags & 0x10) {
3407 TRACE_(typelib)("VAR_CONST\n");
3408 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3409 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3410 sizeof(VARIANT));
3411 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3412 if (pItem->flags & 0x08)
3413 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3414 else {
3415 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3417 case VT_LPSTR:
3418 case VT_LPWSTR:
3419 case VT_BSTR:
3421 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3422 BSTR str;
3423 TRACE_(typelib)("len = %u\n", len);
3424 if (len == 0xffff) {
3425 str = NULL;
3426 } else {
3427 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3428 str = SysAllocStringLen(NULL, alloc_len);
3429 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3431 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3432 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3433 break;
3435 case VT_I2:
3436 case VT_UI2:
3437 case VT_I4:
3438 case VT_UI4:
3439 case VT_INT:
3440 case VT_UINT:
3441 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3442 *(INT*)(pBlk + pItem->byte_offs);
3443 break;
3444 default:
3445 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3449 else {
3450 TRACE_(typelib)("VAR_PERINSTANCE\n");
3451 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3452 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3455 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3456 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3458 if (pItem->flags & 0x80)
3459 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3461 bstrPrevName = (*ppVarDesc)->Name;
3462 ppVarDesc = &((*ppVarDesc)->next);
3464 pTI->TypeAttr.cVars = cVars;
3467 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3468 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3470 SLTG_Function *pFunc;
3471 unsigned short i;
3472 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3474 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3475 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3477 int param;
3478 WORD *pType, *pArg;
3480 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3481 sizeof(**ppFuncDesc));
3483 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3484 case SLTG_FUNCTION_MAGIC:
3485 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3486 break;
3487 case SLTG_DISPATCH_FUNCTION_MAGIC:
3488 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3489 break;
3490 case SLTG_STATIC_FUNCTION_MAGIC:
3491 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3492 break;
3493 default:
3494 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3495 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3496 *ppFuncDesc = NULL;
3497 return;
3499 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3501 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3502 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3503 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3504 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3505 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3506 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3508 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3509 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3511 if(pFunc->retnextopt & 0x80)
3512 pType = &pFunc->rettype;
3513 else
3514 pType = (WORD*)(pBlk + pFunc->rettype);
3516 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3518 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3519 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3520 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3521 (*ppFuncDesc)->pParamDesc =
3522 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3523 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3525 pArg = (WORD*)(pBlk + pFunc->arg_off);
3527 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3528 char *paramName = pNameTable + *pArg;
3529 BOOL HaveOffs;
3530 /* If arg type follows then paramName points to the 2nd
3531 letter of the name, else the next WORD is an offset to
3532 the arg type and paramName points to the first letter.
3533 So let's take one char off paramName and see if we're
3534 pointing at an alpha-numeric char. However if *pArg is
3535 0xffff or 0xfffe then the param has no name, the former
3536 meaning that the next WORD is the type, the latter
3537 meaning that the next WORD is an offset to the type. */
3539 HaveOffs = FALSE;
3540 if(*pArg == 0xffff)
3541 paramName = NULL;
3542 else if(*pArg == 0xfffe) {
3543 paramName = NULL;
3544 HaveOffs = TRUE;
3546 else if(paramName[-1] && !isalnum(paramName[-1]))
3547 HaveOffs = TRUE;
3549 pArg++;
3551 if(HaveOffs) { /* the next word is an offset to type */
3552 pType = (WORD*)(pBlk + *pArg);
3553 SLTG_DoElem(pType, pBlk,
3554 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3555 pArg++;
3556 } else {
3557 if(paramName)
3558 paramName--;
3559 pArg = SLTG_DoElem(pArg, pBlk,
3560 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3563 /* Are we an optional param ? */
3564 if((*ppFuncDesc)->funcdesc.cParams - param <=
3565 (*ppFuncDesc)->funcdesc.cParamsOpt)
3566 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3568 if(paramName) {
3569 (*ppFuncDesc)->pParamDesc[param].Name =
3570 TLB_MultiByteToBSTR(paramName);
3571 } else {
3572 (*ppFuncDesc)->pParamDesc[param].Name =
3573 SysAllocString((*ppFuncDesc)->Name);
3577 ppFuncDesc = &((*ppFuncDesc)->next);
3578 if(pFunc->next == 0xffff) break;
3580 pTI->TypeAttr.cFuncs = cFuncs;
3583 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3584 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3585 SLTG_TypeInfoTail *pTITail)
3587 char *pFirstItem;
3588 sltg_ref_lookup_t *ref_lookup = NULL;
3590 if(pTIHeader->href_table != 0xffffffff) {
3591 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3592 pNameTable);
3595 pFirstItem = pBlk;
3597 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3598 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3600 HeapFree(GetProcessHeap(), 0, ref_lookup);
3604 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3605 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3606 const SLTG_TypeInfoTail *pTITail)
3608 char *pFirstItem;
3609 sltg_ref_lookup_t *ref_lookup = NULL;
3611 if(pTIHeader->href_table != 0xffffffff) {
3612 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3613 pNameTable);
3616 pFirstItem = pBlk;
3618 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3619 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3622 if (pTITail->funcs_off != 0xffff)
3623 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3625 HeapFree(GetProcessHeap(), 0, ref_lookup);
3627 if (TRACE_ON(typelib))
3628 dump_TLBFuncDesc(pTI->funclist);
3631 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3632 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3633 const SLTG_TypeInfoTail *pTITail)
3635 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3638 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3639 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3640 const SLTG_TypeInfoTail *pTITail)
3642 WORD *pType;
3643 sltg_ref_lookup_t *ref_lookup = NULL;
3645 if (pTITail->simple_alias) {
3646 /* if simple alias, no more processing required */
3647 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3648 return;
3651 if(pTIHeader->href_table != 0xffffffff) {
3652 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3653 pNameTable);
3656 /* otherwise it is an offset to a type */
3657 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3659 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3661 HeapFree(GetProcessHeap(), 0, ref_lookup);
3664 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3665 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3666 const SLTG_TypeInfoTail *pTITail)
3668 sltg_ref_lookup_t *ref_lookup = NULL;
3669 if (pTIHeader->href_table != 0xffffffff)
3670 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3671 pNameTable);
3673 if (pTITail->vars_off != 0xffff)
3674 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3676 if (pTITail->funcs_off != 0xffff)
3677 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3679 if (pTITail->impls_off != 0xffff)
3680 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3682 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3683 * of dispinterface functions including the IDispatch ones, so
3684 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3685 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3687 HeapFree(GetProcessHeap(), 0, ref_lookup);
3688 if (TRACE_ON(typelib))
3689 dump_TLBFuncDesc(pTI->funclist);
3692 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3693 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3694 const SLTG_TypeInfoTail *pTITail)
3696 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3699 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3700 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3701 const SLTG_TypeInfoTail *pTITail)
3703 sltg_ref_lookup_t *ref_lookup = NULL;
3704 if (pTIHeader->href_table != 0xffffffff)
3705 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3706 pNameTable);
3708 if (pTITail->vars_off != 0xffff)
3709 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3711 if (pTITail->funcs_off != 0xffff)
3712 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3713 HeapFree(GetProcessHeap(), 0, ref_lookup);
3714 if (TRACE_ON(typelib))
3715 dump_TypeInfo(pTI);
3718 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3719 managable copy of it into this */
3720 typedef struct {
3721 WORD small_no;
3722 char *index_name;
3723 char *other_name;
3724 WORD res1a;
3725 WORD name_offs;
3726 WORD more_bytes;
3727 char *extra;
3728 WORD res20;
3729 DWORD helpcontext;
3730 WORD res26;
3731 GUID uuid;
3732 } SLTG_InternalOtherTypeInfo;
3734 /****************************************************************************
3735 * ITypeLib2_Constructor_SLTG
3737 * loading a SLTG typelib from an in-memory image
3739 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3741 ITypeLibImpl *pTypeLibImpl;
3742 SLTG_Header *pHeader;
3743 SLTG_BlkEntry *pBlkEntry;
3744 SLTG_Magic *pMagic;
3745 SLTG_Index *pIndex;
3746 SLTG_Pad9 *pPad9;
3747 LPVOID pBlk, pFirstBlk;
3748 SLTG_LibBlk *pLibBlk;
3749 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3750 char *pAfterOTIBlks = NULL;
3751 char *pNameTable, *ptr;
3752 int i;
3753 DWORD len, order;
3754 ITypeInfoImpl **ppTypeInfoImpl;
3756 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3759 pTypeLibImpl = TypeLibImpl_Constructor();
3760 if (!pTypeLibImpl) return NULL;
3762 pHeader = pLib;
3764 TRACE_(typelib)("header:\n");
3765 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3766 pHeader->nrOfFileBlks );
3767 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3768 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3769 pHeader->SLTG_magic);
3770 return NULL;
3773 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3774 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3776 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3777 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3779 /* Next we have a magic block */
3780 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3782 /* Let's see if we're still in sync */
3783 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3784 sizeof(SLTG_COMPOBJ_MAGIC))) {
3785 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3786 return NULL;
3788 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3789 sizeof(SLTG_DIR_MAGIC))) {
3790 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3791 return NULL;
3794 pIndex = (SLTG_Index*)(pMagic+1);
3796 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3798 pFirstBlk = pPad9 + 1;
3800 /* We'll set up a ptr to the main library block, which is the last one. */
3802 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3803 pBlkEntry[order].next != 0;
3804 order = pBlkEntry[order].next - 1, i++) {
3805 pBlk = (char*)pBlk + pBlkEntry[order].len;
3807 pLibBlk = pBlk;
3809 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3811 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3812 interspersed */
3814 len += 0x40;
3816 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3818 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3819 sizeof(*pOtherTypeInfoBlks) *
3820 pTypeLibImpl->TypeInfoCount);
3823 ptr = (char*)pLibBlk + len;
3825 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3826 WORD w, extra;
3827 len = 0;
3829 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3831 w = *(WORD*)(ptr + 2);
3832 if(w != 0xffff) {
3833 len += w;
3834 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3835 w+1);
3836 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3837 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3839 w = *(WORD*)(ptr + 4 + len);
3840 if(w != 0xffff) {
3841 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3842 len += w;
3843 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3844 w+1);
3845 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3846 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3848 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3849 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3850 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3851 if(extra) {
3852 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3853 extra);
3854 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3855 len += extra;
3857 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3858 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3859 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3860 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3861 len += sizeof(SLTG_OtherTypeInfo);
3862 ptr += len;
3865 pAfterOTIBlks = ptr;
3867 /* Skip this WORD and get the next DWORD */
3868 len = *(DWORD*)(pAfterOTIBlks + 2);
3870 /* Now add this to pLibBLk look at what we're pointing at and
3871 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3872 dust and we should be pointing at the beginning of the name
3873 table */
3875 pNameTable = (char*)pLibBlk + len;
3877 switch(*(WORD*)pNameTable) {
3878 case 0xffff:
3879 break;
3880 case 0x0200:
3881 pNameTable += 0x20;
3882 break;
3883 default:
3884 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3885 break;
3888 pNameTable += 0x216;
3890 pNameTable += 2;
3892 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3894 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3897 /* Hopefully we now have enough ptrs set up to actually read in
3898 some TypeInfos. It's not clear which order to do them in, so
3899 I'll just follow the links along the BlkEntry chain and read
3900 them in the order in which they are in the file */
3902 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3904 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3905 pBlkEntry[order].next != 0;
3906 order = pBlkEntry[order].next - 1, i++) {
3908 SLTG_TypeInfoHeader *pTIHeader;
3909 SLTG_TypeInfoTail *pTITail;
3910 SLTG_MemberHeader *pMemHeader;
3912 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3913 pOtherTypeInfoBlks[i].index_name)) {
3914 FIXME_(typelib)("Index strings don't match\n");
3915 return NULL;
3918 pTIHeader = pBlk;
3919 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3920 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3921 return NULL;
3923 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3924 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3925 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3927 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3928 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3929 (*ppTypeInfoImpl)->index = i;
3930 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3931 pOtherTypeInfoBlks[i].name_offs +
3932 pNameTable);
3933 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3934 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3935 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3936 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3937 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3938 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3939 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3941 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3942 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3944 if((pTIHeader->typeflags1 & 7) != 2)
3945 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3946 if(pTIHeader->typeflags3 != 2)
3947 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3949 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3950 debugstr_w((*ppTypeInfoImpl)->Name),
3951 typekind_desc[pTIHeader->typekind],
3952 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3953 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3955 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3957 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3959 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3960 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3961 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3963 switch(pTIHeader->typekind) {
3964 case TKIND_ENUM:
3965 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3966 pTIHeader, pTITail);
3967 break;
3969 case TKIND_RECORD:
3970 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3971 pTIHeader, pTITail);
3972 break;
3974 case TKIND_INTERFACE:
3975 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3976 pTIHeader, pTITail);
3977 break;
3979 case TKIND_COCLASS:
3980 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3981 pTIHeader, pTITail);
3982 break;
3984 case TKIND_ALIAS:
3985 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3986 pTIHeader, pTITail);
3987 break;
3989 case TKIND_DISPATCH:
3990 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3991 pTIHeader, pTITail);
3992 break;
3994 case TKIND_MODULE:
3995 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3996 pTIHeader, pTITail);
3997 break;
3999 default:
4000 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4001 break;
4005 /* could get cFuncs, cVars and cImplTypes from here
4006 but we've already set those */
4007 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4008 X(06);
4009 X(16);
4010 X(18);
4011 X(1a);
4012 X(1e);
4013 X(24);
4014 X(26);
4015 X(2a);
4016 X(2c);
4017 X(2e);
4018 X(30);
4019 X(32);
4020 X(34);
4021 #undef X
4022 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4023 pBlk = (char*)pBlk + pBlkEntry[order].len;
4026 if(i != pTypeLibImpl->TypeInfoCount) {
4027 FIXME("Somehow processed %d TypeInfos\n", i);
4028 return NULL;
4031 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4032 return (ITypeLib2*)pTypeLibImpl;
4035 /* ITypeLib::QueryInterface
4037 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4038 ITypeLib2 * iface,
4039 REFIID riid,
4040 VOID **ppvObject)
4042 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4044 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4046 *ppvObject=NULL;
4047 if(IsEqualIID(riid, &IID_IUnknown) ||
4048 IsEqualIID(riid,&IID_ITypeLib)||
4049 IsEqualIID(riid,&IID_ITypeLib2))
4051 *ppvObject = This;
4054 if(*ppvObject)
4056 ITypeLib2_AddRef(iface);
4057 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4058 return S_OK;
4060 TRACE("-- Interface: E_NOINTERFACE\n");
4061 return E_NOINTERFACE;
4064 /* ITypeLib::AddRef
4066 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4068 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4069 ULONG ref = InterlockedIncrement(&This->ref);
4071 TRACE("(%p)->ref was %u\n",This, ref - 1);
4073 return ref;
4076 /* ITypeLib::Release
4078 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4080 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4081 ULONG ref = InterlockedDecrement(&This->ref);
4083 TRACE("(%p)->(%u)\n",This, ref);
4085 if (!ref)
4087 TLBImpLib *pImpLib, *pImpLibNext;
4088 TLBCustData *pCustData, *pCustDataNext;
4089 TLBRefType *ref_type;
4090 void *cursor2;
4091 int i;
4093 /* remove cache entry */
4094 if(This->path)
4096 TRACE("removing from cache list\n");
4097 EnterCriticalSection(&cache_section);
4098 if (This->next) This->next->prev = This->prev;
4099 if (This->prev) This->prev->next = This->next;
4100 else tlb_cache_first = This->next;
4101 LeaveCriticalSection(&cache_section);
4102 HeapFree(GetProcessHeap(), 0, This->path);
4104 TRACE(" destroying ITypeLib(%p)\n",This);
4106 SysFreeString(This->Name);
4107 This->Name = NULL;
4109 SysFreeString(This->DocString);
4110 This->DocString = NULL;
4112 SysFreeString(This->HelpFile);
4113 This->HelpFile = NULL;
4115 SysFreeString(This->HelpStringDll);
4116 This->HelpStringDll = NULL;
4118 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4120 VariantClear(&pCustData->data);
4122 pCustDataNext = pCustData->next;
4123 TLB_Free(pCustData);
4126 for (i = 0; i < This->ctTypeDesc; i++)
4127 if (This->pTypeDesc[i].vt == VT_CARRAY)
4128 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4130 TLB_Free(This->pTypeDesc);
4132 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4134 if (pImpLib->pImpTypeLib)
4135 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4136 SysFreeString(pImpLib->name);
4138 pImpLibNext = pImpLib->next;
4139 TLB_Free(pImpLib);
4142 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4144 list_remove(&ref_type->entry);
4145 TLB_Free(ref_type);
4148 if (This->pTypeInfo) /* can be NULL */
4149 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4150 HeapFree(GetProcessHeap(),0,This);
4151 return 0;
4154 return ref;
4157 /* ITypeLib::GetTypeInfoCount
4159 * Returns the number of type descriptions in the type library
4161 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4163 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4164 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4165 return This->TypeInfoCount;
4168 /* ITypeLib::GetTypeInfo
4170 * retrieves the specified type description in the library.
4172 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4173 ITypeLib2 *iface,
4174 UINT index,
4175 ITypeInfo **ppTInfo)
4177 UINT i;
4179 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4180 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4182 TRACE("(%p)->(index=%d)\n", This, index);
4184 if (!ppTInfo) return E_INVALIDARG;
4186 /* search element n in list */
4187 for(i=0; i < index; i++)
4189 pTypeInfo = pTypeInfo->next;
4190 if (!pTypeInfo)
4192 TRACE("-- element not found\n");
4193 return TYPE_E_ELEMENTNOTFOUND;
4197 *ppTInfo = (ITypeInfo *) pTypeInfo;
4199 ITypeInfo_AddRef(*ppTInfo);
4200 TRACE("-- found (%p)\n",*ppTInfo);
4201 return S_OK;
4205 /* ITypeLibs::GetTypeInfoType
4207 * Retrieves the type of a type description.
4209 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4210 ITypeLib2 *iface,
4211 UINT index,
4212 TYPEKIND *pTKind)
4214 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4215 UINT i;
4216 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4218 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4219 return TYPE_E_ELEMENTNOTFOUND;
4221 TRACE("(%p) index %d\n", This, index);
4223 if(!pTKind) return E_INVALIDARG;
4225 /* search element n in list */
4226 for(i=0; i < index; i++)
4228 if(!pTInfo)
4230 TRACE("-- element not found\n");
4231 return TYPE_E_ELEMENTNOTFOUND;
4233 pTInfo = pTInfo->next;
4236 *pTKind = pTInfo->TypeAttr.typekind;
4237 TRACE("-- found Type (%d)\n", *pTKind);
4238 return S_OK;
4241 /* ITypeLib::GetTypeInfoOfGuid
4243 * Retrieves the type description that corresponds to the specified GUID.
4246 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4247 ITypeLib2 *iface,
4248 REFGUID guid,
4249 ITypeInfo **ppTInfo)
4251 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4252 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4254 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4256 if (!pTypeInfo)
4258 WARN("-- element not found\n");
4259 return TYPE_E_ELEMENTNOTFOUND;
4262 /* search linked list for guid */
4263 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4265 pTypeInfo = pTypeInfo->next;
4267 if (!pTypeInfo)
4269 /* end of list reached */
4270 WARN("-- element not found\n");
4271 return TYPE_E_ELEMENTNOTFOUND;
4275 TRACE("-- found (%p, %s)\n",
4276 pTypeInfo,
4277 debugstr_w(pTypeInfo->Name));
4279 *ppTInfo = (ITypeInfo*)pTypeInfo;
4280 ITypeInfo_AddRef(*ppTInfo);
4281 return S_OK;
4284 /* ITypeLib::GetLibAttr
4286 * Retrieves the structure that contains the library's attributes.
4289 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4290 ITypeLib2 *iface,
4291 LPTLIBATTR *ppTLibAttr)
4293 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4294 TRACE("(%p)\n",This);
4295 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4296 **ppTLibAttr = This->LibAttr;
4297 return S_OK;
4300 /* ITypeLib::GetTypeComp
4302 * Enables a client compiler to bind to a library's types, variables,
4303 * constants, and global functions.
4306 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4307 ITypeLib2 *iface,
4308 ITypeComp **ppTComp)
4310 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4312 TRACE("(%p)->(%p)\n",This,ppTComp);
4313 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4314 ITypeComp_AddRef(*ppTComp);
4316 return S_OK;
4319 /* ITypeLib::GetDocumentation
4321 * Retrieves the library's documentation string, the complete Help file name
4322 * and path, and the context identifier for the library Help topic in the Help
4323 * file.
4325 * On a successful return all non-null BSTR pointers will have been set,
4326 * possibly to NULL.
4328 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4329 ITypeLib2 *iface,
4330 INT index,
4331 BSTR *pBstrName,
4332 BSTR *pBstrDocString,
4333 DWORD *pdwHelpContext,
4334 BSTR *pBstrHelpFile)
4336 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4338 HRESULT result = E_INVALIDARG;
4340 ITypeInfo *pTInfo;
4343 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4344 This, index,
4345 pBstrName, pBstrDocString,
4346 pdwHelpContext, pBstrHelpFile);
4348 if(index<0)
4350 /* documentation for the typelib */
4351 if(pBstrName)
4353 if (This->Name)
4355 if(!(*pBstrName = SysAllocString(This->Name)))
4356 goto memerr1;
4358 else
4359 *pBstrName = NULL;
4361 if(pBstrDocString)
4363 if (This->DocString)
4365 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4366 goto memerr2;
4368 else if (This->Name)
4370 if(!(*pBstrDocString = SysAllocString(This->Name)))
4371 goto memerr2;
4373 else
4374 *pBstrDocString = NULL;
4376 if(pdwHelpContext)
4378 *pdwHelpContext = This->dwHelpContext;
4380 if(pBstrHelpFile)
4382 if (This->HelpFile)
4384 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4385 goto memerr3;
4387 else
4388 *pBstrHelpFile = NULL;
4391 result = S_OK;
4393 else
4395 /* for a typeinfo */
4396 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4398 if(SUCCEEDED(result))
4400 result = ITypeInfo_GetDocumentation(pTInfo,
4401 MEMBERID_NIL,
4402 pBstrName,
4403 pBstrDocString,
4404 pdwHelpContext, pBstrHelpFile);
4406 ITypeInfo_Release(pTInfo);
4409 return result;
4410 memerr3:
4411 if (pBstrDocString) SysFreeString (*pBstrDocString);
4412 memerr2:
4413 if (pBstrName) SysFreeString (*pBstrName);
4414 memerr1:
4415 return STG_E_INSUFFICIENTMEMORY;
4418 /* ITypeLib::IsName
4420 * Indicates whether a passed-in string contains the name of a type or member
4421 * described in the library.
4424 static HRESULT WINAPI ITypeLib2_fnIsName(
4425 ITypeLib2 *iface,
4426 LPOLESTR szNameBuf,
4427 ULONG lHashVal,
4428 BOOL *pfName)
4430 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4431 ITypeInfoImpl *pTInfo;
4432 TLBFuncDesc *pFInfo;
4433 TLBVarDesc *pVInfo;
4434 int i;
4435 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4437 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4438 pfName);
4440 *pfName=TRUE;
4441 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4442 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4443 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4444 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4445 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4446 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4447 goto ITypeLib2_fnIsName_exit;
4449 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4450 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4453 *pfName=FALSE;
4455 ITypeLib2_fnIsName_exit:
4456 TRACE("(%p)slow! search for %s: %s found!\n", This,
4457 debugstr_w(szNameBuf), *pfName?"NOT":"");
4459 return S_OK;
4462 /* ITypeLib::FindName
4464 * Finds occurrences of a type description in a type library. This may be used
4465 * to quickly verify that a name exists in a type library.
4468 static HRESULT WINAPI ITypeLib2_fnFindName(
4469 ITypeLib2 *iface,
4470 LPOLESTR szNameBuf,
4471 ULONG lHashVal,
4472 ITypeInfo **ppTInfo,
4473 MEMBERID *rgMemId,
4474 UINT16 *pcFound)
4476 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4477 ITypeInfoImpl *pTInfo;
4478 TLBFuncDesc *pFInfo;
4479 TLBVarDesc *pVInfo;
4480 int i,j = 0;
4481 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4483 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4484 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4485 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4486 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4487 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4488 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4489 goto ITypeLib2_fnFindName_exit;
4492 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4493 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4494 continue;
4495 ITypeLib2_fnFindName_exit:
4496 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4497 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4498 j++;
4500 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4501 This, *pcFound, debugstr_w(szNameBuf), j);
4503 *pcFound=j;
4505 return S_OK;
4508 /* ITypeLib::ReleaseTLibAttr
4510 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4513 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4514 ITypeLib2 *iface,
4515 TLIBATTR *pTLibAttr)
4517 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4518 TRACE("freeing (%p)\n",This);
4519 HeapFree(GetProcessHeap(),0,pTLibAttr);
4523 /* ITypeLib2::GetCustData
4525 * gets the custom data
4527 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4528 ITypeLib2 * iface,
4529 REFGUID guid,
4530 VARIANT *pVarVal)
4532 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4533 TLBCustData *pCData;
4535 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4537 if( IsEqualIID(guid, &pCData->guid)) break;
4540 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4542 if(pCData)
4544 VariantInit( pVarVal);
4545 VariantCopy( pVarVal, &pCData->data);
4546 return S_OK;
4548 return E_INVALIDARG; /* FIXME: correct? */
4551 /* ITypeLib2::GetLibStatistics
4553 * Returns statistics about a type library that are required for efficient
4554 * sizing of hash tables.
4557 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4558 ITypeLib2 * iface,
4559 ULONG *pcUniqueNames,
4560 ULONG *pcchUniqueNames)
4562 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4564 FIXME("(%p): stub!\n", This);
4566 if(pcUniqueNames) *pcUniqueNames=1;
4567 if(pcchUniqueNames) *pcchUniqueNames=1;
4568 return S_OK;
4571 /* ITypeLib2::GetDocumentation2
4573 * Retrieves the library's documentation string, the complete Help file name
4574 * and path, the localization context to use, and the context ID for the
4575 * library Help topic in the Help file.
4578 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4579 ITypeLib2 * iface,
4580 INT index,
4581 LCID lcid,
4582 BSTR *pbstrHelpString,
4583 DWORD *pdwHelpStringContext,
4584 BSTR *pbstrHelpStringDll)
4586 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4587 HRESULT result;
4588 ITypeInfo *pTInfo;
4590 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4592 /* the help string should be obtained from the helpstringdll,
4593 * using the _DLLGetDocumentation function, based on the supplied
4594 * lcid. Nice to do sometime...
4596 if(index<0)
4598 /* documentation for the typelib */
4599 if(pbstrHelpString)
4600 *pbstrHelpString=SysAllocString(This->DocString);
4601 if(pdwHelpStringContext)
4602 *pdwHelpStringContext=This->dwHelpContext;
4603 if(pbstrHelpStringDll)
4604 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4606 result = S_OK;
4608 else
4610 /* for a typeinfo */
4611 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4613 if(SUCCEEDED(result))
4615 ITypeInfo2 * pTInfo2;
4616 result = ITypeInfo_QueryInterface(pTInfo,
4617 &IID_ITypeInfo2,
4618 (LPVOID*) &pTInfo2);
4620 if(SUCCEEDED(result))
4622 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4623 MEMBERID_NIL,
4624 lcid,
4625 pbstrHelpString,
4626 pdwHelpStringContext,
4627 pbstrHelpStringDll);
4629 ITypeInfo2_Release(pTInfo2);
4632 ITypeInfo_Release(pTInfo);
4635 return result;
4638 /* ITypeLib2::GetAllCustData
4640 * Gets all custom data items for the library.
4643 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4644 ITypeLib2 * iface,
4645 CUSTDATA *pCustData)
4647 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4648 TLBCustData *pCData;
4649 int i;
4650 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4651 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4652 if(pCustData->prgCustData ){
4653 pCustData->cCustData=This->ctCustData;
4654 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4655 pCustData->prgCustData[i].guid=pCData->guid;
4656 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4658 }else{
4659 ERR(" OUT OF MEMORY!\n");
4660 return E_OUTOFMEMORY;
4662 return S_OK;
4665 static const ITypeLib2Vtbl tlbvt = {
4666 ITypeLib2_fnQueryInterface,
4667 ITypeLib2_fnAddRef,
4668 ITypeLib2_fnRelease,
4669 ITypeLib2_fnGetTypeInfoCount,
4670 ITypeLib2_fnGetTypeInfo,
4671 ITypeLib2_fnGetTypeInfoType,
4672 ITypeLib2_fnGetTypeInfoOfGuid,
4673 ITypeLib2_fnGetLibAttr,
4674 ITypeLib2_fnGetTypeComp,
4675 ITypeLib2_fnGetDocumentation,
4676 ITypeLib2_fnIsName,
4677 ITypeLib2_fnFindName,
4678 ITypeLib2_fnReleaseTLibAttr,
4680 ITypeLib2_fnGetCustData,
4681 ITypeLib2_fnGetLibStatistics,
4682 ITypeLib2_fnGetDocumentation2,
4683 ITypeLib2_fnGetAllCustData
4687 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4689 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4691 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4694 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4696 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4698 return ITypeLib2_AddRef((ITypeLib2 *)This);
4701 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4703 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4705 return ITypeLib2_Release((ITypeLib2 *)This);
4708 static HRESULT WINAPI ITypeLibComp_fnBind(
4709 ITypeComp * iface,
4710 OLECHAR * szName,
4711 ULONG lHash,
4712 WORD wFlags,
4713 ITypeInfo ** ppTInfo,
4714 DESCKIND * pDescKind,
4715 BINDPTR * pBindPtr)
4717 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4718 ITypeInfoImpl *pTypeInfo;
4720 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4722 *pDescKind = DESCKIND_NONE;
4723 pBindPtr->lptcomp = NULL;
4724 *ppTInfo = NULL;
4726 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4728 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4730 /* FIXME: check wFlags here? */
4731 /* FIXME: we should use a hash table to look this info up using lHash
4732 * instead of an O(n) search */
4733 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4734 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4736 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4738 *pDescKind = DESCKIND_TYPECOMP;
4739 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4740 ITypeComp_AddRef(pBindPtr->lptcomp);
4741 TRACE("module or enum: %s\n", debugstr_w(szName));
4742 return S_OK;
4746 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4747 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4749 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4750 HRESULT hr;
4752 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4753 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4755 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4756 return S_OK;
4760 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4761 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4763 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4764 HRESULT hr;
4765 ITypeInfo *subtypeinfo;
4766 BINDPTR subbindptr;
4767 DESCKIND subdesckind;
4769 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4770 &subtypeinfo, &subdesckind, &subbindptr);
4771 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4773 TYPEDESC tdesc_appobject =
4776 (TYPEDESC *)pTypeInfo->hreftype
4778 VT_USERDEFINED
4780 const VARDESC vardesc_appobject =
4782 -2, /* memid */
4783 NULL, /* lpstrSchema */
4785 0 /* oInst */
4788 /* ELEMDESC */
4790 /* TYPEDESC */
4792 &tdesc_appobject
4794 VT_PTR
4797 0, /* wVarFlags */
4798 VAR_STATIC /* varkind */
4801 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4803 /* cleanup things filled in by Bind call so we can put our
4804 * application object data in there instead */
4805 switch (subdesckind)
4807 case DESCKIND_FUNCDESC:
4808 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4809 break;
4810 case DESCKIND_VARDESC:
4811 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4812 break;
4813 default:
4814 break;
4816 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4818 if (pTypeInfo->hreftype == -1)
4819 FIXME("no hreftype for interface %p\n", pTypeInfo);
4821 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4822 if (FAILED(hr))
4823 return hr;
4825 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4826 *ppTInfo = (ITypeInfo *)pTypeInfo;
4827 ITypeInfo_AddRef(*ppTInfo);
4828 return S_OK;
4833 TRACE("name not found %s\n", debugstr_w(szName));
4834 return S_OK;
4837 static HRESULT WINAPI ITypeLibComp_fnBindType(
4838 ITypeComp * iface,
4839 OLECHAR * szName,
4840 ULONG lHash,
4841 ITypeInfo ** ppTInfo,
4842 ITypeComp ** ppTComp)
4844 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4845 ITypeInfoImpl *pTypeInfo;
4847 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4849 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4851 /* FIXME: should use lHash to do the search */
4852 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4854 TRACE("returning %p\n", pTypeInfo);
4855 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4856 ITypeInfo_AddRef(*ppTInfo);
4857 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4858 ITypeComp_AddRef(*ppTComp);
4859 return S_OK;
4863 TRACE("not found\n");
4864 *ppTInfo = NULL;
4865 *ppTComp = NULL;
4866 return S_OK;
4869 static const ITypeCompVtbl tlbtcvt =
4872 ITypeLibComp_fnQueryInterface,
4873 ITypeLibComp_fnAddRef,
4874 ITypeLibComp_fnRelease,
4876 ITypeLibComp_fnBind,
4877 ITypeLibComp_fnBindType
4880 /*================== ITypeInfo(2) Methods ===================================*/
4881 static ITypeInfo2 * ITypeInfo_Constructor(void)
4883 ITypeInfoImpl * pTypeInfoImpl;
4885 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4886 if (pTypeInfoImpl)
4888 pTypeInfoImpl->lpVtbl = &tinfvt;
4889 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4890 pTypeInfoImpl->ref=1;
4891 pTypeInfoImpl->hreftype = -1;
4892 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4893 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4895 TRACE("(%p)\n", pTypeInfoImpl);
4896 return (ITypeInfo2*) pTypeInfoImpl;
4899 /* ITypeInfo::QueryInterface
4901 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4902 ITypeInfo2 *iface,
4903 REFIID riid,
4904 VOID **ppvObject)
4906 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4908 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4910 *ppvObject=NULL;
4911 if(IsEqualIID(riid, &IID_IUnknown) ||
4912 IsEqualIID(riid,&IID_ITypeInfo)||
4913 IsEqualIID(riid,&IID_ITypeInfo2))
4914 *ppvObject = This;
4916 if(*ppvObject){
4917 ITypeInfo_AddRef(iface);
4918 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4919 return S_OK;
4921 TRACE("-- Interface: E_NOINTERFACE\n");
4922 return E_NOINTERFACE;
4925 /* ITypeInfo::AddRef
4927 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4929 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4930 ULONG ref = InterlockedIncrement(&This->ref);
4932 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4934 TRACE("(%p)->ref is %u\n",This, ref);
4935 return ref;
4938 /* ITypeInfo::Release
4940 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4942 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4943 ULONG ref = InterlockedDecrement(&This->ref);
4945 TRACE("(%p)->(%u)\n",This, ref);
4947 if (ref) {
4948 /* We don't release ITypeLib when ref=0 because
4949 it means that function is called by ITypeLib2_Release */
4950 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4951 } else {
4952 TLBFuncDesc *pFInfo, *pFInfoNext;
4953 TLBVarDesc *pVInfo, *pVInfoNext;
4954 TLBImplType *pImpl, *pImplNext;
4956 TRACE("destroying ITypeInfo(%p)\n",This);
4958 if (This->no_free_data)
4959 goto finish_free;
4961 SysFreeString(This->Name);
4962 This->Name = NULL;
4964 SysFreeString(This->DocString);
4965 This->DocString = NULL;
4967 SysFreeString(This->DllName);
4968 This->DllName = NULL;
4970 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4972 INT i;
4973 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4975 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4976 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4978 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4979 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4981 SysFreeString(pFInfo->pParamDesc[i].Name);
4983 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4984 TLB_Free(pFInfo->pParamDesc);
4985 TLB_FreeCustData(pFInfo->pCustData);
4986 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4987 SysFreeString(pFInfo->Entry);
4988 SysFreeString(pFInfo->HelpString);
4989 SysFreeString(pFInfo->Name);
4991 pFInfoNext = pFInfo->next;
4992 TLB_Free(pFInfo);
4994 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4996 if (pVInfo->vardesc.varkind == VAR_CONST)
4998 VariantClear(pVInfo->vardesc.u.lpvarValue);
4999 TLB_Free(pVInfo->vardesc.u.lpvarValue);
5001 TLB_FreeCustData(pVInfo->pCustData);
5002 SysFreeString(pVInfo->Name);
5003 pVInfoNext = pVInfo->next;
5004 TLB_Free(pVInfo);
5006 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5008 TLB_FreeCustData(pImpl->pCustData);
5009 pImplNext = pImpl->next;
5010 TLB_Free(pImpl);
5012 TLB_FreeCustData(This->pCustData);
5014 finish_free:
5015 if (This->next)
5017 ITypeInfo_Release((ITypeInfo*)This->next);
5020 HeapFree(GetProcessHeap(),0,This);
5021 return 0;
5023 return ref;
5026 /* ITypeInfo::GetTypeAttr
5028 * Retrieves a TYPEATTR structure that contains the attributes of the type
5029 * description.
5032 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5033 LPTYPEATTR *ppTypeAttr)
5035 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5036 SIZE_T size;
5038 TRACE("(%p)\n",This);
5040 size = sizeof(**ppTypeAttr);
5041 if (This->TypeAttr.typekind == TKIND_ALIAS)
5042 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5044 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5045 if (!*ppTypeAttr)
5046 return E_OUTOFMEMORY;
5048 **ppTypeAttr = This->TypeAttr;
5050 if (This->TypeAttr.typekind == TKIND_ALIAS)
5051 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5052 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5054 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5055 /* This should include all the inherited funcs */
5056 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5057 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5058 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5060 return S_OK;
5063 /* ITypeInfo::GetTypeComp
5065 * Retrieves the ITypeComp interface for the type description, which enables a
5066 * client compiler to bind to the type description's members.
5069 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5070 ITypeComp * *ppTComp)
5072 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5074 TRACE("(%p)->(%p)\n", This, ppTComp);
5076 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5077 ITypeComp_AddRef(*ppTComp);
5078 return S_OK;
5081 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5083 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5084 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5085 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5086 return size;
5089 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5091 *dest = *src;
5092 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5093 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5095 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5096 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5097 *buffer += sizeof(PARAMDESCEX);
5098 *pparamdescex_dest = *pparamdescex_src;
5099 VariantInit(&pparamdescex_dest->varDefaultValue);
5100 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5101 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5103 else
5104 dest->u.paramdesc.pparamdescex = NULL;
5105 return S_OK;
5108 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5110 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5111 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5114 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5116 FUNCDESC *dest;
5117 char *buffer;
5118 SIZE_T size = sizeof(*src);
5119 SHORT i;
5120 HRESULT hr;
5122 size += sizeof(*src->lprgscode) * src->cScodes;
5123 size += TLB_SizeElemDesc(&src->elemdescFunc);
5124 for (i = 0; i < src->cParams; i++)
5126 size += sizeof(ELEMDESC);
5127 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5130 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5131 if (!dest) return E_OUTOFMEMORY;
5133 *dest = *src;
5134 if (dispinterface) /* overwrite funckind */
5135 dest->funckind = FUNC_DISPATCH;
5136 buffer = (char *)(dest + 1);
5138 dest->lprgscode = (SCODE *)buffer;
5139 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5140 buffer += sizeof(*src->lprgscode) * src->cScodes;
5142 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5143 if (FAILED(hr))
5145 SysFreeString((BSTR)dest);
5146 return hr;
5149 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5150 buffer += sizeof(ELEMDESC) * src->cParams;
5151 for (i = 0; i < src->cParams; i++)
5153 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5154 if (FAILED(hr))
5155 break;
5157 if (FAILED(hr))
5159 /* undo the above actions */
5160 for (i = i - 1; i >= 0; i--)
5161 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5162 TLB_FreeElemDesc(&dest->elemdescFunc);
5163 SysFreeString((BSTR)dest);
5164 return hr;
5167 /* special treatment for dispinterfaces: this makes functions appear
5168 * to return their [retval] value when it is really returning an
5169 * HRESULT */
5170 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5172 if (dest->cParams &&
5173 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5175 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5176 if (elemdesc->tdesc.vt != VT_PTR)
5178 ERR("elemdesc should have started with VT_PTR instead of:\n");
5179 if (ERR_ON(ole))
5180 dump_ELEMDESC(elemdesc);
5181 return E_UNEXPECTED;
5184 /* copy last parameter to the return value. we are using a flat
5185 * buffer so there is no danger of leaking memory in
5186 * elemdescFunc */
5187 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5189 /* remove the last parameter */
5190 dest->cParams--;
5192 else
5193 /* otherwise this function is made to appear to have no return
5194 * value */
5195 dest->elemdescFunc.tdesc.vt = VT_VOID;
5199 *dest_ptr = dest;
5200 return S_OK;
5203 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5205 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5206 const TLBFuncDesc *pFDesc;
5207 UINT i;
5209 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5212 if (pFDesc)
5214 *ppFuncDesc = &pFDesc->funcdesc;
5215 return S_OK;
5218 return TYPE_E_ELEMENTNOTFOUND;
5221 /* internal function to make the inherited interfaces' methods appear
5222 * part of the interface */
5223 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5224 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5226 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5227 HRESULT hr;
5228 UINT implemented_funcs = 0;
5230 if (funcs)
5231 *funcs = 0;
5232 else
5233 *hrefoffset = DISPATCH_HREF_OFFSET;
5235 if(This->impltypelist)
5237 ITypeInfo *pSubTypeInfo;
5238 UINT sub_funcs;
5240 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5241 if (FAILED(hr))
5242 return hr;
5244 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5245 index,
5246 ppFuncDesc,
5247 &sub_funcs, hrefoffset);
5248 implemented_funcs += sub_funcs;
5249 ITypeInfo_Release(pSubTypeInfo);
5250 if (SUCCEEDED(hr))
5251 return hr;
5252 *hrefoffset += DISPATCH_HREF_OFFSET;
5255 if (funcs)
5256 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5257 else
5258 *hrefoffset = 0;
5260 if (index < implemented_funcs)
5261 return E_INVALIDARG;
5262 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5263 ppFuncDesc);
5266 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5268 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5269 while (TRUE)
5271 switch (pTypeDesc->vt)
5273 case VT_USERDEFINED:
5274 pTypeDesc->u.hreftype += hrefoffset;
5275 return;
5276 case VT_PTR:
5277 case VT_SAFEARRAY:
5278 pTypeDesc = pTypeDesc->u.lptdesc;
5279 break;
5280 case VT_CARRAY:
5281 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5282 break;
5283 default:
5284 return;
5289 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5291 SHORT i;
5292 for (i = 0; i < pFuncDesc->cParams; i++)
5293 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5294 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5297 /* ITypeInfo::GetFuncDesc
5299 * Retrieves the FUNCDESC structure that contains information about a
5300 * specified function.
5303 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5304 LPFUNCDESC *ppFuncDesc)
5306 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5307 const FUNCDESC *internal_funcdesc;
5308 HRESULT hr;
5309 UINT hrefoffset = 0;
5311 TRACE("(%p) index %d\n", This, index);
5313 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5314 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5315 &internal_funcdesc, NULL,
5316 &hrefoffset);
5317 else
5318 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5319 &internal_funcdesc);
5320 if (FAILED(hr))
5322 WARN("description for function %d not found\n", index);
5323 return hr;
5326 hr = TLB_AllocAndInitFuncDesc(
5327 internal_funcdesc,
5328 ppFuncDesc,
5329 This->TypeAttr.typekind == TKIND_DISPATCH);
5331 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5332 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5334 TRACE("-- 0x%08x\n", hr);
5335 return hr;
5338 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5340 VARDESC *dest;
5341 char *buffer;
5342 SIZE_T size = sizeof(*src);
5343 HRESULT hr;
5345 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5346 if (src->varkind == VAR_CONST)
5347 size += sizeof(VARIANT);
5348 size += TLB_SizeElemDesc(&src->elemdescVar);
5350 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5351 if (!dest) return E_OUTOFMEMORY;
5353 *dest = *src;
5354 buffer = (char *)(dest + 1);
5355 if (src->lpstrSchema)
5357 int len;
5358 dest->lpstrSchema = (LPOLESTR)buffer;
5359 len = strlenW(src->lpstrSchema);
5360 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5361 buffer += (len + 1) * sizeof(WCHAR);
5364 if (src->varkind == VAR_CONST)
5366 HRESULT hr;
5368 dest->u.lpvarValue = (VARIANT *)buffer;
5369 *dest->u.lpvarValue = *src->u.lpvarValue;
5370 buffer += sizeof(VARIANT);
5371 VariantInit(dest->u.lpvarValue);
5372 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5373 if (FAILED(hr))
5375 SysFreeString((BSTR)dest_ptr);
5376 return hr;
5379 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5380 if (FAILED(hr))
5382 if (src->varkind == VAR_CONST)
5383 VariantClear(dest->u.lpvarValue);
5384 SysFreeString((BSTR)dest);
5385 return hr;
5387 *dest_ptr = dest;
5388 return S_OK;
5391 /* ITypeInfo::GetVarDesc
5393 * Retrieves a VARDESC structure that describes the specified variable.
5396 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5397 LPVARDESC *ppVarDesc)
5399 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5400 UINT i;
5401 const TLBVarDesc *pVDesc;
5403 TRACE("(%p) index %d\n", This, index);
5405 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5408 if (pVDesc)
5409 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5411 return E_INVALIDARG;
5414 /* ITypeInfo_GetNames
5416 * Retrieves the variable with the specified member ID (or the name of the
5417 * property or method and its parameters) that correspond to the specified
5418 * function ID.
5420 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5421 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5423 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5424 const TLBFuncDesc *pFDesc;
5425 const TLBVarDesc *pVDesc;
5426 int i;
5427 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5428 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5429 if(pFDesc)
5431 /* function found, now return function and parameter names */
5432 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5434 if(!i)
5435 *rgBstrNames=SysAllocString(pFDesc->Name);
5436 else
5437 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5439 *pcNames=i;
5441 else
5443 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5444 if(pVDesc)
5446 *rgBstrNames=SysAllocString(pVDesc->Name);
5447 *pcNames=1;
5449 else
5451 if(This->impltypelist &&
5452 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5453 /* recursive search */
5454 ITypeInfo *pTInfo;
5455 HRESULT result;
5456 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5457 &pTInfo);
5458 if(SUCCEEDED(result))
5460 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5461 ITypeInfo_Release(pTInfo);
5462 return result;
5464 WARN("Could not search inherited interface!\n");
5466 else
5468 WARN("no names found\n");
5470 *pcNames=0;
5471 return TYPE_E_ELEMENTNOTFOUND;
5474 return S_OK;
5478 /* ITypeInfo::GetRefTypeOfImplType
5480 * If a type description describes a COM class, it retrieves the type
5481 * description of the implemented interface types. For an interface,
5482 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5483 * if any exist.
5486 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5487 ITypeInfo2 *iface,
5488 UINT index,
5489 HREFTYPE *pRefType)
5491 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5492 UINT i;
5493 HRESULT hr = S_OK;
5494 const TLBImplType *pImpl = This->impltypelist;
5496 TRACE("(%p) index %d\n", This, index);
5497 if (TRACE_ON(ole)) dump_TypeInfo(This);
5499 if(index==(UINT)-1)
5501 /* only valid on dual interfaces;
5502 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5504 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5506 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5508 *pRefType = -1;
5510 else
5512 hr = TYPE_E_ELEMENTNOTFOUND;
5515 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5517 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5518 *pRefType = This->pTypeLib->dispatch_href;
5520 else
5522 /* get element n from linked list */
5523 for(i=0; pImpl && i<index; i++)
5525 pImpl = pImpl->next;
5528 if (pImpl)
5529 *pRefType = pImpl->hRef;
5530 else
5531 hr = TYPE_E_ELEMENTNOTFOUND;
5534 if(TRACE_ON(ole))
5536 if(SUCCEEDED(hr))
5537 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5538 else
5539 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5542 return hr;
5545 /* ITypeInfo::GetImplTypeFlags
5547 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5548 * or base interface in a type description.
5550 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5551 UINT index, INT *pImplTypeFlags)
5553 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5554 UINT i;
5555 TLBImplType *pImpl;
5557 TRACE("(%p) index %d\n", This, index);
5558 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5559 i++, pImpl=pImpl->next)
5561 if(i==index && pImpl){
5562 *pImplTypeFlags=pImpl->implflags;
5563 return S_OK;
5565 *pImplTypeFlags=0;
5566 return TYPE_E_ELEMENTNOTFOUND;
5569 /* GetIDsOfNames
5570 * Maps between member names and member IDs, and parameter names and
5571 * parameter IDs.
5573 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5574 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5576 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5577 const TLBFuncDesc *pFDesc;
5578 const TLBVarDesc *pVDesc;
5579 HRESULT ret=S_OK;
5580 UINT i;
5582 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5583 cNames);
5585 /* init out parameters in case of failure */
5586 for (i = 0; i < cNames; i++)
5587 pMemId[i] = MEMBERID_NIL;
5589 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5590 int j;
5591 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5592 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5593 for(i=1; i < cNames; i++){
5594 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5595 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5596 break;
5597 if( j<pFDesc->funcdesc.cParams)
5598 pMemId[i]=j;
5599 else
5600 ret=DISP_E_UNKNOWNNAME;
5602 TRACE("-- 0x%08x\n", ret);
5603 return ret;
5606 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5607 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5608 if(cNames) *pMemId=pVDesc->vardesc.memid;
5609 return ret;
5612 /* not found, see if it can be found in an inherited interface */
5613 if(This->impltypelist) {
5614 /* recursive search */
5615 ITypeInfo *pTInfo;
5616 ret=ITypeInfo_GetRefTypeInfo(iface,
5617 This->impltypelist->hRef, &pTInfo);
5618 if(SUCCEEDED(ret)){
5619 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5620 ITypeInfo_Release(pTInfo);
5621 return ret;
5623 WARN("Could not search inherited interface!\n");
5624 } else
5625 WARN("no names found\n");
5626 return DISP_E_UNKNOWNNAME;
5630 #ifdef __i386__
5632 extern DWORD CDECL call_method( void *func, int nb_args, const DWORD *args );
5633 __ASM_GLOBAL_FUNC( call_method,
5634 "pushl %ebp\n\t"
5635 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5636 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5637 "movl %esp,%ebp\n\t"
5638 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5639 "pushl %esi\n\t"
5640 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5641 "pushl %edi\n\t"
5642 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5643 "movl 12(%ebp),%edx\n\t"
5644 "shll $2,%edx\n\t"
5645 "jz 1f\n\t"
5646 "subl %edx,%esp\n\t"
5647 "andl $~15,%esp\n\t"
5648 "movl 12(%ebp),%ecx\n\t"
5649 "movl 16(%ebp),%esi\n\t"
5650 "movl %esp,%edi\n\t"
5651 "cld\n\t"
5652 "rep; movsl\n"
5653 "1:\tcall *8(%ebp)\n\t"
5654 "leal -8(%ebp),%esp\n\t"
5655 "popl %edi\n\t"
5656 __ASM_CFI(".cfi_same_value %edi\n\t")
5657 "popl %esi\n\t"
5658 __ASM_CFI(".cfi_same_value %esi\n\t")
5659 "popl %ebp\n\t"
5660 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5661 __ASM_CFI(".cfi_same_value %ebp\n\t")
5662 "ret" )
5664 /* ITypeInfo::Invoke
5666 * Invokes a method, or accesses a property of an object, that implements the
5667 * interface described by the type description.
5669 DWORD
5670 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5671 DWORD res;
5673 if (TRACE_ON(ole)) {
5674 int i;
5675 TRACE("Calling %p(",func);
5676 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5677 TRACE(")\n");
5680 switch (callconv) {
5681 case CC_STDCALL:
5682 case CC_CDECL:
5683 res = call_method( func, nrargs, args );
5684 break;
5685 default:
5686 FIXME("unsupported calling convention %d\n",callconv);
5687 res = -1;
5688 break;
5690 TRACE("returns %08x\n",res);
5691 return res;
5694 /* The size of the argument on the stack in DWORD units (in all x86 call
5695 * convetions the arguments on the stack are DWORD-aligned)
5697 static int _dispargsize(VARTYPE vt)
5699 switch (vt) {
5700 case VT_I8:
5701 case VT_UI8:
5702 return 8/sizeof(DWORD);
5703 case VT_R8:
5704 return sizeof(double)/sizeof(DWORD);
5705 case VT_DECIMAL:
5706 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5707 case VT_CY:
5708 return sizeof(CY)/sizeof(DWORD);
5709 case VT_DATE:
5710 return sizeof(DATE)/sizeof(DWORD);
5711 case VT_VARIANT:
5712 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5713 case VT_RECORD:
5714 FIXME("VT_RECORD not implemented\n");
5715 return 1;
5716 default:
5717 return 1;
5720 #endif /* __i386__ */
5722 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5724 HRESULT hr = S_OK;
5725 ITypeInfo *tinfo2 = NULL;
5726 TYPEATTR *tattr = NULL;
5728 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5729 if (hr)
5731 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5732 "hr = 0x%08x\n",
5733 tdesc->u.hreftype, hr);
5734 return hr;
5736 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5737 if (hr)
5739 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5740 ITypeInfo_Release(tinfo2);
5741 return hr;
5744 switch (tattr->typekind)
5746 case TKIND_ENUM:
5747 *vt |= VT_I4;
5748 break;
5750 case TKIND_ALIAS:
5751 tdesc = &tattr->tdescAlias;
5752 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5753 break;
5755 case TKIND_INTERFACE:
5756 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5757 *vt |= VT_DISPATCH;
5758 else
5759 *vt |= VT_UNKNOWN;
5760 break;
5762 case TKIND_DISPATCH:
5763 *vt |= VT_DISPATCH;
5764 break;
5766 case TKIND_COCLASS:
5767 *vt |= VT_DISPATCH;
5768 break;
5770 case TKIND_RECORD:
5771 FIXME("TKIND_RECORD unhandled.\n");
5772 hr = E_NOTIMPL;
5773 break;
5775 case TKIND_UNION:
5776 FIXME("TKIND_UNION unhandled.\n");
5777 hr = E_NOTIMPL;
5778 break;
5780 default:
5781 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5782 hr = E_NOTIMPL;
5783 break;
5785 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5786 ITypeInfo_Release(tinfo2);
5787 return hr;
5790 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5792 HRESULT hr = S_OK;
5794 /* enforce only one level of pointer indirection */
5795 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5797 tdesc = tdesc->u.lptdesc;
5799 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5800 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5801 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5802 if ((tdesc->vt == VT_USERDEFINED) ||
5803 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5805 VARTYPE vt_userdefined = 0;
5806 const TYPEDESC *tdesc_userdefined = tdesc;
5807 if (tdesc->vt == VT_PTR)
5809 vt_userdefined = VT_BYREF;
5810 tdesc_userdefined = tdesc->u.lptdesc;
5812 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5813 if ((hr == S_OK) &&
5814 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5815 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5817 *vt |= vt_userdefined;
5818 return S_OK;
5821 *vt = VT_BYREF;
5824 switch (tdesc->vt)
5826 case VT_HRESULT:
5827 *vt |= VT_ERROR;
5828 break;
5829 case VT_USERDEFINED:
5830 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5831 break;
5832 case VT_VOID:
5833 case VT_CARRAY:
5834 case VT_PTR:
5835 case VT_LPSTR:
5836 case VT_LPWSTR:
5837 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5838 hr = DISP_E_BADVARTYPE;
5839 break;
5840 case VT_SAFEARRAY:
5841 *vt |= VT_ARRAY;
5842 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5843 break;
5844 case VT_INT:
5845 *vt |= VT_I4;
5846 break;
5847 case VT_UINT:
5848 *vt |= VT_UI4;
5849 break;
5850 default:
5851 *vt |= tdesc->vt;
5852 break;
5854 return hr;
5857 /***********************************************************************
5858 * DispCallFunc (OLEAUT32.@)
5860 * Invokes a function of the specified calling convention, passing the
5861 * specified arguments and returns the result.
5863 * PARAMS
5864 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5865 * oVft [I] The offset in the vtable. See notes.
5866 * cc [I] Calling convention of the function to call.
5867 * vtReturn [I] The return type of the function.
5868 * cActuals [I] Number of parameters.
5869 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5870 * prgpvarg [I] The arguments to pass.
5871 * pvargResult [O] The return value of the function. Can be NULL.
5873 * RETURNS
5874 * Success: S_OK.
5875 * Failure: HRESULT code.
5877 * NOTES
5878 * The HRESULT return value of this function is not affected by the return
5879 * value of the user supplied function, which is returned in pvargResult.
5881 * If pvInstance is NULL then a non-object function is to be called and oVft
5882 * is the address of the function to call.
5884 * The cc parameter can be one of the following values:
5885 *|CC_FASTCALL
5886 *|CC_CDECL
5887 *|CC_PASCAL
5888 *|CC_STDCALL
5889 *|CC_FPFASTCALL
5890 *|CC_SYSCALL
5891 *|CC_MPWCDECL
5892 *|CC_MPWPASCAL
5895 HRESULT WINAPI
5896 DispCallFunc(
5897 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5898 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5900 #ifdef __i386__
5901 int argsize, argspos;
5902 UINT i;
5903 DWORD *args;
5904 HRESULT hres;
5906 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5907 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5908 pvargResult, V_VT(pvargResult));
5910 argsize = 0;
5911 if (pvInstance)
5912 argsize++; /* for This pointer */
5914 for (i=0;i<cActuals;i++)
5916 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5917 dump_Variant(prgpvarg[i]);
5918 argsize += _dispargsize(prgvt[i]);
5920 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5922 argspos = 0;
5923 if (pvInstance)
5925 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5926 argspos++;
5929 for (i=0;i<cActuals;i++)
5931 VARIANT *arg = prgpvarg[i];
5932 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5933 if (prgvt[i] == VT_VARIANT)
5934 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5935 else
5936 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5937 argspos += _dispargsize(prgvt[i]);
5940 if (pvInstance)
5942 FARPROC *vtable = *(FARPROC**)pvInstance;
5943 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5945 else
5946 /* if we aren't invoking an object then the function pointer is stored
5947 * in oVft */
5948 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5950 if (pvargResult && (vtReturn != VT_EMPTY))
5952 TRACE("Method returned 0x%08x\n",hres);
5953 V_VT(pvargResult) = vtReturn;
5954 V_UI4(pvargResult) = hres;
5956 HeapFree(GetProcessHeap(),0,args);
5957 return S_OK;
5958 #else
5959 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
5960 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
5961 return E_NOTIMPL;
5962 #endif
5965 #define INVBUF_ELEMENT_SIZE \
5966 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5967 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5968 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5969 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5970 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5971 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5972 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5973 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5975 static HRESULT WINAPI ITypeInfo_fnInvoke(
5976 ITypeInfo2 *iface,
5977 VOID *pIUnk,
5978 MEMBERID memid,
5979 UINT16 wFlags,
5980 DISPPARAMS *pDispParams,
5981 VARIANT *pVarResult,
5982 EXCEPINFO *pExcepInfo,
5983 UINT *pArgErr)
5985 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5986 int i;
5987 unsigned int var_index;
5988 TYPEKIND type_kind;
5989 HRESULT hres;
5990 const TLBFuncDesc *pFuncInfo;
5992 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5993 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5996 if (!pDispParams)
5998 ERR("NULL pDispParams not allowed\n");
5999 return E_INVALIDARG;
6002 dump_DispParms(pDispParams);
6004 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6006 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6007 pDispParams->cNamedArgs, pDispParams->cArgs);
6008 return E_INVALIDARG;
6011 /* we do this instead of using GetFuncDesc since it will return a fake
6012 * FUNCDESC for dispinterfaces and we want the real function description */
6013 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6014 if ((memid == pFuncInfo->funcdesc.memid) &&
6015 (wFlags & pFuncInfo->funcdesc.invkind))
6016 break;
6018 if (pFuncInfo) {
6019 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6021 if (TRACE_ON(ole))
6023 TRACE("invoking:\n");
6024 dump_TLBFuncDescOne(pFuncInfo);
6027 switch (func_desc->funckind) {
6028 case FUNC_PUREVIRTUAL:
6029 case FUNC_VIRTUAL: {
6030 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6031 VARIANT varresult;
6032 VARIANT retval; /* pointer for storing byref retvals in */
6033 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6034 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6035 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6036 UINT cNamedArgs = pDispParams->cNamedArgs;
6037 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6038 UINT vargs_converted=0;
6040 hres = S_OK;
6042 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6044 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6046 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6047 hres = DISP_E_PARAMNOTFOUND;
6048 goto func_fail;
6050 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6051 cNamedArgs--;
6052 rgdispidNamedArgs++;
6055 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6057 ERR("functions with the vararg attribute do not support named arguments\n");
6058 hres = DISP_E_NONAMEDARGS;
6059 goto func_fail;
6062 for (i = 0; i < func_desc->cParams; i++)
6064 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6065 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6066 if (FAILED(hres))
6067 goto func_fail;
6070 TRACE("changing args\n");
6071 for (i = 0; i < func_desc->cParams; i++)
6073 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6074 VARIANTARG *src_arg;
6076 if (wParamFlags & PARAMFLAG_FLCID)
6078 VARIANTARG *arg;
6079 arg = prgpvarg[i] = &rgvarg[i];
6080 V_VT(arg) = VT_I4;
6081 V_I4(arg) = This->pTypeLib->lcid;
6082 continue;
6085 if (cNamedArgs)
6087 USHORT j;
6088 src_arg = NULL;
6089 for (j = 0; j < cNamedArgs; j++)
6090 if (rgdispidNamedArgs[j] == i)
6092 src_arg = &pDispParams->rgvarg[j];
6093 break;
6096 else
6098 src_arg = vargs_converted < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted] : NULL;
6099 vargs_converted++;
6102 if (wParamFlags & PARAMFLAG_FRETVAL)
6104 /* under most conditions the caller is not allowed to
6105 * pass in a dispparam arg in the index of what would be
6106 * the retval parameter. however, there is an exception
6107 * where the extra parameter is used in an extra
6108 * IDispatch::Invoke below */
6109 if ((i < pDispParams->cArgs) &&
6110 ((func_desc->cParams != 1) || !pVarResult ||
6111 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6113 hres = DISP_E_BADPARAMCOUNT;
6114 break;
6117 /* note: this check is placed so that if the caller passes
6118 * in a VARIANTARG for the retval we just ignore it, like
6119 * native does */
6120 if (i == func_desc->cParams - 1)
6122 VARIANTARG *arg;
6123 arg = prgpvarg[i] = &rgvarg[i];
6124 memset(arg, 0, sizeof(*arg));
6125 V_VT(arg) = rgvt[i];
6126 memset(&retval, 0, sizeof(retval));
6127 V_BYREF(arg) = &retval;
6129 else
6131 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6132 hres = E_UNEXPECTED;
6133 break;
6136 else if (src_arg)
6138 dump_Variant(src_arg);
6140 if (rgvt[i] == VT_VARIANT)
6141 hres = VariantCopy(&rgvarg[i], src_arg);
6142 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6144 if (rgvt[i] == V_VT(src_arg))
6145 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6146 else
6148 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6149 hres = VariantCopy(&missing_arg[i], src_arg);
6150 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6152 V_VT(&rgvarg[i]) = rgvt[i];
6154 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6156 SAFEARRAY *a;
6157 SAFEARRAYBOUND bound;
6158 VARIANT *v;
6159 LONG j;
6160 bound.lLbound = 0;
6161 bound.cElements = pDispParams->cArgs-i;
6162 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6164 ERR("SafeArrayCreate failed\n");
6165 break;
6167 hres = SafeArrayAccessData(a, (LPVOID)&v);
6168 if (hres != S_OK)
6170 ERR("SafeArrayAccessData failed with %x\n", hres);
6171 break;
6173 for (j = 0; j < bound.cElements; j++)
6174 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6175 hres = SafeArrayUnaccessData(a);
6176 if (hres != S_OK)
6178 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6179 break;
6181 V_ARRAY(&rgvarg[i]) = a;
6182 V_VT(&rgvarg[i]) = rgvt[i];
6184 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6186 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6187 V_VT(&missing_arg[i]) = V_VT(src_arg);
6188 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6189 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6190 V_VT(&rgvarg[i]) = rgvt[i];
6192 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6194 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6195 V_VT(&rgvarg[i]) = rgvt[i];
6197 else
6199 /* FIXME: this doesn't work for VT_BYREF arguments if
6200 * they are not the same type as in the paramdesc */
6201 V_VT(&rgvarg[i]) = V_VT(src_arg);
6202 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6203 V_VT(&rgvarg[i]) = rgvt[i];
6206 if (FAILED(hres))
6208 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6209 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6210 debugstr_VT(src_arg), debugstr_VF(src_arg));
6211 break;
6213 prgpvarg[i] = &rgvarg[i];
6215 else if (wParamFlags & PARAMFLAG_FOPT)
6217 VARIANTARG *arg;
6218 arg = prgpvarg[i] = &rgvarg[i];
6219 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6221 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6222 if (FAILED(hres))
6223 break;
6225 else
6227 VARIANTARG *missing_arg;
6228 /* if the function wants a pointer to a variant then
6229 * set that up, otherwise just pass the VT_ERROR in
6230 * the argument by value */
6231 if (rgvt[i] & VT_BYREF)
6233 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6234 V_VT(arg) = VT_VARIANT | VT_BYREF;
6235 V_VARIANTREF(arg) = missing_arg;
6237 else
6238 missing_arg = arg;
6239 V_VT(missing_arg) = VT_ERROR;
6240 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6243 else
6245 hres = DISP_E_BADPARAMCOUNT;
6246 break;
6249 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6251 /* VT_VOID is a special case for return types, so it is not
6252 * handled in the general function */
6253 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6254 V_VT(&varresult) = VT_EMPTY;
6255 else
6257 V_VT(&varresult) = 0;
6258 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6259 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6262 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6263 V_VT(&varresult), func_desc->cParams, rgvt,
6264 prgpvarg, &varresult);
6266 vargs_converted = 0;
6268 for (i = 0; i < func_desc->cParams; i++)
6270 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6272 if (wParamFlags & PARAMFLAG_FLCID)
6273 continue;
6274 else if (wParamFlags & PARAMFLAG_FRETVAL)
6276 if (TRACE_ON(ole))
6278 TRACE("[retval] value: ");
6279 dump_Variant(prgpvarg[i]);
6282 if (pVarResult)
6284 VariantInit(pVarResult);
6285 /* deref return value */
6286 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6289 /* free data stored in varresult. Note that
6290 * VariantClear doesn't do what we want because we are
6291 * working with byref types. */
6292 /* FIXME: clear safearrays, bstrs, records and
6293 * variants here too */
6294 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6295 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6297 if(*V_UNKNOWNREF(prgpvarg[i]))
6298 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6300 break;
6302 else if (vargs_converted < pDispParams->cArgs)
6304 if (wParamFlags & PARAMFLAG_FOUT)
6306 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6308 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6309 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6311 if (FAILED(hres))
6313 ERR("failed to convert param %d to vt %d\n", i,
6314 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6315 break;
6318 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6319 func_desc->cParamsOpt < 0 &&
6320 i == func_desc->cParams-1)
6322 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6323 LONG j, ubound;
6324 VARIANT *v;
6325 hres = SafeArrayGetUBound(a, 1, &ubound);
6326 if (hres != S_OK)
6328 ERR("SafeArrayGetUBound failed with %x\n", hres);
6329 break;
6331 hres = SafeArrayAccessData(a, (LPVOID)&v);
6332 if (hres != S_OK)
6334 ERR("SafeArrayAccessData failed with %x\n", hres);
6335 break;
6337 for (j = 0; j <= ubound; j++)
6338 VariantClear(&v[j]);
6339 hres = SafeArrayUnaccessData(a);
6340 if (hres != S_OK)
6342 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6343 break;
6346 VariantClear(&rgvarg[i]);
6347 vargs_converted++;
6349 else if (wParamFlags & PARAMFLAG_FOPT)
6351 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6352 VariantClear(&rgvarg[i]);
6356 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6358 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6359 hres = DISP_E_EXCEPTION;
6360 if (pExcepInfo)
6362 IErrorInfo *pErrorInfo;
6363 pExcepInfo->scode = V_ERROR(&varresult);
6364 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6366 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6367 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6368 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6369 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6371 IErrorInfo_Release(pErrorInfo);
6375 if (V_VT(&varresult) != VT_ERROR)
6377 TRACE("varresult value: ");
6378 dump_Variant(&varresult);
6380 if (pVarResult)
6382 VariantClear(pVarResult);
6383 *pVarResult = varresult;
6385 else
6386 VariantClear(&varresult);
6389 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6390 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6391 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6392 (pDispParams->cArgs != 0))
6394 if (V_VT(pVarResult) == VT_DISPATCH)
6396 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6397 /* Note: not VariantClear; we still need the dispatch
6398 * pointer to be valid */
6399 VariantInit(pVarResult);
6400 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6401 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6402 pDispParams, pVarResult, pExcepInfo, pArgErr);
6403 IDispatch_Release(pDispatch);
6405 else
6407 VariantClear(pVarResult);
6408 hres = DISP_E_NOTACOLLECTION;
6412 func_fail:
6413 HeapFree(GetProcessHeap(), 0, buffer);
6414 break;
6416 case FUNC_DISPATCH: {
6417 IDispatch *disp;
6419 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6420 if (SUCCEEDED(hres)) {
6421 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6422 hres = IDispatch_Invoke(
6423 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6424 pVarResult,pExcepInfo,pArgErr
6426 if (FAILED(hres))
6427 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6428 IDispatch_Release(disp);
6429 } else
6430 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6431 break;
6433 default:
6434 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6435 hres = E_FAIL;
6436 break;
6439 TRACE("-- 0x%08x\n", hres);
6440 return hres;
6442 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6443 VARDESC *var_desc;
6445 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6446 if(FAILED(hres)) return hres;
6448 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6449 dump_VARDESC(var_desc);
6450 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6451 return E_NOTIMPL;
6454 /* not found, look for it in inherited interfaces */
6455 ITypeInfo2_GetTypeKind(iface, &type_kind);
6456 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6457 if(This->impltypelist) {
6458 /* recursive search */
6459 ITypeInfo *pTInfo;
6460 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6461 if(SUCCEEDED(hres)){
6462 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6463 ITypeInfo_Release(pTInfo);
6464 return hres;
6466 WARN("Could not search inherited interface!\n");
6469 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6470 return DISP_E_MEMBERNOTFOUND;
6473 /* ITypeInfo::GetDocumentation
6475 * Retrieves the documentation string, the complete Help file name and path,
6476 * and the context ID for the Help topic for a specified type description.
6478 * (Can be tested by the Visual Basic Editor in Word for instance.)
6480 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6481 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6482 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6484 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6485 const TLBFuncDesc *pFDesc;
6486 const TLBVarDesc *pVDesc;
6487 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6488 " HelpContext(%p) HelpFile(%p)\n",
6489 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6490 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6491 if(pBstrName)
6492 *pBstrName=SysAllocString(This->Name);
6493 if(pBstrDocString)
6494 *pBstrDocString=SysAllocString(This->DocString);
6495 if(pdwHelpContext)
6496 *pdwHelpContext=This->dwHelpContext;
6497 if(pBstrHelpFile)
6498 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6499 return S_OK;
6500 }else {/* for a member */
6501 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6502 if(pFDesc->funcdesc.memid==memid){
6503 if(pBstrName)
6504 *pBstrName = SysAllocString(pFDesc->Name);
6505 if(pBstrDocString)
6506 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6507 if(pdwHelpContext)
6508 *pdwHelpContext=pFDesc->helpcontext;
6509 return S_OK;
6511 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6512 if(pVDesc->vardesc.memid==memid){
6513 if(pBstrName)
6514 *pBstrName = SysAllocString(pVDesc->Name);
6515 if(pBstrDocString)
6516 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6517 if(pdwHelpContext)
6518 *pdwHelpContext=pVDesc->HelpContext;
6519 return S_OK;
6523 if(This->impltypelist &&
6524 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6525 /* recursive search */
6526 ITypeInfo *pTInfo;
6527 HRESULT result;
6528 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6529 &pTInfo);
6530 if(SUCCEEDED(result)) {
6531 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6532 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6533 ITypeInfo_Release(pTInfo);
6534 return result;
6536 WARN("Could not search inherited interface!\n");
6539 WARN("member %d not found\n", memid);
6540 return TYPE_E_ELEMENTNOTFOUND;
6543 /* ITypeInfo::GetDllEntry
6545 * Retrieves a description or specification of an entry point for a function
6546 * in a DLL.
6548 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6549 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6550 WORD *pwOrdinal)
6552 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6553 const TLBFuncDesc *pFDesc;
6555 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6557 if (pBstrDllName) *pBstrDllName = NULL;
6558 if (pBstrName) *pBstrName = NULL;
6559 if (pwOrdinal) *pwOrdinal = 0;
6561 if (This->TypeAttr.typekind != TKIND_MODULE)
6562 return TYPE_E_BADMODULEKIND;
6564 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6565 if(pFDesc->funcdesc.memid==memid){
6566 dump_TypeInfo(This);
6567 if (TRACE_ON(ole))
6568 dump_TLBFuncDescOne(pFDesc);
6570 if (pBstrDllName)
6571 *pBstrDllName = SysAllocString(This->DllName);
6573 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6574 if (pBstrName)
6575 *pBstrName = SysAllocString(pFDesc->Entry);
6576 if (pwOrdinal)
6577 *pwOrdinal = -1;
6578 return S_OK;
6580 if (pBstrName)
6581 *pBstrName = NULL;
6582 if (pwOrdinal)
6583 *pwOrdinal = (DWORD)pFDesc->Entry;
6584 return S_OK;
6586 return TYPE_E_ELEMENTNOTFOUND;
6589 /* internal function to make the inherited interfaces' methods appear
6590 * part of the interface */
6591 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6592 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6594 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6595 HRESULT hr;
6597 TRACE("%p, 0x%x\n", iface, *hRefType);
6599 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6601 ITypeInfo *pSubTypeInfo;
6603 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6604 if (FAILED(hr))
6605 return hr;
6607 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6608 hRefType, ppTInfo);
6609 ITypeInfo_Release(pSubTypeInfo);
6610 if (SUCCEEDED(hr))
6611 return hr;
6613 *hRefType -= DISPATCH_HREF_OFFSET;
6615 if (!(*hRefType & DISPATCH_HREF_MASK))
6616 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6617 else
6618 return E_FAIL;
6621 /* ITypeInfo::GetRefTypeInfo
6623 * If a type description references other type descriptions, it retrieves
6624 * the referenced type descriptions.
6626 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6627 ITypeInfo2 *iface,
6628 HREFTYPE hRefType,
6629 ITypeInfo **ppTInfo)
6631 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6632 HRESULT result = E_FAIL;
6634 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6636 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6637 ITypeInfo_AddRef(*ppTInfo);
6638 result = S_OK;
6640 else if (hRefType == -1 &&
6641 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6642 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6644 /* when we meet a DUAL dispinterface, we must create the interface
6645 * version of it.
6647 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6650 /* the interface version contains the same information as the dispinterface
6651 * copy the contents of the structs.
6653 *pTypeInfoImpl = *This;
6654 pTypeInfoImpl->ref = 0;
6656 /* change the type to interface */
6657 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6659 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6661 /* we use data structures from This, so we need to keep a reference
6662 * to it to stop it being destroyed and signal to the new instance to
6663 * not free its data structures when it is destroyed */
6664 pTypeInfoImpl->no_free_data = TRUE;
6665 pTypeInfoImpl->next = This;
6666 ITypeInfo_AddRef((ITypeInfo*) This);
6668 ITypeInfo_AddRef(*ppTInfo);
6670 result = S_OK;
6672 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6673 (This->TypeAttr.typekind == TKIND_DISPATCH))
6675 HREFTYPE href_dispatch = hRefType;
6676 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6677 } else {
6678 TLBRefType *ref_type;
6679 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6681 if(ref_type->reference == hRefType)
6682 break;
6684 if(&ref_type->entry == &This->pTypeLib->ref_list)
6686 FIXME("Can't find pRefType for ref %x\n", hRefType);
6687 goto end;
6689 if(hRefType != -1) {
6690 ITypeLib *pTLib = NULL;
6692 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6693 UINT Index;
6694 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6695 } else {
6696 if(ref_type->pImpTLInfo->pImpTypeLib) {
6697 TRACE("typeinfo in imported typelib that is already loaded\n");
6698 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6699 ITypeLib2_AddRef(pTLib);
6700 result = S_OK;
6701 } else {
6702 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6703 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6704 ref_type->pImpTLInfo->wVersionMajor,
6705 ref_type->pImpTLInfo->wVersionMinor,
6706 ref_type->pImpTLInfo->lcid,
6707 &pTLib);
6709 if(FAILED(result)) {
6710 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6711 result=LoadTypeLib(libnam, &pTLib);
6712 SysFreeString(libnam);
6714 if(SUCCEEDED(result)) {
6715 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6716 ITypeLib2_AddRef(pTLib);
6720 if(SUCCEEDED(result)) {
6721 if(ref_type->index == TLB_REF_USE_GUID)
6722 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6723 &ref_type->guid,
6724 ppTInfo);
6725 else
6726 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6727 ppTInfo);
6729 if (pTLib != NULL)
6730 ITypeLib2_Release(pTLib);
6734 end:
6735 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6736 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6737 return result;
6740 /* ITypeInfo::AddressOfMember
6742 * Retrieves the addresses of static functions or variables, such as those
6743 * defined in a DLL.
6745 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6746 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6748 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6749 HRESULT hr;
6750 BSTR dll, entry;
6751 WORD ordinal;
6752 HMODULE module;
6754 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6756 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6757 if (FAILED(hr))
6758 return hr;
6760 module = LoadLibraryW(dll);
6761 if (!module)
6763 ERR("couldn't load %s\n", debugstr_w(dll));
6764 SysFreeString(dll);
6765 SysFreeString(entry);
6766 return STG_E_FILENOTFOUND;
6768 /* FIXME: store library somewhere where we can free it */
6770 if (entry)
6772 LPSTR entryA;
6773 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6774 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6775 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6777 *ppv = GetProcAddress(module, entryA);
6778 if (!*ppv)
6779 ERR("function not found %s\n", debugstr_a(entryA));
6781 HeapFree(GetProcessHeap(), 0, entryA);
6783 else
6785 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6786 if (!*ppv)
6787 ERR("function not found %d\n", ordinal);
6790 SysFreeString(dll);
6791 SysFreeString(entry);
6793 if (!*ppv)
6794 return TYPE_E_DLLFUNCTIONNOTFOUND;
6796 return S_OK;
6799 /* ITypeInfo::CreateInstance
6801 * Creates a new instance of a type that describes a component object class
6802 * (coclass).
6804 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6805 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6807 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6808 HRESULT hr;
6809 TYPEATTR *pTA;
6811 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6813 *ppvObj = NULL;
6815 if(pOuterUnk)
6817 WARN("Not able to aggregate\n");
6818 return CLASS_E_NOAGGREGATION;
6821 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6822 if(FAILED(hr)) return hr;
6824 if(pTA->typekind != TKIND_COCLASS)
6826 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6827 hr = E_INVALIDARG;
6828 goto end;
6831 hr = S_FALSE;
6832 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6834 IUnknown *pUnk;
6835 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6836 TRACE("GetActiveObject rets %08x\n", hr);
6837 if(hr == S_OK)
6839 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6840 IUnknown_Release(pUnk);
6844 if(hr != S_OK)
6845 hr = CoCreateInstance(&pTA->guid, NULL,
6846 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6847 riid, ppvObj);
6849 end:
6850 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6851 return hr;
6854 /* ITypeInfo::GetMops
6856 * Retrieves marshalling information.
6858 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6859 BSTR *pBstrMops)
6861 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6862 FIXME("(%p) stub!\n", This);
6863 return S_OK;
6866 /* ITypeInfo::GetContainingTypeLib
6868 * Retrieves the containing type library and the index of the type description
6869 * within that type library.
6871 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6872 ITypeLib * *ppTLib, UINT *pIndex)
6874 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6876 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6877 if (pIndex) {
6878 *pIndex=This->index;
6879 TRACE("returning pIndex=%d\n", *pIndex);
6882 if (ppTLib) {
6883 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6884 ITypeLib2_AddRef(*ppTLib);
6885 TRACE("returning ppTLib=%p\n", *ppTLib);
6888 return S_OK;
6891 /* ITypeInfo::ReleaseTypeAttr
6893 * Releases a TYPEATTR previously returned by GetTypeAttr.
6896 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6897 TYPEATTR* pTypeAttr)
6899 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6900 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6901 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6904 /* ITypeInfo::ReleaseFuncDesc
6906 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6908 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6909 ITypeInfo2 *iface,
6910 FUNCDESC *pFuncDesc)
6912 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6913 SHORT i;
6915 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6917 for (i = 0; i < pFuncDesc->cParams; i++)
6918 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6919 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6921 SysFreeString((BSTR)pFuncDesc);
6924 /* ITypeInfo::ReleaseVarDesc
6926 * Releases a VARDESC previously returned by GetVarDesc.
6928 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6929 VARDESC *pVarDesc)
6931 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6932 TRACE("(%p)->(%p)\n", This, pVarDesc);
6934 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6935 if (pVarDesc->varkind == VAR_CONST)
6936 VariantClear(pVarDesc->u.lpvarValue);
6937 SysFreeString((BSTR)pVarDesc);
6940 /* ITypeInfo2::GetTypeKind
6942 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6945 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6946 TYPEKIND *pTypeKind)
6948 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6949 *pTypeKind=This->TypeAttr.typekind;
6950 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6951 return S_OK;
6954 /* ITypeInfo2::GetTypeFlags
6956 * Returns the type flags without any allocations. This returns a DWORD type
6957 * flag, which expands the type flags without growing the TYPEATTR (type
6958 * attribute).
6961 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6963 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6964 *pTypeFlags=This->TypeAttr.wTypeFlags;
6965 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6966 return S_OK;
6969 /* ITypeInfo2::GetFuncIndexOfMemId
6970 * Binds to a specific member based on a known DISPID, where the member name
6971 * is not known (for example, when binding to a default member).
6974 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6975 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6977 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6978 const TLBFuncDesc *pFuncInfo;
6979 int i;
6980 HRESULT result;
6982 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6983 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6984 break;
6985 if(pFuncInfo) {
6986 *pFuncIndex = i;
6987 result = S_OK;
6988 } else
6989 result = TYPE_E_ELEMENTNOTFOUND;
6991 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6992 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6993 return result;
6996 /* TypeInfo2::GetVarIndexOfMemId
6998 * Binds to a specific member based on a known DISPID, where the member name
6999 * is not known (for example, when binding to a default member).
7002 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7003 MEMBERID memid, UINT *pVarIndex)
7005 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7006 TLBVarDesc *pVarInfo;
7007 int i;
7008 HRESULT result;
7009 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7010 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7012 if(pVarInfo) {
7013 *pVarIndex = i;
7014 result = S_OK;
7015 } else
7016 result = TYPE_E_ELEMENTNOTFOUND;
7018 TRACE("(%p) memid 0x%08x -> %s\n", This,
7019 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7020 return result;
7023 /* ITypeInfo2::GetCustData
7025 * Gets the custom data
7027 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7028 ITypeInfo2 * iface,
7029 REFGUID guid,
7030 VARIANT *pVarVal)
7032 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7033 TLBCustData *pCData;
7035 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7036 if( IsEqualIID(guid, &pCData->guid)) break;
7038 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7040 VariantInit( pVarVal);
7041 if (pCData)
7042 VariantCopy( pVarVal, &pCData->data);
7043 else
7044 VariantClear( pVarVal );
7045 return S_OK;
7048 /* ITypeInfo2::GetFuncCustData
7050 * Gets the custom data
7052 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7053 ITypeInfo2 * iface,
7054 UINT index,
7055 REFGUID guid,
7056 VARIANT *pVarVal)
7058 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7059 TLBCustData *pCData=NULL;
7060 TLBFuncDesc * pFDesc;
7061 UINT i;
7062 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7063 pFDesc=pFDesc->next);
7065 if(pFDesc)
7066 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7067 if( IsEqualIID(guid, &pCData->guid)) break;
7069 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7071 if(pCData){
7072 VariantInit( pVarVal);
7073 VariantCopy( pVarVal, &pCData->data);
7074 return S_OK;
7076 return E_INVALIDARG; /* FIXME: correct? */
7079 /* ITypeInfo2::GetParamCustData
7081 * Gets the custom data
7083 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7084 ITypeInfo2 * iface,
7085 UINT indexFunc,
7086 UINT indexParam,
7087 REFGUID guid,
7088 VARIANT *pVarVal)
7090 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7091 TLBCustData *pCData=NULL;
7092 TLBFuncDesc * pFDesc;
7093 UINT i;
7095 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7097 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7098 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7099 pCData = pCData->next)
7100 if( IsEqualIID(guid, &pCData->guid)) break;
7102 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7104 if(pCData)
7106 VariantInit( pVarVal);
7107 VariantCopy( pVarVal, &pCData->data);
7108 return S_OK;
7110 return E_INVALIDARG; /* FIXME: correct? */
7113 /* ITypeInfo2::GetVarCustData
7115 * Gets the custom data
7117 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7118 ITypeInfo2 * iface,
7119 UINT index,
7120 REFGUID guid,
7121 VARIANT *pVarVal)
7123 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7124 TLBCustData *pCData=NULL;
7125 TLBVarDesc * pVDesc;
7126 UINT i;
7128 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7130 if(pVDesc)
7132 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7134 if( IsEqualIID(guid, &pCData->guid)) break;
7138 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7140 if(pCData)
7142 VariantInit( pVarVal);
7143 VariantCopy( pVarVal, &pCData->data);
7144 return S_OK;
7146 return E_INVALIDARG; /* FIXME: correct? */
7149 /* ITypeInfo2::GetImplCustData
7151 * Gets the custom data
7153 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7154 ITypeInfo2 * iface,
7155 UINT index,
7156 REFGUID guid,
7157 VARIANT *pVarVal)
7159 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7160 TLBCustData *pCData=NULL;
7161 TLBImplType * pRDesc;
7162 UINT i;
7164 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7166 if(pRDesc)
7168 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7170 if( IsEqualIID(guid, &pCData->guid)) break;
7174 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7176 if(pCData)
7178 VariantInit( pVarVal);
7179 VariantCopy( pVarVal, &pCData->data);
7180 return S_OK;
7182 return E_INVALIDARG; /* FIXME: correct? */
7185 /* ITypeInfo2::GetDocumentation2
7187 * Retrieves the documentation string, the complete Help file name and path,
7188 * the localization context to use, and the context ID for the library Help
7189 * topic in the Help file.
7192 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7193 ITypeInfo2 * iface,
7194 MEMBERID memid,
7195 LCID lcid,
7196 BSTR *pbstrHelpString,
7197 DWORD *pdwHelpStringContext,
7198 BSTR *pbstrHelpStringDll)
7200 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7201 const TLBFuncDesc *pFDesc;
7202 const TLBVarDesc *pVDesc;
7203 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7204 "HelpStringContext(%p) HelpStringDll(%p)\n",
7205 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7206 pbstrHelpStringDll );
7207 /* the help string should be obtained from the helpstringdll,
7208 * using the _DLLGetDocumentation function, based on the supplied
7209 * lcid. Nice to do sometime...
7211 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7212 if(pbstrHelpString)
7213 *pbstrHelpString=SysAllocString(This->Name);
7214 if(pdwHelpStringContext)
7215 *pdwHelpStringContext=This->dwHelpStringContext;
7216 if(pbstrHelpStringDll)
7217 *pbstrHelpStringDll=
7218 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7219 return S_OK;
7220 }else {/* for a member */
7221 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7222 if(pFDesc->funcdesc.memid==memid){
7223 if(pbstrHelpString)
7224 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7225 if(pdwHelpStringContext)
7226 *pdwHelpStringContext=pFDesc->HelpStringContext;
7227 if(pbstrHelpStringDll)
7228 *pbstrHelpStringDll=
7229 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7230 return S_OK;
7232 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7233 if(pVDesc->vardesc.memid==memid){
7234 if(pbstrHelpString)
7235 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7236 if(pdwHelpStringContext)
7237 *pdwHelpStringContext=pVDesc->HelpStringContext;
7238 if(pbstrHelpStringDll)
7239 *pbstrHelpStringDll=
7240 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7241 return S_OK;
7244 return TYPE_E_ELEMENTNOTFOUND;
7247 /* ITypeInfo2::GetAllCustData
7249 * Gets all custom data items for the Type info.
7252 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7253 ITypeInfo2 * iface,
7254 CUSTDATA *pCustData)
7256 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7257 TLBCustData *pCData;
7258 int i;
7260 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7262 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7263 if(pCustData->prgCustData ){
7264 pCustData->cCustData=This->ctCustData;
7265 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7266 pCustData->prgCustData[i].guid=pCData->guid;
7267 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7269 }else{
7270 ERR(" OUT OF MEMORY!\n");
7271 return E_OUTOFMEMORY;
7273 return S_OK;
7276 /* ITypeInfo2::GetAllFuncCustData
7278 * Gets all custom data items for the specified Function
7281 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7282 ITypeInfo2 * iface,
7283 UINT index,
7284 CUSTDATA *pCustData)
7286 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7287 TLBCustData *pCData;
7288 TLBFuncDesc * pFDesc;
7289 UINT i;
7290 TRACE("(%p) index %d\n", This, index);
7291 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7292 pFDesc=pFDesc->next)
7294 if(pFDesc){
7295 pCustData->prgCustData =
7296 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7297 if(pCustData->prgCustData ){
7298 pCustData->cCustData=pFDesc->ctCustData;
7299 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7300 pCData = pCData->next){
7301 pCustData->prgCustData[i].guid=pCData->guid;
7302 VariantCopy(& pCustData->prgCustData[i].varValue,
7303 & pCData->data);
7305 }else{
7306 ERR(" OUT OF MEMORY!\n");
7307 return E_OUTOFMEMORY;
7309 return S_OK;
7311 return TYPE_E_ELEMENTNOTFOUND;
7314 /* ITypeInfo2::GetAllParamCustData
7316 * Gets all custom data items for the Functions
7319 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7320 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7322 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7323 TLBCustData *pCData=NULL;
7324 TLBFuncDesc * pFDesc;
7325 UINT i;
7326 TRACE("(%p) index %d\n", This, indexFunc);
7327 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7328 pFDesc=pFDesc->next)
7330 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7331 pCustData->prgCustData =
7332 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7333 sizeof(CUSTDATAITEM));
7334 if(pCustData->prgCustData ){
7335 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7336 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7337 pCData; i++, pCData = pCData->next){
7338 pCustData->prgCustData[i].guid=pCData->guid;
7339 VariantCopy(& pCustData->prgCustData[i].varValue,
7340 & pCData->data);
7342 }else{
7343 ERR(" OUT OF MEMORY!\n");
7344 return E_OUTOFMEMORY;
7346 return S_OK;
7348 return TYPE_E_ELEMENTNOTFOUND;
7351 /* ITypeInfo2::GetAllVarCustData
7353 * Gets all custom data items for the specified Variable
7356 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7357 UINT index, CUSTDATA *pCustData)
7359 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7360 TLBCustData *pCData;
7361 TLBVarDesc * pVDesc;
7362 UINT i;
7363 TRACE("(%p) index %d\n", This, index);
7364 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7365 pVDesc=pVDesc->next)
7367 if(pVDesc){
7368 pCustData->prgCustData =
7369 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7370 if(pCustData->prgCustData ){
7371 pCustData->cCustData=pVDesc->ctCustData;
7372 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7373 pCData = pCData->next){
7374 pCustData->prgCustData[i].guid=pCData->guid;
7375 VariantCopy(& pCustData->prgCustData[i].varValue,
7376 & pCData->data);
7378 }else{
7379 ERR(" OUT OF MEMORY!\n");
7380 return E_OUTOFMEMORY;
7382 return S_OK;
7384 return TYPE_E_ELEMENTNOTFOUND;
7387 /* ITypeInfo2::GetAllImplCustData
7389 * Gets all custom data items for the specified implementation type
7392 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7393 ITypeInfo2 * iface,
7394 UINT index,
7395 CUSTDATA *pCustData)
7397 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7398 TLBCustData *pCData;
7399 TLBImplType * pRDesc;
7400 UINT i;
7401 TRACE("(%p) index %d\n", This, index);
7402 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7403 pRDesc=pRDesc->next)
7405 if(pRDesc){
7406 pCustData->prgCustData =
7407 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7408 if(pCustData->prgCustData ){
7409 pCustData->cCustData=pRDesc->ctCustData;
7410 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7411 pCData = pCData->next){
7412 pCustData->prgCustData[i].guid=pCData->guid;
7413 VariantCopy(& pCustData->prgCustData[i].varValue,
7414 & pCData->data);
7416 }else{
7417 ERR(" OUT OF MEMORY!\n");
7418 return E_OUTOFMEMORY;
7420 return S_OK;
7422 return TYPE_E_ELEMENTNOTFOUND;
7425 static const ITypeInfo2Vtbl tinfvt =
7428 ITypeInfo_fnQueryInterface,
7429 ITypeInfo_fnAddRef,
7430 ITypeInfo_fnRelease,
7432 ITypeInfo_fnGetTypeAttr,
7433 ITypeInfo_fnGetTypeComp,
7434 ITypeInfo_fnGetFuncDesc,
7435 ITypeInfo_fnGetVarDesc,
7436 ITypeInfo_fnGetNames,
7437 ITypeInfo_fnGetRefTypeOfImplType,
7438 ITypeInfo_fnGetImplTypeFlags,
7439 ITypeInfo_fnGetIDsOfNames,
7440 ITypeInfo_fnInvoke,
7441 ITypeInfo_fnGetDocumentation,
7442 ITypeInfo_fnGetDllEntry,
7443 ITypeInfo_fnGetRefTypeInfo,
7444 ITypeInfo_fnAddressOfMember,
7445 ITypeInfo_fnCreateInstance,
7446 ITypeInfo_fnGetMops,
7447 ITypeInfo_fnGetContainingTypeLib,
7448 ITypeInfo_fnReleaseTypeAttr,
7449 ITypeInfo_fnReleaseFuncDesc,
7450 ITypeInfo_fnReleaseVarDesc,
7452 ITypeInfo2_fnGetTypeKind,
7453 ITypeInfo2_fnGetTypeFlags,
7454 ITypeInfo2_fnGetFuncIndexOfMemId,
7455 ITypeInfo2_fnGetVarIndexOfMemId,
7456 ITypeInfo2_fnGetCustData,
7457 ITypeInfo2_fnGetFuncCustData,
7458 ITypeInfo2_fnGetParamCustData,
7459 ITypeInfo2_fnGetVarCustData,
7460 ITypeInfo2_fnGetImplTypeCustData,
7461 ITypeInfo2_fnGetDocumentation2,
7462 ITypeInfo2_fnGetAllCustData,
7463 ITypeInfo2_fnGetAllFuncCustData,
7464 ITypeInfo2_fnGetAllParamCustData,
7465 ITypeInfo2_fnGetAllVarCustData,
7466 ITypeInfo2_fnGetAllImplTypeCustData,
7469 /******************************************************************************
7470 * CreateDispTypeInfo [OLEAUT32.31]
7472 * Build type information for an object so it can be called through an
7473 * IDispatch interface.
7475 * RETURNS
7476 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7477 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7479 * NOTES
7480 * This call allows an objects methods to be accessed through IDispatch, by
7481 * building an ITypeInfo object that IDispatch can use to call through.
7483 HRESULT WINAPI CreateDispTypeInfo(
7484 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7485 LCID lcid, /* [I] Locale Id */
7486 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7488 ITypeInfoImpl *pTIClass, *pTIIface;
7489 ITypeLibImpl *pTypeLibImpl;
7490 unsigned int param, func;
7491 TLBFuncDesc **ppFuncDesc;
7492 TLBRefType *ref;
7494 TRACE("\n");
7495 pTypeLibImpl = TypeLibImpl_Constructor();
7496 if (!pTypeLibImpl) return E_FAIL;
7498 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7499 pTIIface->pTypeLib = pTypeLibImpl;
7500 pTIIface->index = 0;
7501 pTIIface->Name = NULL;
7502 pTIIface->dwHelpContext = -1;
7503 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7504 pTIIface->TypeAttr.lcid = lcid;
7505 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7506 pTIIface->TypeAttr.wMajorVerNum = 0;
7507 pTIIface->TypeAttr.wMinorVerNum = 0;
7508 pTIIface->TypeAttr.cbAlignment = 2;
7509 pTIIface->TypeAttr.cbSizeInstance = -1;
7510 pTIIface->TypeAttr.cbSizeVft = -1;
7511 pTIIface->TypeAttr.cFuncs = 0;
7512 pTIIface->TypeAttr.cImplTypes = 0;
7513 pTIIface->TypeAttr.cVars = 0;
7514 pTIIface->TypeAttr.wTypeFlags = 0;
7516 ppFuncDesc = &pTIIface->funclist;
7517 for(func = 0; func < pidata->cMembers; func++) {
7518 METHODDATA *md = pidata->pmethdata + func;
7519 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7520 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7521 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7522 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7523 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7524 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7525 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7526 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7527 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7528 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7529 (*ppFuncDesc)->funcdesc.cScodes = 0;
7530 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7531 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7532 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7533 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7534 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7535 md->cArgs * sizeof(ELEMDESC));
7536 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7537 md->cArgs * sizeof(TLBParDesc));
7538 for(param = 0; param < md->cArgs; param++) {
7539 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7540 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7542 (*ppFuncDesc)->helpcontext = 0;
7543 (*ppFuncDesc)->HelpStringContext = 0;
7544 (*ppFuncDesc)->HelpString = NULL;
7545 (*ppFuncDesc)->Entry = NULL;
7546 (*ppFuncDesc)->ctCustData = 0;
7547 (*ppFuncDesc)->pCustData = NULL;
7548 (*ppFuncDesc)->next = NULL;
7549 pTIIface->TypeAttr.cFuncs++;
7550 ppFuncDesc = &(*ppFuncDesc)->next;
7553 dump_TypeInfo(pTIIface);
7555 pTypeLibImpl->pTypeInfo = pTIIface;
7556 pTypeLibImpl->TypeInfoCount++;
7558 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7559 pTIClass->pTypeLib = pTypeLibImpl;
7560 pTIClass->index = 1;
7561 pTIClass->Name = NULL;
7562 pTIClass->dwHelpContext = -1;
7563 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7564 pTIClass->TypeAttr.lcid = lcid;
7565 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7566 pTIClass->TypeAttr.wMajorVerNum = 0;
7567 pTIClass->TypeAttr.wMinorVerNum = 0;
7568 pTIClass->TypeAttr.cbAlignment = 2;
7569 pTIClass->TypeAttr.cbSizeInstance = -1;
7570 pTIClass->TypeAttr.cbSizeVft = -1;
7571 pTIClass->TypeAttr.cFuncs = 0;
7572 pTIClass->TypeAttr.cImplTypes = 1;
7573 pTIClass->TypeAttr.cVars = 0;
7574 pTIClass->TypeAttr.wTypeFlags = 0;
7576 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7577 pTIClass->impltypelist->hRef = 0;
7579 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7580 ref->index = 0;
7581 ref->reference = 0;
7582 ref->pImpTLInfo = TLB_REF_INTERNAL;
7583 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7585 dump_TypeInfo(pTIClass);
7587 pTIIface->next = pTIClass;
7588 pTypeLibImpl->TypeInfoCount++;
7590 *pptinfo = (ITypeInfo*)pTIClass;
7592 ITypeInfo_AddRef(*pptinfo);
7593 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7595 return S_OK;
7599 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7601 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7603 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7606 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7608 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7610 return ITypeInfo_AddRef((ITypeInfo *)This);
7613 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7615 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7617 return ITypeInfo_Release((ITypeInfo *)This);
7620 static HRESULT WINAPI ITypeComp_fnBind(
7621 ITypeComp * iface,
7622 OLECHAR * szName,
7623 ULONG lHash,
7624 WORD wFlags,
7625 ITypeInfo ** ppTInfo,
7626 DESCKIND * pDescKind,
7627 BINDPTR * pBindPtr)
7629 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7630 const TLBFuncDesc *pFDesc;
7631 const TLBVarDesc *pVDesc;
7632 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7634 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7636 *pDescKind = DESCKIND_NONE;
7637 pBindPtr->lpfuncdesc = NULL;
7638 *ppTInfo = NULL;
7640 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7641 if (!strcmpiW(pFDesc->Name, szName)) {
7642 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7643 break;
7644 else
7645 /* name found, but wrong flags */
7646 hr = TYPE_E_TYPEMISMATCH;
7649 if (pFDesc)
7651 HRESULT hr = TLB_AllocAndInitFuncDesc(
7652 &pFDesc->funcdesc,
7653 &pBindPtr->lpfuncdesc,
7654 This->TypeAttr.typekind == TKIND_DISPATCH);
7655 if (FAILED(hr))
7656 return hr;
7657 *pDescKind = DESCKIND_FUNCDESC;
7658 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7659 ITypeInfo_AddRef(*ppTInfo);
7660 return S_OK;
7661 } else {
7662 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7663 if (!strcmpiW(pVDesc->Name, szName)) {
7664 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7665 if (FAILED(hr))
7666 return hr;
7667 *pDescKind = DESCKIND_VARDESC;
7668 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7669 ITypeInfo_AddRef(*ppTInfo);
7670 return S_OK;
7674 /* FIXME: search each inherited interface, not just the first */
7675 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7676 /* recursive search */
7677 ITypeInfo *pTInfo;
7678 ITypeComp *pTComp;
7679 HRESULT hr;
7680 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7681 if (SUCCEEDED(hr))
7683 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7684 ITypeInfo_Release(pTInfo);
7686 if (SUCCEEDED(hr))
7688 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7689 ITypeComp_Release(pTComp);
7690 return hr;
7692 WARN("Could not search inherited interface!\n");
7694 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7695 return hr;
7698 static HRESULT WINAPI ITypeComp_fnBindType(
7699 ITypeComp * iface,
7700 OLECHAR * szName,
7701 ULONG lHash,
7702 ITypeInfo ** ppTInfo,
7703 ITypeComp ** ppTComp)
7705 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7707 /* strange behaviour (does nothing) but like the
7708 * original */
7710 if (!ppTInfo || !ppTComp)
7711 return E_POINTER;
7713 *ppTInfo = NULL;
7714 *ppTComp = NULL;
7716 return S_OK;
7719 static const ITypeCompVtbl tcompvt =
7722 ITypeComp_fnQueryInterface,
7723 ITypeComp_fnAddRef,
7724 ITypeComp_fnRelease,
7726 ITypeComp_fnBind,
7727 ITypeComp_fnBindType