wine.inf: Add a Wow64Install section for the Wow64-specific configuration.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blobc1fa321b8a4f2ba9edc27fb276dd28af5cd6330c
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 (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
556 res = E_FAIL;
557 else if (doc)
559 if (RegSetValueExW(key, NULL, 0, REG_SZ,
560 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
561 res = E_FAIL;
563 SysFreeString(doc);
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 IS_INTRESOURCE true, it's numeric; if -1 it isn't 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 not_attached_to_typelib;
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);
1088 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This);
1090 typedef struct tagTLBContext
1092 unsigned int oStart; /* start of TLB in file */
1093 unsigned int pos; /* current pos */
1094 unsigned int length; /* total length */
1095 void *mapping; /* memory mapping */
1096 MSFT_SegDir * pTblDir;
1097 ITypeLibImpl* pLibInfo;
1098 } TLBContext;
1101 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1104 debug
1106 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1107 if (pTD->vt & VT_RESERVED)
1108 szVarType += strlen(strcpy(szVarType, "reserved | "));
1109 if (pTD->vt & VT_BYREF)
1110 szVarType += strlen(strcpy(szVarType, "ref to "));
1111 if (pTD->vt & VT_ARRAY)
1112 szVarType += strlen(strcpy(szVarType, "array of "));
1113 if (pTD->vt & VT_VECTOR)
1114 szVarType += strlen(strcpy(szVarType, "vector of "));
1115 switch(pTD->vt & VT_TYPEMASK) {
1116 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1117 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1118 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1119 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1120 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1121 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1122 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1123 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1124 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1125 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1126 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1127 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1128 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1129 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1130 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1131 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1132 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1133 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1134 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1135 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1136 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1137 pTD->u.hreftype); break;
1138 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1139 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1140 case VT_PTR: sprintf(szVarType, "ptr to ");
1141 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1142 break;
1143 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1144 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1145 break;
1146 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1147 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1148 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1149 break;
1151 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1155 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1156 char buf[200];
1157 USHORT flags = edesc->u.paramdesc.wParamFlags;
1158 dump_TypeDesc(&edesc->tdesc,buf);
1159 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1160 MESSAGE("\t\tu.paramdesc.wParamFlags");
1161 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1162 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1163 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1164 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1165 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1166 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1167 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1168 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1169 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1171 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1172 int i;
1173 MESSAGE("memid is %08x\n",funcdesc->memid);
1174 for (i=0;i<funcdesc->cParams;i++) {
1175 MESSAGE("Param %d:\n",i);
1176 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1178 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1179 switch (funcdesc->funckind) {
1180 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1181 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1182 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1183 case FUNC_STATIC: MESSAGE("static");break;
1184 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1185 default: MESSAGE("unknown");break;
1187 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1188 switch (funcdesc->invkind) {
1189 case INVOKE_FUNC: MESSAGE("func");break;
1190 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1191 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1192 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1194 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1195 switch (funcdesc->callconv) {
1196 case CC_CDECL: MESSAGE("cdecl");break;
1197 case CC_PASCAL: MESSAGE("pascal");break;
1198 case CC_STDCALL: MESSAGE("stdcall");break;
1199 case CC_SYSCALL: MESSAGE("syscall");break;
1200 default:break;
1202 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1203 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1204 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1206 MESSAGE("\telemdescFunc (return value type):\n");
1207 dump_ELEMDESC(&funcdesc->elemdescFunc);
1210 static const char * const typekind_desc[] =
1212 "TKIND_ENUM",
1213 "TKIND_RECORD",
1214 "TKIND_MODULE",
1215 "TKIND_INTERFACE",
1216 "TKIND_DISPATCH",
1217 "TKIND_COCLASS",
1218 "TKIND_ALIAS",
1219 "TKIND_UNION",
1220 "TKIND_MAX"
1223 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1225 int i;
1226 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1227 for (i=0;i<pfd->funcdesc.cParams;i++)
1228 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1231 dump_FUNCDESC(&(pfd->funcdesc));
1233 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1234 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1236 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1238 while (pfd)
1240 dump_TLBFuncDescOne(pfd);
1241 pfd = pfd->next;
1244 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1246 while (pvd)
1248 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1249 pvd = pvd->next;
1253 static void dump_TLBImpLib(const TLBImpLib *import)
1255 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1256 debugstr_w(import->name));
1257 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1258 import->wVersionMinor, import->lcid, import->offset);
1261 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1263 TLBRefType *ref;
1265 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1267 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1268 if(ref->index == -1)
1269 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1270 else
1271 TRACE_(typelib)("type no: %d\n", ref->index);
1273 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1275 TRACE_(typelib)("in lib\n");
1276 dump_TLBImpLib(ref->pImpTLInfo);
1281 static void dump_TLBImplType(const TLBImplType * impl)
1283 while (impl) {
1284 TRACE_(typelib)(
1285 "implementing/inheriting interface hRef = %x implflags %x\n",
1286 impl->hRef, impl->implflags);
1287 impl = impl->next;
1291 static void dump_Variant(const VARIANT * pvar)
1293 SYSTEMTIME st;
1295 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1297 if (pvar)
1299 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1300 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1302 TRACE(",%p", V_BYREF(pvar));
1304 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1306 TRACE(",%p", V_ARRAY(pvar));
1308 else switch (V_TYPE(pvar))
1310 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1311 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1312 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1313 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1314 case VT_INT:
1315 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1316 case VT_UINT:
1317 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1318 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1319 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1320 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1321 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1322 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1323 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1324 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1325 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1326 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1327 V_CY(pvar).s.Lo); break;
1328 case VT_DATE:
1329 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1330 TRACE(",<invalid>");
1331 else
1332 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1333 st.wHour, st.wMinute, st.wSecond);
1334 break;
1335 case VT_ERROR:
1336 case VT_VOID:
1337 case VT_USERDEFINED:
1338 case VT_EMPTY:
1339 case VT_NULL: break;
1340 default: TRACE(",?"); break;
1343 TRACE("}\n");
1346 static void dump_DispParms(const DISPPARAMS * pdp)
1348 unsigned int index;
1350 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1352 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1354 TRACE("named args:\n");
1355 for (index = 0; index < pdp->cNamedArgs; index++)
1356 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1359 if (pdp->cArgs && pdp->rgvarg)
1361 TRACE("args:\n");
1362 for (index = 0; index < pdp->cArgs; index++)
1363 dump_Variant( &pdp->rgvarg[index] );
1367 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1369 TRACE("%p ref=%u\n", pty, pty->ref);
1370 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1371 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1372 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1373 TRACE("fct:%u var:%u impl:%u\n",
1374 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1375 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1376 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1377 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1378 if (TRACE_ON(ole))
1379 dump_TLBFuncDesc(pty->funclist);
1380 dump_TLBVarDesc(pty->varlist);
1381 dump_TLBImplType(pty->impltypelist);
1384 static void dump_VARDESC(const VARDESC *v)
1386 MESSAGE("memid %d\n",v->memid);
1387 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1388 MESSAGE("oInst %d\n",v->u.oInst);
1389 dump_ELEMDESC(&(v->elemdescVar));
1390 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1391 MESSAGE("varkind %d\n",v->varkind);
1394 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1396 /* VT_LPWSTR is largest type that */
1397 /* may appear in type description*/
1398 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1399 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1400 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1401 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1402 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1403 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1404 {{0},30},{{0},31}
1407 static void TLB_abort(void)
1409 DebugBreak();
1412 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1413 static void * TLB_Alloc(unsigned size)
1415 void * ret;
1416 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1417 /* FIXME */
1418 ERR("cannot allocate memory\n");
1420 return ret;
1423 static void TLB_Free(void * ptr)
1425 HeapFree(GetProcessHeap(), 0, ptr);
1428 /* returns the size required for a deep copy of a typedesc into a
1429 * flat buffer */
1430 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1432 SIZE_T size = 0;
1434 if (alloc_initial_space)
1435 size += sizeof(TYPEDESC);
1437 switch (tdesc->vt)
1439 case VT_PTR:
1440 case VT_SAFEARRAY:
1441 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1442 break;
1443 case VT_CARRAY:
1444 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1445 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1446 break;
1448 return size;
1451 /* deep copy a typedesc into a flat buffer */
1452 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1454 if (!dest)
1456 dest = buffer;
1457 buffer = (char *)buffer + sizeof(TYPEDESC);
1460 *dest = *src;
1462 switch (src->vt)
1464 case VT_PTR:
1465 case VT_SAFEARRAY:
1466 dest->u.lptdesc = buffer;
1467 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1468 break;
1469 case VT_CARRAY:
1470 dest->u.lpadesc = buffer;
1471 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1472 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1473 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1474 break;
1476 return buffer;
1479 /* free custom data allocated by MSFT_CustData */
1480 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1482 TLBCustData *pCustDataNext;
1483 for (; pCustData; pCustData = pCustDataNext)
1485 VariantClear(&pCustData->data);
1487 pCustDataNext = pCustData->next;
1488 TLB_Free(pCustData);
1492 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1494 DWORD len;
1495 BSTR ret;
1497 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1498 ret = SysAllocStringLen(NULL, len - 1);
1499 if (!ret) return ret;
1500 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1501 return ret;
1504 /**********************************************************************
1506 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1508 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1510 return pcx->pos;
1513 static inline void MSFT_Seek(TLBContext *pcx, long where)
1515 if (where != DO_NOT_SEEK)
1517 where += pcx->oStart;
1518 if (where > pcx->length)
1520 /* FIXME */
1521 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1522 TLB_abort();
1524 pcx->pos = where;
1528 /* read function */
1529 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1531 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1532 pcx->pos, count, pcx->oStart, pcx->length, where);
1534 MSFT_Seek(pcx, where);
1535 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1536 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1537 pcx->pos += count;
1538 return count;
1541 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1542 long where )
1544 DWORD ret;
1546 ret = MSFT_Read(buffer, count, pcx, where);
1547 FromLEDWords(buffer, ret);
1549 return ret;
1552 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1553 long where )
1555 DWORD ret;
1557 ret = MSFT_Read(buffer, count, pcx, where);
1558 FromLEWords(buffer, ret);
1560 return ret;
1563 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1565 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1566 memset(pGuid,0, sizeof(GUID));
1567 return;
1569 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1570 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1571 pGuid->Data2 = FromLEWord(pGuid->Data2);
1572 pGuid->Data3 = FromLEWord(pGuid->Data3);
1573 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1576 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1578 MSFT_NameIntro niName;
1580 if (offset < 0)
1582 ERR_(typelib)("bad offset %d\n", offset);
1583 return -1;
1586 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1587 pcx->pTblDir->pNametab.offset+offset);
1589 return niName.hreftype;
1592 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1594 char * name;
1595 MSFT_NameIntro niName;
1596 int lengthInChars;
1597 BSTR bstrName = NULL;
1599 if (offset < 0)
1601 ERR_(typelib)("bad offset %d\n", offset);
1602 return NULL;
1604 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1605 pcx->pTblDir->pNametab.offset+offset);
1606 niName.namelen &= 0xFF; /* FIXME: correct ? */
1607 name=TLB_Alloc((niName.namelen & 0xff) +1);
1608 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1609 name[niName.namelen & 0xff]='\0';
1611 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1612 name, -1, NULL, 0);
1614 /* no invalid characters in string */
1615 if (lengthInChars)
1617 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1619 /* don't check for invalid character since this has been done previously */
1620 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1622 TLB_Free(name);
1624 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1625 return bstrName;
1628 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1630 char * string;
1631 INT16 length;
1632 int lengthInChars;
1633 BSTR bstr = NULL;
1635 if(offset<0) return NULL;
1636 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1637 if(length <= 0) return 0;
1638 string=TLB_Alloc(length +1);
1639 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1640 string[length]='\0';
1642 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1643 string, -1, NULL, 0);
1645 /* no invalid characters in string */
1646 if (lengthInChars)
1648 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1650 /* don't check for invalid character since this has been done previously */
1651 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1653 TLB_Free(string);
1655 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1656 return bstr;
1659 * read a value and fill a VARIANT structure
1661 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1663 int size;
1665 TRACE_(typelib)("\n");
1667 if(offset <0) { /* data are packed in here */
1668 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1669 V_I4(pVar) = offset & 0x3ffffff;
1670 return;
1672 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1673 pcx->pTblDir->pCustData.offset + offset );
1674 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1675 switch (V_VT(pVar)){
1676 case VT_EMPTY: /* FIXME: is this right? */
1677 case VT_NULL: /* FIXME: is this right? */
1678 case VT_I2 : /* this should not happen */
1679 case VT_I4 :
1680 case VT_R4 :
1681 case VT_ERROR :
1682 case VT_BOOL :
1683 case VT_I1 :
1684 case VT_UI1 :
1685 case VT_UI2 :
1686 case VT_UI4 :
1687 case VT_INT :
1688 case VT_UINT :
1689 case VT_VOID : /* FIXME: is this right? */
1690 case VT_HRESULT :
1691 size=4; break;
1692 case VT_R8 :
1693 case VT_CY :
1694 case VT_DATE :
1695 case VT_I8 :
1696 case VT_UI8 :
1697 case VT_DECIMAL : /* FIXME: is this right? */
1698 case VT_FILETIME :
1699 size=8;break;
1700 /* pointer types with known behaviour */
1701 case VT_BSTR :{
1702 char * ptr;
1703 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1704 if(size < 0) {
1705 char next;
1706 DWORD origPos = MSFT_Tell(pcx), nullPos;
1708 do {
1709 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1710 } while (next);
1711 nullPos = MSFT_Tell(pcx);
1712 size = nullPos - origPos;
1713 MSFT_Seek(pcx, origPos);
1715 ptr=TLB_Alloc(size);/* allocate temp buffer */
1716 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1717 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1718 /* FIXME: do we need a AtoW conversion here? */
1719 V_UNION(pVar, bstrVal[size])='\0';
1720 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1721 TLB_Free(ptr);
1723 size=-4; break;
1724 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1725 case VT_DISPATCH :
1726 case VT_VARIANT :
1727 case VT_UNKNOWN :
1728 case VT_PTR :
1729 case VT_SAFEARRAY :
1730 case VT_CARRAY :
1731 case VT_USERDEFINED :
1732 case VT_LPSTR :
1733 case VT_LPWSTR :
1734 case VT_BLOB :
1735 case VT_STREAM :
1736 case VT_STORAGE :
1737 case VT_STREAMED_OBJECT :
1738 case VT_STORED_OBJECT :
1739 case VT_BLOB_OBJECT :
1740 case VT_CF :
1741 case VT_CLSID :
1742 default:
1743 size=0;
1744 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1745 V_VT(pVar));
1748 if(size>0) /* (big|small) endian correct? */
1749 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1750 return;
1753 * create a linked list with custom data
1755 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1757 MSFT_CDGuid entry;
1758 TLBCustData* pNew;
1759 int count=0;
1761 TRACE_(typelib)("\n");
1763 while(offset >=0){
1764 count++;
1765 pNew=TLB_Alloc(sizeof(TLBCustData));
1766 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1767 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1768 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1769 /* add new custom data at head of the list */
1770 pNew->next=*ppCustData;
1771 *ppCustData=pNew;
1772 offset = entry.next;
1774 return count;
1777 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1778 ITypeInfoImpl *pTI)
1780 if(type <0)
1781 pTd->vt=type & VT_TYPEMASK;
1782 else
1783 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1785 if(pTd->vt == VT_USERDEFINED)
1786 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1788 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1791 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1793 /* resolve referenced type if any */
1794 while (lpTypeDesc)
1796 switch (lpTypeDesc->vt)
1798 case VT_PTR:
1799 lpTypeDesc = lpTypeDesc->u.lptdesc;
1800 break;
1802 case VT_CARRAY:
1803 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1804 break;
1806 case VT_USERDEFINED:
1807 MSFT_DoRefType(pcx, pTI->pTypeLib,
1808 lpTypeDesc->u.hreftype);
1810 lpTypeDesc = NULL;
1811 break;
1813 default:
1814 lpTypeDesc = NULL;
1819 static void
1820 MSFT_DoFuncs(TLBContext* pcx,
1821 ITypeInfoImpl* pTI,
1822 int cFuncs,
1823 int cVars,
1824 int offset,
1825 TLBFuncDesc** pptfd)
1828 * member information is stored in a data structure at offset
1829 * indicated by the memoffset field of the typeinfo structure
1830 * There are several distinctive parts.
1831 * The first part starts with a field that holds the total length
1832 * of this (first) part excluding this field. Then follow the records,
1833 * for each member there is one record.
1835 * The first entry is always the length of the record (including this
1836 * length word).
1837 * The rest of the record depends on the type of the member. If there is
1838 * a field indicating the member type (function, variable, interface, etc)
1839 * I have not found it yet. At this time we depend on the information
1840 * in the type info and the usual order how things are stored.
1842 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1843 * for each member;
1845 * Third is an equal sized array with file offsets to the name entry
1846 * of each member.
1848 * The fourth and last (?) part is an array with offsets to the records
1849 * in the first part of this file segment.
1852 int infolen, nameoffset, reclength, nrattributes, i;
1853 int recoffset = offset + sizeof(INT);
1855 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1856 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1857 TLBFuncDesc *ptfd_prev = NULL;
1859 TRACE_(typelib)("\n");
1861 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1863 for ( i = 0; i < cFuncs ; i++ )
1865 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1867 /* name, eventually add to a hash table */
1868 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1869 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1871 /* nameoffset is sometimes -1 on the second half of a propget/propput
1872 * pair of functions */
1873 if ((nameoffset == -1) && (i > 0))
1874 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1875 else
1876 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1878 /* read the function information record */
1879 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1881 reclength &= 0xffff;
1883 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1885 /* do the attributes */
1886 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1887 / sizeof(int);
1889 if ( nrattributes > 0 )
1891 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1893 if ( nrattributes > 1 )
1895 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1896 pFuncRec->OptAttr[1]) ;
1898 if ( nrattributes > 2 )
1900 if ( pFuncRec->FKCCIC & 0x2000 )
1902 if (!IS_INTRESOURCE(pFuncRec->OptAttr[2]))
1903 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->OptAttr[2]);
1904 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1906 else
1908 (*pptfd)->Entry = MSFT_ReadString(pcx,
1909 pFuncRec->OptAttr[2]);
1911 if( nrattributes > 5 )
1913 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1915 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1917 MSFT_CustData(pcx,
1918 pFuncRec->OptAttr[6],
1919 &(*pptfd)->pCustData);
1923 else
1925 (*pptfd)->Entry = (BSTR)-1;
1930 /* fill the FuncDesc Structure */
1931 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1932 offset + infolen + ( i + 1) * sizeof(INT));
1934 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1935 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1936 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1937 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1938 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1939 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1940 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1942 MSFT_GetTdesc(pcx,
1943 pFuncRec->DataType,
1944 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1945 pTI);
1946 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1948 /* do the parameters/arguments */
1949 if(pFuncRec->nrargs)
1951 int j = 0;
1952 MSFT_ParameterInfo paraminfo;
1954 (*pptfd)->funcdesc.lprgelemdescParam =
1955 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1957 (*pptfd)->pParamDesc =
1958 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1960 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1961 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1963 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1965 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1967 MSFT_GetTdesc(pcx,
1968 paraminfo.DataType,
1969 &elemdesc->tdesc,
1970 pTI);
1972 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1974 /* name */
1975 if (paraminfo.oName == -1)
1976 /* this occurs for [propput] or [propget] methods, so
1977 * we should just set the name of the parameter to the
1978 * name of the method. */
1979 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1980 else
1981 (*pptfd)->pParamDesc[j].Name =
1982 MSFT_ReadName( pcx, paraminfo.oName );
1983 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1985 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1987 /* default value */
1988 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1989 (pFuncRec->FKCCIC & 0x1000) )
1991 INT* pInt = (INT *)((char *)pFuncRec +
1992 reclength -
1993 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1995 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1997 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1998 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2000 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2001 pInt[j], pcx);
2003 else
2004 elemdesc->u.paramdesc.pparamdescex = NULL;
2005 /* custom info */
2006 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2008 MSFT_CustData(pcx,
2009 pFuncRec->OptAttr[7+j],
2010 &(*pptfd)->pParamDesc[j].pCustData);
2013 /* SEEK value = jump to offset,
2014 * from there jump to the end of record,
2015 * go back by (j-1) arguments
2017 MSFT_ReadLEDWords( &paraminfo ,
2018 sizeof(MSFT_ParameterInfo), pcx,
2019 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2020 * sizeof(MSFT_ParameterInfo)));
2024 /* scode is not used: archaic win16 stuff FIXME: right? */
2025 (*pptfd)->funcdesc.cScodes = 0 ;
2026 (*pptfd)->funcdesc.lprgscode = NULL ;
2028 ptfd_prev = *pptfd;
2029 pptfd = & ((*pptfd)->next);
2030 recoffset += reclength;
2032 HeapFree(GetProcessHeap(), 0, recbuf);
2035 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2036 int cVars, int offset, TLBVarDesc ** pptvd)
2038 int infolen, nameoffset, reclength;
2039 char recbuf[256];
2040 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2041 int i;
2042 int recoffset;
2044 TRACE_(typelib)("\n");
2046 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2047 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2048 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2049 recoffset += offset+sizeof(INT);
2050 for(i=0;i<cVars;i++){
2051 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2052 /* name, eventually add to a hash table */
2053 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2054 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2055 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2056 /* read the variable information record */
2057 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2058 reclength &=0xff;
2059 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2060 /* Optional data */
2061 if(reclength >(6*sizeof(INT)) )
2062 (*pptvd)->HelpContext=pVarRec->HelpContext;
2063 if(reclength >(7*sizeof(INT)) )
2064 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2065 if(reclength >(8*sizeof(INT)) )
2066 if(reclength >(9*sizeof(INT)) )
2067 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2068 /* fill the VarDesc Structure */
2069 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2070 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2071 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2072 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2073 MSFT_GetTdesc(pcx, pVarRec->DataType,
2074 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2075 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2076 if(pVarRec->VarKind == VAR_CONST ){
2077 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2078 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2079 pVarRec->OffsValue, pcx);
2080 } else
2081 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2082 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2083 pptvd=&((*pptvd)->next);
2084 recoffset += reclength;
2087 /* fill in data for a hreftype (offset). When the referenced type is contained
2088 * in the typelib, it's just an (file) offset in the type info base dir.
2089 * If comes from import, it's an offset+1 in the ImpInfo table
2090 * */
2091 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2092 int offset)
2094 TLBRefType *ref;
2096 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2098 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2100 if(ref->reference == offset) return;
2103 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2104 list_add_tail(&pTL->ref_list, &ref->entry);
2106 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2107 /* external typelib */
2108 MSFT_ImpInfo impinfo;
2109 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2111 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2113 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2114 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2115 while (pImpLib){ /* search the known offsets of all import libraries */
2116 if(pImpLib->offset==impinfo.oImpFile) break;
2117 pImpLib=pImpLib->next;
2119 if(pImpLib){
2120 ref->reference = offset;
2121 ref->pImpTLInfo = pImpLib;
2122 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2123 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2124 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2125 ref->index = TLB_REF_USE_GUID;
2126 } else
2127 ref->index = impinfo.oGuid;
2128 }else{
2129 ERR("Cannot find a reference\n");
2130 ref->reference = -1;
2131 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2133 }else{
2134 /* in this typelib */
2135 ref->index = MSFT_HREFTYPE_INDEX(offset);
2136 ref->reference = offset;
2137 ref->pImpTLInfo = TLB_REF_INTERNAL;
2141 /* process Implemented Interfaces of a com class */
2142 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2143 int offset)
2145 int i;
2146 MSFT_RefRecord refrec;
2147 TLBImplType **ppImpl = &pTI->impltypelist;
2149 TRACE_(typelib)("\n");
2151 for(i=0;i<count;i++){
2152 if(offset<0) break; /* paranoia */
2153 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2154 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2155 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2156 (*ppImpl)->hRef = refrec.reftype;
2157 (*ppImpl)->implflags=refrec.flags;
2158 (*ppImpl)->ctCustData=
2159 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2160 offset=refrec.onext;
2161 ppImpl=&((*ppImpl)->next);
2165 * process a typeinfo record
2167 static ITypeInfoImpl * MSFT_DoTypeInfo(
2168 TLBContext *pcx,
2169 int count,
2170 ITypeLibImpl * pLibInfo)
2172 MSFT_TypeInfoBase tiBase;
2173 ITypeInfoImpl *ptiRet;
2175 TRACE_(typelib)("count=%u\n", count);
2177 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2178 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2179 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2181 /* this is where we are coming from */
2182 ptiRet->pTypeLib = pLibInfo;
2183 ptiRet->index=count;
2184 /* fill in the typeattr fields */
2186 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2187 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2188 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2189 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2190 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2191 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2192 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2193 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2194 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2195 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2196 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2197 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2198 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2199 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2200 MSFT_GetTdesc(pcx, tiBase.datatype1,
2201 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2203 /* FIXME: */
2204 /* IDLDESC idldescType; *//* never saw this one != zero */
2206 /* name, eventually add to a hash table */
2207 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2208 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2209 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2210 /* help info */
2211 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2212 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2213 ptiRet->dwHelpContext=tiBase.helpcontext;
2215 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2216 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2218 /* note: InfoType's Help file and HelpStringDll come from the containing
2219 * library. Further HelpString and Docstring appear to be the same thing :(
2221 /* functions */
2222 if(ptiRet->TypeAttr.cFuncs >0 )
2223 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2224 ptiRet->TypeAttr.cVars,
2225 tiBase.memoffset, & ptiRet->funclist);
2226 /* variables */
2227 if(ptiRet->TypeAttr.cVars >0 )
2228 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2229 ptiRet->TypeAttr.cVars,
2230 tiBase.memoffset, & ptiRet->varlist);
2231 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2232 switch(ptiRet->TypeAttr.typekind)
2234 case TKIND_COCLASS:
2235 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2236 tiBase.datatype1);
2237 break;
2238 case TKIND_DISPATCH:
2239 /* This is not -1 when the interface is a non-base dual interface or
2240 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2241 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2242 not this interface.
2245 if (tiBase.datatype1 != -1)
2247 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2248 ptiRet->impltypelist->hRef = tiBase.datatype1;
2249 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2251 break;
2252 default:
2253 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2254 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2255 ptiRet->impltypelist->hRef = tiBase.datatype1;
2256 break;
2259 ptiRet->ctCustData=
2260 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2262 TRACE_(typelib)("%s guid: %s kind:%s\n",
2263 debugstr_w(ptiRet->Name),
2264 debugstr_guid(&ptiRet->TypeAttr.guid),
2265 typekind_desc[ptiRet->TypeAttr.typekind]);
2266 if (TRACE_ON(typelib))
2267 dump_TypeInfo(ptiRet);
2269 return ptiRet;
2272 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2273 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2274 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2275 * tradeoff here.
2277 static ITypeLibImpl *tlb_cache_first;
2278 static CRITICAL_SECTION cache_section;
2279 static CRITICAL_SECTION_DEBUG cache_section_debug =
2281 0, 0, &cache_section,
2282 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2283 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2285 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2288 typedef struct TLB_PEFile
2290 const IUnknownVtbl *lpvtbl;
2291 LONG refs;
2292 HMODULE dll;
2293 HRSRC typelib_resource;
2294 HGLOBAL typelib_global;
2295 LPVOID typelib_base;
2296 } TLB_PEFile;
2298 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2300 if (IsEqualIID(riid, &IID_IUnknown))
2302 *ppv = iface;
2303 IUnknown_AddRef(iface);
2304 return S_OK;
2306 *ppv = NULL;
2307 return E_NOINTERFACE;
2310 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2312 TLB_PEFile *This = (TLB_PEFile *)iface;
2313 return InterlockedIncrement(&This->refs);
2316 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2318 TLB_PEFile *This = (TLB_PEFile *)iface;
2319 ULONG refs = InterlockedDecrement(&This->refs);
2320 if (!refs)
2322 if (This->typelib_global)
2323 FreeResource(This->typelib_global);
2324 if (This->dll)
2325 FreeLibrary(This->dll);
2326 HeapFree(GetProcessHeap(), 0, This);
2328 return refs;
2331 static const IUnknownVtbl TLB_PEFile_Vtable =
2333 TLB_PEFile_QueryInterface,
2334 TLB_PEFile_AddRef,
2335 TLB_PEFile_Release
2338 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2340 TLB_PEFile *This;
2342 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2343 if (!This)
2344 return E_OUTOFMEMORY;
2346 This->lpvtbl = &TLB_PEFile_Vtable;
2347 This->refs = 1;
2348 This->dll = NULL;
2349 This->typelib_resource = NULL;
2350 This->typelib_global = NULL;
2351 This->typelib_base = NULL;
2353 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2354 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2356 if (This->dll)
2358 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2359 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2360 if (This->typelib_resource)
2362 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2363 if (This->typelib_global)
2365 This->typelib_base = LockResource(This->typelib_global);
2367 if (This->typelib_base)
2369 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2370 *ppBase = This->typelib_base;
2371 *ppFile = (IUnknown *)&This->lpvtbl;
2372 return S_OK;
2378 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2379 return TYPE_E_CANTLOADLIBRARY;
2382 typedef struct TLB_NEFile
2384 const IUnknownVtbl *lpvtbl;
2385 LONG refs;
2386 LPVOID typelib_base;
2387 } TLB_NEFile;
2389 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2391 if (IsEqualIID(riid, &IID_IUnknown))
2393 *ppv = iface;
2394 IUnknown_AddRef(iface);
2395 return S_OK;
2397 *ppv = NULL;
2398 return E_NOINTERFACE;
2401 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2403 TLB_NEFile *This = (TLB_NEFile *)iface;
2404 return InterlockedIncrement(&This->refs);
2407 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2409 TLB_NEFile *This = (TLB_NEFile *)iface;
2410 ULONG refs = InterlockedDecrement(&This->refs);
2411 if (!refs)
2413 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2414 HeapFree(GetProcessHeap(), 0, This);
2416 return refs;
2419 static const IUnknownVtbl TLB_NEFile_Vtable =
2421 TLB_NEFile_QueryInterface,
2422 TLB_NEFile_AddRef,
2423 TLB_NEFile_Release
2426 /***********************************************************************
2427 * read_xx_header [internal]
2429 static int read_xx_header( HFILE lzfd )
2431 IMAGE_DOS_HEADER mzh;
2432 char magic[3];
2434 LZSeek( lzfd, 0, SEEK_SET );
2435 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2436 return 0;
2437 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2438 return 0;
2440 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2441 if ( 2 != LZRead( lzfd, magic, 2 ) )
2442 return 0;
2444 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2446 if ( magic[0] == 'N' && magic[1] == 'E' )
2447 return IMAGE_OS2_SIGNATURE;
2448 if ( magic[0] == 'P' && magic[1] == 'E' )
2449 return IMAGE_NT_SIGNATURE;
2451 magic[2] = '\0';
2452 WARN("Can't handle %s files.\n", magic );
2453 return 0;
2457 /***********************************************************************
2458 * find_ne_resource [internal]
2460 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2461 DWORD *resLen, DWORD *resOff )
2463 IMAGE_OS2_HEADER nehd;
2464 NE_TYPEINFO *typeInfo;
2465 NE_NAMEINFO *nameInfo;
2466 DWORD nehdoffset;
2467 LPBYTE resTab;
2468 DWORD resTabSize;
2469 int count;
2471 /* Read in NE header */
2472 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2473 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2475 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2476 if ( !resTabSize )
2478 TRACE("No resources in NE dll\n" );
2479 return FALSE;
2482 /* Read in resource table */
2483 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2484 if ( !resTab ) return FALSE;
2486 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2487 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2489 HeapFree( GetProcessHeap(), 0, resTab );
2490 return FALSE;
2493 /* Find resource */
2494 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2496 if (!IS_INTRESOURCE(typeid)) /* named type */
2498 BYTE len = strlen( typeid );
2499 while (typeInfo->type_id)
2501 if (!(typeInfo->type_id & 0x8000))
2503 BYTE *p = resTab + typeInfo->type_id;
2504 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2506 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2507 typeInfo->count * sizeof(NE_NAMEINFO));
2510 else /* numeric type id */
2512 WORD id = LOWORD(typeid) | 0x8000;
2513 while (typeInfo->type_id)
2515 if (typeInfo->type_id == id) goto found_type;
2516 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2517 typeInfo->count * sizeof(NE_NAMEINFO));
2520 TRACE("No typeid entry found for %p\n", typeid );
2521 HeapFree( GetProcessHeap(), 0, resTab );
2522 return FALSE;
2524 found_type:
2525 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2527 if (!IS_INTRESOURCE(resid)) /* named resource */
2529 BYTE len = strlen( resid );
2530 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2532 BYTE *p = resTab + nameInfo->id;
2533 if (nameInfo->id & 0x8000) continue;
2534 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2537 else /* numeric resource id */
2539 WORD id = LOWORD(resid) | 0x8000;
2540 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2541 if (nameInfo->id == id) goto found_name;
2543 TRACE("No resid entry found for %p\n", typeid );
2544 HeapFree( GetProcessHeap(), 0, resTab );
2545 return FALSE;
2547 found_name:
2548 /* Return resource data */
2549 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2550 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2552 HeapFree( GetProcessHeap(), 0, resTab );
2553 return TRUE;
2556 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2558 HFILE lzfd = -1;
2559 OFSTRUCT ofs;
2560 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2561 TLB_NEFile *This = NULL;
2563 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2564 if (!This) return E_OUTOFMEMORY;
2566 This->lpvtbl = &TLB_NEFile_Vtable;
2567 This->refs = 1;
2568 This->typelib_base = NULL;
2570 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2571 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2573 DWORD reslen, offset;
2574 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2576 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2577 if( !This->typelib_base )
2578 hr = E_OUTOFMEMORY;
2579 else
2581 LZSeek( lzfd, offset, SEEK_SET );
2582 reslen = LZRead( lzfd, This->typelib_base, reslen );
2583 LZClose( lzfd );
2584 *ppBase = This->typelib_base;
2585 *pdwTLBLength = reslen;
2586 *ppFile = (IUnknown *)&This->lpvtbl;
2587 return S_OK;
2592 if( lzfd >= 0) LZClose( lzfd );
2593 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2594 return hr;
2597 typedef struct TLB_Mapping
2599 const IUnknownVtbl *lpvtbl;
2600 LONG refs;
2601 HANDLE file;
2602 HANDLE mapping;
2603 LPVOID typelib_base;
2604 } TLB_Mapping;
2606 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2608 if (IsEqualIID(riid, &IID_IUnknown))
2610 *ppv = iface;
2611 IUnknown_AddRef(iface);
2612 return S_OK;
2614 *ppv = NULL;
2615 return E_NOINTERFACE;
2618 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2620 TLB_Mapping *This = (TLB_Mapping *)iface;
2621 return InterlockedIncrement(&This->refs);
2624 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2626 TLB_Mapping *This = (TLB_Mapping *)iface;
2627 ULONG refs = InterlockedDecrement(&This->refs);
2628 if (!refs)
2630 if (This->typelib_base)
2631 UnmapViewOfFile(This->typelib_base);
2632 if (This->mapping)
2633 CloseHandle(This->mapping);
2634 if (This->file != INVALID_HANDLE_VALUE)
2635 CloseHandle(This->file);
2636 HeapFree(GetProcessHeap(), 0, This);
2638 return refs;
2641 static const IUnknownVtbl TLB_Mapping_Vtable =
2643 TLB_Mapping_QueryInterface,
2644 TLB_Mapping_AddRef,
2645 TLB_Mapping_Release
2648 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2650 TLB_Mapping *This;
2652 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2653 if (!This)
2654 return E_OUTOFMEMORY;
2656 This->lpvtbl = &TLB_Mapping_Vtable;
2657 This->refs = 1;
2658 This->file = INVALID_HANDLE_VALUE;
2659 This->mapping = NULL;
2660 This->typelib_base = NULL;
2662 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2663 if (INVALID_HANDLE_VALUE != This->file)
2665 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2666 if (This->mapping)
2668 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2669 if(This->typelib_base)
2671 /* retrieve file size */
2672 *pdwTLBLength = GetFileSize(This->file, NULL);
2673 *ppBase = This->typelib_base;
2674 *ppFile = (IUnknown *)&This->lpvtbl;
2675 return S_OK;
2680 IUnknown_Release((IUnknown *)&This->lpvtbl);
2681 return TYPE_E_CANTLOADLIBRARY;
2684 /****************************************************************************
2685 * TLB_ReadTypeLib
2687 * find the type of the typelib file and map the typelib resource into
2688 * the memory
2690 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2691 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2692 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2694 ITypeLibImpl *entry;
2695 HRESULT ret;
2696 INT index = 1;
2697 LPWSTR index_str, file = (LPWSTR)pszFileName;
2698 LPVOID pBase = NULL;
2699 DWORD dwTLBLength = 0;
2700 IUnknown *pFile = NULL;
2702 *ppTypeLib = NULL;
2704 index_str = strrchrW(pszFileName, '\\');
2705 if(index_str && *++index_str != '\0')
2707 LPWSTR end_ptr;
2708 long idx = strtolW(index_str, &end_ptr, 10);
2709 if(*end_ptr == '\0')
2711 int str_len = index_str - pszFileName - 1;
2712 index = idx;
2713 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2714 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2715 file[str_len] = 0;
2719 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2721 if(strchrW(file, '\\'))
2723 lstrcpyW(pszPath, file);
2725 else
2727 int len = GetSystemDirectoryW(pszPath, cchPath);
2728 pszPath[len] = '\\';
2729 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2733 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2735 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2737 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2738 EnterCriticalSection(&cache_section);
2739 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2741 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2743 TRACE("cache hit\n");
2744 *ppTypeLib = (ITypeLib2*)entry;
2745 ITypeLib_AddRef(*ppTypeLib);
2746 LeaveCriticalSection(&cache_section);
2747 return S_OK;
2750 LeaveCriticalSection(&cache_section);
2752 /* now actually load and parse the typelib */
2754 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2755 if (ret == TYPE_E_CANTLOADLIBRARY)
2756 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2757 if (ret == TYPE_E_CANTLOADLIBRARY)
2758 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2759 if (SUCCEEDED(ret))
2761 if (dwTLBLength >= 4)
2763 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2764 if (dwSignature == MSFT_SIGNATURE)
2765 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2766 else if (dwSignature == SLTG_SIGNATURE)
2767 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2768 else
2770 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2771 ret = TYPE_E_CANTLOADLIBRARY;
2774 else
2775 ret = TYPE_E_CANTLOADLIBRARY;
2776 IUnknown_Release(pFile);
2779 if(*ppTypeLib) {
2780 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2782 TRACE("adding to cache\n");
2783 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2784 lstrcpyW(impl->path, pszPath);
2785 /* We should really canonicalise the path here. */
2786 impl->index = index;
2788 /* FIXME: check if it has added already in the meantime */
2789 EnterCriticalSection(&cache_section);
2790 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2791 impl->prev = NULL;
2792 tlb_cache_first = impl;
2793 LeaveCriticalSection(&cache_section);
2794 ret = S_OK;
2795 } else
2796 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2798 return ret;
2801 /*================== ITypeLib(2) Methods ===================================*/
2803 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2805 ITypeLibImpl* pTypeLibImpl;
2807 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2808 if (!pTypeLibImpl) return NULL;
2810 pTypeLibImpl->lpVtbl = &tlbvt;
2811 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2812 pTypeLibImpl->ref = 1;
2814 list_init(&pTypeLibImpl->ref_list);
2815 pTypeLibImpl->dispatch_href = -1;
2817 return pTypeLibImpl;
2820 /****************************************************************************
2821 * ITypeLib2_Constructor_MSFT
2823 * loading an MSFT typelib from an in-memory image
2825 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2827 TLBContext cx;
2828 long lPSegDir;
2829 MSFT_Header tlbHeader;
2830 MSFT_SegDir tlbSegDir;
2831 ITypeLibImpl * pTypeLibImpl;
2833 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2835 pTypeLibImpl = TypeLibImpl_Constructor();
2836 if (!pTypeLibImpl) return NULL;
2838 /* get pointer to beginning of typelib data */
2839 cx.pos = 0;
2840 cx.oStart=0;
2841 cx.mapping = pLib;
2842 cx.pLibInfo = pTypeLibImpl;
2843 cx.length = dwTLBLength;
2845 /* read header */
2846 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2847 TRACE_(typelib)("header:\n");
2848 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2849 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2850 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2851 return NULL;
2853 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2855 /* there is a small amount of information here until the next important
2856 * part:
2857 * the segment directory . Try to calculate the amount of data */
2858 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2860 /* now read the segment directory */
2861 TRACE("read segment directory (at %ld)\n",lPSegDir);
2862 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2863 cx.pTblDir = &tlbSegDir;
2865 /* just check two entries */
2866 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2868 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2869 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2870 return NULL;
2873 /* now fill our internal data */
2874 /* TLIBATTR fields */
2875 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2877 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2878 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2879 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2880 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2881 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2883 pTypeLibImpl->lcid = tlbHeader.lcid;
2885 /* name, eventually add to a hash table */
2886 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2888 /* help info */
2889 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2890 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2892 if( tlbHeader.varflags & HELPDLLFLAG)
2894 int offset;
2895 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2896 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2899 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2901 /* custom data */
2902 if(tlbHeader.CustomDataOffset >= 0)
2904 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2907 /* fill in type descriptions */
2908 if(tlbSegDir.pTypdescTab.length > 0)
2910 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2911 INT16 td[4];
2912 pTypeLibImpl->ctTypeDesc = cTD;
2913 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2914 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2915 for(i=0; i<cTD; )
2917 /* FIXME: add several sanity checks here */
2918 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2919 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2921 /* FIXME: check safearray */
2922 if(td[3] < 0)
2923 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2924 else
2925 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2927 else if(td[0] == VT_CARRAY)
2929 /* array descr table here */
2930 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2932 else if(td[0] == VT_USERDEFINED)
2934 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2936 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2939 /* second time around to fill the array subscript info */
2940 for(i=0;i<cTD;i++)
2942 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2943 if(tlbSegDir.pArrayDescriptions.offset>0)
2945 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2946 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2948 if(td[1]<0)
2949 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2950 else
2951 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
2953 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2955 for(j = 0; j<td[2]; j++)
2957 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2958 sizeof(INT), &cx, DO_NOT_SEEK);
2959 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2960 sizeof(INT), &cx, DO_NOT_SEEK);
2963 else
2965 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2966 ERR("didn't find array description data\n");
2971 /* imported type libs */
2972 if(tlbSegDir.pImpFiles.offset>0)
2974 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2975 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2976 UINT16 size;
2978 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2980 char *name;
2982 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2983 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2984 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2986 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2987 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2988 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2989 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2991 size >>= 2;
2992 name = TLB_Alloc(size+1);
2993 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2994 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2995 TLB_Free(name);
2997 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2998 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3000 ppImpLib = &(*ppImpLib)->next;
3004 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3005 if(pTypeLibImpl->dispatch_href != -1)
3006 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3008 /* type info's */
3009 if(tlbHeader.nrtypeinfos >= 0 )
3011 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3012 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3013 int i;
3015 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3017 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3019 ppTI = &((*ppTI)->next);
3020 (pTypeLibImpl->TypeInfoCount)++;
3024 TRACE("(%p)\n", pTypeLibImpl);
3025 return (ITypeLib2*) pTypeLibImpl;
3029 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3031 char b[3];
3032 int i;
3033 short s;
3035 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3036 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3037 return FALSE;
3040 guid->Data4[0] = s >> 8;
3041 guid->Data4[1] = s & 0xff;
3043 b[2] = '\0';
3044 for(i = 0; i < 6; i++) {
3045 memcpy(b, str + 24 + 2 * i, 2);
3046 guid->Data4[i + 2] = strtol(b, NULL, 16);
3048 return TRUE;
3051 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3053 WORD bytelen;
3054 DWORD len;
3056 *pBstr = NULL;
3057 bytelen = *(const WORD*)ptr;
3058 if(bytelen == 0xffff) return 2;
3059 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3060 *pBstr = SysAllocStringLen(NULL, len);
3061 if (*pBstr)
3062 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3063 return bytelen + 2;
3066 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3068 WORD bytelen;
3070 *str = NULL;
3071 bytelen = *(const WORD*)ptr;
3072 if(bytelen == 0xffff) return 2;
3073 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3074 memcpy(*str, ptr + 2, bytelen);
3075 (*str)[bytelen] = '\0';
3076 return bytelen + 2;
3079 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3081 char *ptr = pLibBlk;
3082 WORD w;
3084 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3085 FIXME("libblk magic = %04x\n", w);
3086 return 0;
3089 ptr += 6;
3090 if((w = *(WORD*)ptr) != 0xffff) {
3091 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3092 ptr += w;
3094 ptr += 2;
3096 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3098 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3100 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3101 ptr += 4;
3103 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3104 ptr += 2;
3106 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3107 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3108 else
3109 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3110 ptr += 2;
3112 ptr += 4; /* skip res12 */
3114 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3115 ptr += 2;
3117 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3118 ptr += 2;
3120 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3121 ptr += 2;
3123 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3124 ptr += sizeof(GUID);
3126 return ptr - (char*)pLibBlk;
3129 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3130 typedef struct
3132 unsigned int num;
3133 HREFTYPE refs[1];
3134 } sltg_ref_lookup_t;
3136 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3137 HREFTYPE *typelib_ref)
3139 if(table && typeinfo_ref < table->num)
3141 *typelib_ref = table->refs[typeinfo_ref];
3142 return S_OK;
3145 ERR_(typelib)("Unable to find reference\n");
3146 *typelib_ref = -1;
3147 return E_FAIL;
3150 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3152 BOOL done = FALSE;
3154 while(!done) {
3155 if((*pType & 0xe00) == 0xe00) {
3156 pTD->vt = VT_PTR;
3157 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3158 sizeof(TYPEDESC));
3159 pTD = pTD->u.lptdesc;
3161 switch(*pType & 0x3f) {
3162 case VT_PTR:
3163 pTD->vt = VT_PTR;
3164 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3165 sizeof(TYPEDESC));
3166 pTD = pTD->u.lptdesc;
3167 break;
3169 case VT_USERDEFINED:
3170 pTD->vt = VT_USERDEFINED;
3171 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3172 done = TRUE;
3173 break;
3175 case VT_CARRAY:
3177 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3178 array */
3180 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3182 pTD->vt = VT_CARRAY;
3183 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3184 sizeof(ARRAYDESC) +
3185 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3186 pTD->u.lpadesc->cDims = pSA->cDims;
3187 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3188 pSA->cDims * sizeof(SAFEARRAYBOUND));
3190 pTD = &pTD->u.lpadesc->tdescElem;
3191 break;
3194 case VT_SAFEARRAY:
3196 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3197 useful? */
3199 pType++;
3200 pTD->vt = VT_SAFEARRAY;
3201 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3202 sizeof(TYPEDESC));
3203 pTD = pTD->u.lptdesc;
3204 break;
3206 default:
3207 pTD->vt = *pType & 0x3f;
3208 done = TRUE;
3209 break;
3211 pType++;
3213 return pType;
3216 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3217 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3219 /* Handle [in/out] first */
3220 if((*pType & 0xc000) == 0xc000)
3221 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3222 else if(*pType & 0x8000)
3223 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3224 else if(*pType & 0x4000)
3225 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3226 else
3227 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3229 if(*pType & 0x2000)
3230 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3232 if(*pType & 0x80)
3233 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3235 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3239 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3240 char *pNameTable)
3242 unsigned int ref;
3243 char *name;
3244 TLBRefType *ref_type;
3245 sltg_ref_lookup_t *table;
3246 HREFTYPE typelib_ref;
3248 if(pRef->magic != SLTG_REF_MAGIC) {
3249 FIXME("Ref magic = %x\n", pRef->magic);
3250 return NULL;
3252 name = ( (char*)pRef->names + pRef->number);
3254 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3255 table->num = pRef->number >> 3;
3257 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3259 /* We don't want the first href to be 0 */
3260 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3262 for(ref = 0; ref < pRef->number >> 3; ref++) {
3263 char *refname;
3264 unsigned int lib_offs, type_num;
3266 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3268 name += SLTG_ReadStringA(name, &refname);
3269 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3270 FIXME_(typelib)("Can't sscanf ref\n");
3271 if(lib_offs != 0xffff) {
3272 TLBImpLib **import = &pTL->pImpLibs;
3274 while(*import) {
3275 if((*import)->offset == lib_offs)
3276 break;
3277 import = &(*import)->next;
3279 if(!*import) {
3280 char fname[MAX_PATH+1];
3281 int len;
3283 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3284 sizeof(**import));
3285 (*import)->offset = lib_offs;
3286 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3287 &(*import)->guid);
3288 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3289 &(*import)->wVersionMajor,
3290 &(*import)->wVersionMinor,
3291 &(*import)->lcid, fname) != 4) {
3292 FIXME_(typelib)("can't sscanf ref %s\n",
3293 pNameTable + lib_offs + 40);
3295 len = strlen(fname);
3296 if(fname[len-1] != '#')
3297 FIXME("fname = %s\n", fname);
3298 fname[len-1] = '\0';
3299 (*import)->name = TLB_MultiByteToBSTR(fname);
3301 ref_type->pImpTLInfo = *import;
3303 /* Store a reference to IDispatch */
3304 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3305 pTL->dispatch_href = typelib_ref;
3307 } else { /* internal ref */
3308 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3310 ref_type->reference = typelib_ref;
3311 ref_type->index = type_num;
3313 HeapFree(GetProcessHeap(), 0, refname);
3314 list_add_tail(&pTL->ref_list, &ref_type->entry);
3316 table->refs[ref] = typelib_ref;
3317 typelib_ref += 4;
3319 if((BYTE)*name != SLTG_REF_MAGIC)
3320 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3321 dump_TLBRefType(pTL);
3322 return table;
3325 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3326 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3328 SLTG_ImplInfo *info;
3329 TLBImplType **ppImplType = &pTI->impltypelist;
3330 /* I don't really get this structure, usually it's 0x16 bytes
3331 long, but iuser.tlb contains some that are 0x18 bytes long.
3332 That's ok because we can use the next ptr to jump to the next
3333 one. But how do we know the length of the last one? The WORD
3334 at offs 0x8 might be the clue. For now I'm just assuming that
3335 the last one is the regular 0x16 bytes. */
3337 info = (SLTG_ImplInfo*)pBlk;
3338 while(1) {
3339 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3340 sizeof(**ppImplType));
3341 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3342 (*ppImplType)->implflags = info->impltypeflags;
3343 pTI->TypeAttr.cImplTypes++;
3344 ppImplType = &(*ppImplType)->next;
3346 if(info->next == 0xffff)
3347 break;
3348 if(OneOnly)
3349 FIXME_(typelib)("Interface inheriting more than one interface\n");
3350 info = (SLTG_ImplInfo*)(pBlk + info->next);
3352 info++; /* see comment at top of function */
3353 return (char*)info;
3356 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3357 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3359 TLBVarDesc **ppVarDesc = &pTI->varlist;
3360 BSTR bstrPrevName = NULL;
3361 SLTG_Variable *pItem;
3362 unsigned short i;
3363 WORD *pType;
3365 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3366 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3368 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3369 sizeof(**ppVarDesc));
3370 (*ppVarDesc)->vardesc.memid = pItem->memid;
3372 if (pItem->magic != SLTG_VAR_MAGIC &&
3373 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3374 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3375 return;
3378 if (pItem->name == 0xfffe)
3379 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3380 else
3381 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3383 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3384 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3385 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3387 if(pItem->flags & 0x02)
3388 pType = &pItem->type;
3389 else
3390 pType = (WORD*)(pBlk + pItem->type);
3392 if (pItem->flags & ~0xda)
3393 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3395 SLTG_DoElem(pType, pBlk,
3396 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3398 if (TRACE_ON(typelib)) {
3399 char buf[300];
3400 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3401 TRACE_(typelib)("elemdescVar: %s\n", buf);
3404 if (pItem->flags & 0x40) {
3405 TRACE_(typelib)("VAR_DISPATCH\n");
3406 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3408 else if (pItem->flags & 0x10) {
3409 TRACE_(typelib)("VAR_CONST\n");
3410 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3411 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3412 sizeof(VARIANT));
3413 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3414 if (pItem->flags & 0x08)
3415 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3416 else {
3417 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3419 case VT_LPSTR:
3420 case VT_LPWSTR:
3421 case VT_BSTR:
3423 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3424 BSTR str;
3425 TRACE_(typelib)("len = %u\n", len);
3426 if (len == 0xffff) {
3427 str = NULL;
3428 } else {
3429 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3430 str = SysAllocStringLen(NULL, alloc_len);
3431 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3433 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3434 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3435 break;
3437 case VT_I2:
3438 case VT_UI2:
3439 case VT_I4:
3440 case VT_UI4:
3441 case VT_INT:
3442 case VT_UINT:
3443 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3444 *(INT*)(pBlk + pItem->byte_offs);
3445 break;
3446 default:
3447 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3451 else {
3452 TRACE_(typelib)("VAR_PERINSTANCE\n");
3453 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3454 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3457 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3458 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3460 if (pItem->flags & 0x80)
3461 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3463 bstrPrevName = (*ppVarDesc)->Name;
3464 ppVarDesc = &((*ppVarDesc)->next);
3466 pTI->TypeAttr.cVars = cVars;
3469 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3470 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3472 SLTG_Function *pFunc;
3473 unsigned short i;
3474 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3476 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3477 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3479 int param;
3480 WORD *pType, *pArg;
3482 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3483 sizeof(**ppFuncDesc));
3485 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3486 case SLTG_FUNCTION_MAGIC:
3487 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3488 break;
3489 case SLTG_DISPATCH_FUNCTION_MAGIC:
3490 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3491 break;
3492 case SLTG_STATIC_FUNCTION_MAGIC:
3493 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3494 break;
3495 default:
3496 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3497 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3498 *ppFuncDesc = NULL;
3499 return;
3501 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3503 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3504 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3505 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3506 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3507 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3508 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3510 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3511 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3513 if(pFunc->retnextopt & 0x80)
3514 pType = &pFunc->rettype;
3515 else
3516 pType = (WORD*)(pBlk + pFunc->rettype);
3518 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3520 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3521 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3522 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3523 (*ppFuncDesc)->pParamDesc =
3524 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3525 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3527 pArg = (WORD*)(pBlk + pFunc->arg_off);
3529 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3530 char *paramName = pNameTable + *pArg;
3531 BOOL HaveOffs;
3532 /* If arg type follows then paramName points to the 2nd
3533 letter of the name, else the next WORD is an offset to
3534 the arg type and paramName points to the first letter.
3535 So let's take one char off paramName and see if we're
3536 pointing at an alpha-numeric char. However if *pArg is
3537 0xffff or 0xfffe then the param has no name, the former
3538 meaning that the next WORD is the type, the latter
3539 meaning that the next WORD is an offset to the type. */
3541 HaveOffs = FALSE;
3542 if(*pArg == 0xffff)
3543 paramName = NULL;
3544 else if(*pArg == 0xfffe) {
3545 paramName = NULL;
3546 HaveOffs = TRUE;
3548 else if(paramName[-1] && !isalnum(paramName[-1]))
3549 HaveOffs = TRUE;
3551 pArg++;
3553 if(HaveOffs) { /* the next word is an offset to type */
3554 pType = (WORD*)(pBlk + *pArg);
3555 SLTG_DoElem(pType, pBlk,
3556 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3557 pArg++;
3558 } else {
3559 if(paramName)
3560 paramName--;
3561 pArg = SLTG_DoElem(pArg, pBlk,
3562 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3565 /* Are we an optional param ? */
3566 if((*ppFuncDesc)->funcdesc.cParams - param <=
3567 (*ppFuncDesc)->funcdesc.cParamsOpt)
3568 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3570 if(paramName) {
3571 (*ppFuncDesc)->pParamDesc[param].Name =
3572 TLB_MultiByteToBSTR(paramName);
3573 } else {
3574 (*ppFuncDesc)->pParamDesc[param].Name =
3575 SysAllocString((*ppFuncDesc)->Name);
3579 ppFuncDesc = &((*ppFuncDesc)->next);
3580 if(pFunc->next == 0xffff) break;
3582 pTI->TypeAttr.cFuncs = cFuncs;
3585 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3586 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3587 SLTG_TypeInfoTail *pTITail)
3589 char *pFirstItem;
3590 sltg_ref_lookup_t *ref_lookup = NULL;
3592 if(pTIHeader->href_table != 0xffffffff) {
3593 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3594 pNameTable);
3597 pFirstItem = pBlk;
3599 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3600 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3602 HeapFree(GetProcessHeap(), 0, ref_lookup);
3606 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3607 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3608 const SLTG_TypeInfoTail *pTITail)
3610 char *pFirstItem;
3611 sltg_ref_lookup_t *ref_lookup = NULL;
3613 if(pTIHeader->href_table != 0xffffffff) {
3614 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3615 pNameTable);
3618 pFirstItem = pBlk;
3620 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3621 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3624 if (pTITail->funcs_off != 0xffff)
3625 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3627 HeapFree(GetProcessHeap(), 0, ref_lookup);
3629 if (TRACE_ON(typelib))
3630 dump_TLBFuncDesc(pTI->funclist);
3633 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3634 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3635 const SLTG_TypeInfoTail *pTITail)
3637 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3640 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3641 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3642 const SLTG_TypeInfoTail *pTITail)
3644 WORD *pType;
3645 sltg_ref_lookup_t *ref_lookup = NULL;
3647 if (pTITail->simple_alias) {
3648 /* if simple alias, no more processing required */
3649 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3650 return;
3653 if(pTIHeader->href_table != 0xffffffff) {
3654 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3655 pNameTable);
3658 /* otherwise it is an offset to a type */
3659 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3661 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3663 HeapFree(GetProcessHeap(), 0, ref_lookup);
3666 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3667 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3668 const SLTG_TypeInfoTail *pTITail)
3670 sltg_ref_lookup_t *ref_lookup = NULL;
3671 if (pTIHeader->href_table != 0xffffffff)
3672 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3673 pNameTable);
3675 if (pTITail->vars_off != 0xffff)
3676 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3678 if (pTITail->funcs_off != 0xffff)
3679 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3681 if (pTITail->impls_off != 0xffff)
3682 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3684 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3685 * of dispinterface functions including the IDispatch ones, so
3686 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3687 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3689 HeapFree(GetProcessHeap(), 0, ref_lookup);
3690 if (TRACE_ON(typelib))
3691 dump_TLBFuncDesc(pTI->funclist);
3694 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3695 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3696 const SLTG_TypeInfoTail *pTITail)
3698 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3701 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3702 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3703 const SLTG_TypeInfoTail *pTITail)
3705 sltg_ref_lookup_t *ref_lookup = NULL;
3706 if (pTIHeader->href_table != 0xffffffff)
3707 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3708 pNameTable);
3710 if (pTITail->vars_off != 0xffff)
3711 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3713 if (pTITail->funcs_off != 0xffff)
3714 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3715 HeapFree(GetProcessHeap(), 0, ref_lookup);
3716 if (TRACE_ON(typelib))
3717 dump_TypeInfo(pTI);
3720 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3721 managable copy of it into this */
3722 typedef struct {
3723 WORD small_no;
3724 char *index_name;
3725 char *other_name;
3726 WORD res1a;
3727 WORD name_offs;
3728 WORD more_bytes;
3729 char *extra;
3730 WORD res20;
3731 DWORD helpcontext;
3732 WORD res26;
3733 GUID uuid;
3734 } SLTG_InternalOtherTypeInfo;
3736 /****************************************************************************
3737 * ITypeLib2_Constructor_SLTG
3739 * loading a SLTG typelib from an in-memory image
3741 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3743 ITypeLibImpl *pTypeLibImpl;
3744 SLTG_Header *pHeader;
3745 SLTG_BlkEntry *pBlkEntry;
3746 SLTG_Magic *pMagic;
3747 SLTG_Index *pIndex;
3748 SLTG_Pad9 *pPad9;
3749 LPVOID pBlk, pFirstBlk;
3750 SLTG_LibBlk *pLibBlk;
3751 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3752 char *pAfterOTIBlks = NULL;
3753 char *pNameTable, *ptr;
3754 int i;
3755 DWORD len, order;
3756 ITypeInfoImpl **ppTypeInfoImpl;
3758 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3761 pTypeLibImpl = TypeLibImpl_Constructor();
3762 if (!pTypeLibImpl) return NULL;
3764 pHeader = pLib;
3766 TRACE_(typelib)("header:\n");
3767 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3768 pHeader->nrOfFileBlks );
3769 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3770 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3771 pHeader->SLTG_magic);
3772 return NULL;
3775 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3776 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3778 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3779 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3781 /* Next we have a magic block */
3782 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3784 /* Let's see if we're still in sync */
3785 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3786 sizeof(SLTG_COMPOBJ_MAGIC))) {
3787 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3788 return NULL;
3790 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3791 sizeof(SLTG_DIR_MAGIC))) {
3792 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3793 return NULL;
3796 pIndex = (SLTG_Index*)(pMagic+1);
3798 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3800 pFirstBlk = pPad9 + 1;
3802 /* We'll set up a ptr to the main library block, which is the last one. */
3804 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3805 pBlkEntry[order].next != 0;
3806 order = pBlkEntry[order].next - 1, i++) {
3807 pBlk = (char*)pBlk + pBlkEntry[order].len;
3809 pLibBlk = pBlk;
3811 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3813 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3814 interspersed */
3816 len += 0x40;
3818 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3820 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3821 sizeof(*pOtherTypeInfoBlks) *
3822 pTypeLibImpl->TypeInfoCount);
3825 ptr = (char*)pLibBlk + len;
3827 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3828 WORD w, extra;
3829 len = 0;
3831 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3833 w = *(WORD*)(ptr + 2);
3834 if(w != 0xffff) {
3835 len += w;
3836 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3837 w+1);
3838 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3839 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3841 w = *(WORD*)(ptr + 4 + len);
3842 if(w != 0xffff) {
3843 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3844 len += w;
3845 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3846 w+1);
3847 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3848 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3850 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3851 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3852 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3853 if(extra) {
3854 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3855 extra);
3856 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3857 len += extra;
3859 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3860 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3861 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3862 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3863 len += sizeof(SLTG_OtherTypeInfo);
3864 ptr += len;
3867 pAfterOTIBlks = ptr;
3869 /* Skip this WORD and get the next DWORD */
3870 len = *(DWORD*)(pAfterOTIBlks + 2);
3872 /* Now add this to pLibBLk look at what we're pointing at and
3873 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3874 dust and we should be pointing at the beginning of the name
3875 table */
3877 pNameTable = (char*)pLibBlk + len;
3879 switch(*(WORD*)pNameTable) {
3880 case 0xffff:
3881 break;
3882 case 0x0200:
3883 pNameTable += 0x20;
3884 break;
3885 default:
3886 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3887 break;
3890 pNameTable += 0x216;
3892 pNameTable += 2;
3894 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3896 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3899 /* Hopefully we now have enough ptrs set up to actually read in
3900 some TypeInfos. It's not clear which order to do them in, so
3901 I'll just follow the links along the BlkEntry chain and read
3902 them in the order in which they are in the file */
3904 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3906 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3907 pBlkEntry[order].next != 0;
3908 order = pBlkEntry[order].next - 1, i++) {
3910 SLTG_TypeInfoHeader *pTIHeader;
3911 SLTG_TypeInfoTail *pTITail;
3912 SLTG_MemberHeader *pMemHeader;
3914 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3915 pOtherTypeInfoBlks[i].index_name)) {
3916 FIXME_(typelib)("Index strings don't match\n");
3917 return NULL;
3920 pTIHeader = pBlk;
3921 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3922 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3923 return NULL;
3925 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3926 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3927 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3929 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3930 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3931 (*ppTypeInfoImpl)->index = i;
3932 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3933 pOtherTypeInfoBlks[i].name_offs +
3934 pNameTable);
3935 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3936 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3937 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3938 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3939 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3940 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3941 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3943 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3944 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3946 if((pTIHeader->typeflags1 & 7) != 2)
3947 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3948 if(pTIHeader->typeflags3 != 2)
3949 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3951 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3952 debugstr_w((*ppTypeInfoImpl)->Name),
3953 typekind_desc[pTIHeader->typekind],
3954 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3955 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3957 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3959 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3961 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3962 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3963 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3965 switch(pTIHeader->typekind) {
3966 case TKIND_ENUM:
3967 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3968 pTIHeader, pTITail);
3969 break;
3971 case TKIND_RECORD:
3972 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3973 pTIHeader, pTITail);
3974 break;
3976 case TKIND_INTERFACE:
3977 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3978 pTIHeader, pTITail);
3979 break;
3981 case TKIND_COCLASS:
3982 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3983 pTIHeader, pTITail);
3984 break;
3986 case TKIND_ALIAS:
3987 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3988 pTIHeader, pTITail);
3989 break;
3991 case TKIND_DISPATCH:
3992 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3993 pTIHeader, pTITail);
3994 break;
3996 case TKIND_MODULE:
3997 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3998 pTIHeader, pTITail);
3999 break;
4001 default:
4002 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4003 break;
4007 /* could get cFuncs, cVars and cImplTypes from here
4008 but we've already set those */
4009 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4010 X(06);
4011 X(16);
4012 X(18);
4013 X(1a);
4014 X(1e);
4015 X(24);
4016 X(26);
4017 X(2a);
4018 X(2c);
4019 X(2e);
4020 X(30);
4021 X(32);
4022 X(34);
4023 #undef X
4024 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4025 pBlk = (char*)pBlk + pBlkEntry[order].len;
4028 if(i != pTypeLibImpl->TypeInfoCount) {
4029 FIXME("Somehow processed %d TypeInfos\n", i);
4030 return NULL;
4033 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4034 return (ITypeLib2*)pTypeLibImpl;
4037 /* ITypeLib::QueryInterface
4039 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4040 ITypeLib2 * iface,
4041 REFIID riid,
4042 VOID **ppvObject)
4044 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4046 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4048 *ppvObject=NULL;
4049 if(IsEqualIID(riid, &IID_IUnknown) ||
4050 IsEqualIID(riid,&IID_ITypeLib)||
4051 IsEqualIID(riid,&IID_ITypeLib2))
4053 *ppvObject = This;
4056 if(*ppvObject)
4058 ITypeLib2_AddRef(iface);
4059 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4060 return S_OK;
4062 TRACE("-- Interface: E_NOINTERFACE\n");
4063 return E_NOINTERFACE;
4066 /* ITypeLib::AddRef
4068 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4070 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4071 ULONG ref = InterlockedIncrement(&This->ref);
4073 TRACE("(%p)->ref was %u\n",This, ref - 1);
4075 return ref;
4078 /* ITypeLib::Release
4080 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4082 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4083 ULONG ref = InterlockedDecrement(&This->ref);
4085 TRACE("(%p)->(%u)\n",This, ref);
4087 if (!ref)
4089 TLBImpLib *pImpLib, *pImpLibNext;
4090 TLBCustData *pCustData, *pCustDataNext;
4091 TLBRefType *ref_type;
4092 void *cursor2;
4093 int i;
4094 ITypeInfoImpl *pTI, *pTINext;
4096 /* remove cache entry */
4097 if(This->path)
4099 TRACE("removing from cache list\n");
4100 EnterCriticalSection(&cache_section);
4101 if (This->next) This->next->prev = This->prev;
4102 if (This->prev) This->prev->next = This->next;
4103 else tlb_cache_first = This->next;
4104 LeaveCriticalSection(&cache_section);
4105 HeapFree(GetProcessHeap(), 0, This->path);
4107 TRACE(" destroying ITypeLib(%p)\n",This);
4109 SysFreeString(This->Name);
4110 This->Name = NULL;
4112 SysFreeString(This->DocString);
4113 This->DocString = NULL;
4115 SysFreeString(This->HelpFile);
4116 This->HelpFile = NULL;
4118 SysFreeString(This->HelpStringDll);
4119 This->HelpStringDll = NULL;
4121 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4123 VariantClear(&pCustData->data);
4125 pCustDataNext = pCustData->next;
4126 TLB_Free(pCustData);
4129 for (i = 0; i < This->ctTypeDesc; i++)
4130 if (This->pTypeDesc[i].vt == VT_CARRAY)
4131 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4133 TLB_Free(This->pTypeDesc);
4135 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4137 if (pImpLib->pImpTypeLib)
4138 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4139 SysFreeString(pImpLib->name);
4141 pImpLibNext = pImpLib->next;
4142 TLB_Free(pImpLib);
4145 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4147 list_remove(&ref_type->entry);
4148 TLB_Free(ref_type);
4151 for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
4153 pTINext = pTI->next;
4154 ITypeInfo_fnDestroy(pTI);
4156 HeapFree(GetProcessHeap(),0,This);
4157 return 0;
4160 return ref;
4163 /* ITypeLib::GetTypeInfoCount
4165 * Returns the number of type descriptions in the type library
4167 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4169 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4170 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4171 return This->TypeInfoCount;
4174 /* ITypeLib::GetTypeInfo
4176 * retrieves the specified type description in the library.
4178 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4179 ITypeLib2 *iface,
4180 UINT index,
4181 ITypeInfo **ppTInfo)
4183 UINT i;
4185 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4186 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4188 TRACE("(%p)->(index=%d)\n", This, index);
4190 if (!ppTInfo) return E_INVALIDARG;
4192 /* search element n in list */
4193 for(i=0; i < index; i++)
4195 pTypeInfo = pTypeInfo->next;
4196 if (!pTypeInfo)
4198 TRACE("-- element not found\n");
4199 return TYPE_E_ELEMENTNOTFOUND;
4203 *ppTInfo = (ITypeInfo *) pTypeInfo;
4205 ITypeInfo_AddRef(*ppTInfo);
4206 TRACE("-- found (%p)\n",*ppTInfo);
4207 return S_OK;
4211 /* ITypeLibs::GetTypeInfoType
4213 * Retrieves the type of a type description.
4215 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4216 ITypeLib2 *iface,
4217 UINT index,
4218 TYPEKIND *pTKind)
4220 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4221 UINT i;
4222 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4224 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4225 return TYPE_E_ELEMENTNOTFOUND;
4227 TRACE("(%p) index %d\n", This, index);
4229 if(!pTKind) return E_INVALIDARG;
4231 /* search element n in list */
4232 for(i=0; i < index; i++)
4234 if(!pTInfo)
4236 TRACE("-- element not found\n");
4237 return TYPE_E_ELEMENTNOTFOUND;
4239 pTInfo = pTInfo->next;
4242 *pTKind = pTInfo->TypeAttr.typekind;
4243 TRACE("-- found Type (%d)\n", *pTKind);
4244 return S_OK;
4247 /* ITypeLib::GetTypeInfoOfGuid
4249 * Retrieves the type description that corresponds to the specified GUID.
4252 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4253 ITypeLib2 *iface,
4254 REFGUID guid,
4255 ITypeInfo **ppTInfo)
4257 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4258 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4260 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4262 if (!pTypeInfo)
4264 WARN("-- element not found\n");
4265 return TYPE_E_ELEMENTNOTFOUND;
4268 /* search linked list for guid */
4269 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4271 pTypeInfo = pTypeInfo->next;
4273 if (!pTypeInfo)
4275 /* end of list reached */
4276 WARN("-- element not found\n");
4277 return TYPE_E_ELEMENTNOTFOUND;
4281 TRACE("-- found (%p, %s)\n",
4282 pTypeInfo,
4283 debugstr_w(pTypeInfo->Name));
4285 *ppTInfo = (ITypeInfo*)pTypeInfo;
4286 ITypeInfo_AddRef(*ppTInfo);
4287 return S_OK;
4290 /* ITypeLib::GetLibAttr
4292 * Retrieves the structure that contains the library's attributes.
4295 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4296 ITypeLib2 *iface,
4297 LPTLIBATTR *ppTLibAttr)
4299 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4300 TRACE("(%p)\n",This);
4301 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4302 **ppTLibAttr = This->LibAttr;
4303 return S_OK;
4306 /* ITypeLib::GetTypeComp
4308 * Enables a client compiler to bind to a library's types, variables,
4309 * constants, and global functions.
4312 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4313 ITypeLib2 *iface,
4314 ITypeComp **ppTComp)
4316 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4318 TRACE("(%p)->(%p)\n",This,ppTComp);
4319 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4320 ITypeComp_AddRef(*ppTComp);
4322 return S_OK;
4325 /* ITypeLib::GetDocumentation
4327 * Retrieves the library's documentation string, the complete Help file name
4328 * and path, and the context identifier for the library Help topic in the Help
4329 * file.
4331 * On a successful return all non-null BSTR pointers will have been set,
4332 * possibly to NULL.
4334 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4335 ITypeLib2 *iface,
4336 INT index,
4337 BSTR *pBstrName,
4338 BSTR *pBstrDocString,
4339 DWORD *pdwHelpContext,
4340 BSTR *pBstrHelpFile)
4342 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4344 HRESULT result = E_INVALIDARG;
4346 ITypeInfo *pTInfo;
4349 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4350 This, index,
4351 pBstrName, pBstrDocString,
4352 pdwHelpContext, pBstrHelpFile);
4354 if(index<0)
4356 /* documentation for the typelib */
4357 if(pBstrName)
4359 if (This->Name)
4361 if(!(*pBstrName = SysAllocString(This->Name)))
4362 goto memerr1;
4364 else
4365 *pBstrName = NULL;
4367 if(pBstrDocString)
4369 if (This->DocString)
4371 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4372 goto memerr2;
4374 else if (This->Name)
4376 if(!(*pBstrDocString = SysAllocString(This->Name)))
4377 goto memerr2;
4379 else
4380 *pBstrDocString = NULL;
4382 if(pdwHelpContext)
4384 *pdwHelpContext = This->dwHelpContext;
4386 if(pBstrHelpFile)
4388 if (This->HelpFile)
4390 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4391 goto memerr3;
4393 else
4394 *pBstrHelpFile = NULL;
4397 result = S_OK;
4399 else
4401 /* for a typeinfo */
4402 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4404 if(SUCCEEDED(result))
4406 result = ITypeInfo_GetDocumentation(pTInfo,
4407 MEMBERID_NIL,
4408 pBstrName,
4409 pBstrDocString,
4410 pdwHelpContext, pBstrHelpFile);
4412 ITypeInfo_Release(pTInfo);
4415 return result;
4416 memerr3:
4417 if (pBstrDocString) SysFreeString (*pBstrDocString);
4418 memerr2:
4419 if (pBstrName) SysFreeString (*pBstrName);
4420 memerr1:
4421 return STG_E_INSUFFICIENTMEMORY;
4424 /* ITypeLib::IsName
4426 * Indicates whether a passed-in string contains the name of a type or member
4427 * described in the library.
4430 static HRESULT WINAPI ITypeLib2_fnIsName(
4431 ITypeLib2 *iface,
4432 LPOLESTR szNameBuf,
4433 ULONG lHashVal,
4434 BOOL *pfName)
4436 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4437 ITypeInfoImpl *pTInfo;
4438 TLBFuncDesc *pFInfo;
4439 TLBVarDesc *pVInfo;
4440 int i;
4441 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4443 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4444 pfName);
4446 *pfName=TRUE;
4447 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4448 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4449 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4450 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4451 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4452 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4453 goto ITypeLib2_fnIsName_exit;
4455 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4456 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4459 *pfName=FALSE;
4461 ITypeLib2_fnIsName_exit:
4462 TRACE("(%p)slow! search for %s: %s found!\n", This,
4463 debugstr_w(szNameBuf), *pfName?"NOT":"");
4465 return S_OK;
4468 /* ITypeLib::FindName
4470 * Finds occurrences of a type description in a type library. This may be used
4471 * to quickly verify that a name exists in a type library.
4474 static HRESULT WINAPI ITypeLib2_fnFindName(
4475 ITypeLib2 *iface,
4476 LPOLESTR szNameBuf,
4477 ULONG lHashVal,
4478 ITypeInfo **ppTInfo,
4479 MEMBERID *rgMemId,
4480 UINT16 *pcFound)
4482 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4483 ITypeInfoImpl *pTInfo;
4484 TLBFuncDesc *pFInfo;
4485 TLBVarDesc *pVInfo;
4486 int i,j = 0;
4487 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4489 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4490 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4491 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4492 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4493 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4494 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4495 goto ITypeLib2_fnFindName_exit;
4498 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4499 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4500 continue;
4501 ITypeLib2_fnFindName_exit:
4502 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4503 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4504 j++;
4506 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4507 This, *pcFound, debugstr_w(szNameBuf), j);
4509 *pcFound=j;
4511 return S_OK;
4514 /* ITypeLib::ReleaseTLibAttr
4516 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4519 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4520 ITypeLib2 *iface,
4521 TLIBATTR *pTLibAttr)
4523 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4524 TRACE("freeing (%p)\n",This);
4525 HeapFree(GetProcessHeap(),0,pTLibAttr);
4529 /* ITypeLib2::GetCustData
4531 * gets the custom data
4533 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4534 ITypeLib2 * iface,
4535 REFGUID guid,
4536 VARIANT *pVarVal)
4538 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4539 TLBCustData *pCData;
4541 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4543 if( IsEqualIID(guid, &pCData->guid)) break;
4546 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4548 if(pCData)
4550 VariantInit( pVarVal);
4551 VariantCopy( pVarVal, &pCData->data);
4552 return S_OK;
4554 return E_INVALIDARG; /* FIXME: correct? */
4557 /* ITypeLib2::GetLibStatistics
4559 * Returns statistics about a type library that are required for efficient
4560 * sizing of hash tables.
4563 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4564 ITypeLib2 * iface,
4565 ULONG *pcUniqueNames,
4566 ULONG *pcchUniqueNames)
4568 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4570 FIXME("(%p): stub!\n", This);
4572 if(pcUniqueNames) *pcUniqueNames=1;
4573 if(pcchUniqueNames) *pcchUniqueNames=1;
4574 return S_OK;
4577 /* ITypeLib2::GetDocumentation2
4579 * Retrieves the library's documentation string, the complete Help file name
4580 * and path, the localization context to use, and the context ID for the
4581 * library Help topic in the Help file.
4584 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4585 ITypeLib2 * iface,
4586 INT index,
4587 LCID lcid,
4588 BSTR *pbstrHelpString,
4589 DWORD *pdwHelpStringContext,
4590 BSTR *pbstrHelpStringDll)
4592 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4593 HRESULT result;
4594 ITypeInfo *pTInfo;
4596 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4598 /* the help string should be obtained from the helpstringdll,
4599 * using the _DLLGetDocumentation function, based on the supplied
4600 * lcid. Nice to do sometime...
4602 if(index<0)
4604 /* documentation for the typelib */
4605 if(pbstrHelpString)
4606 *pbstrHelpString=SysAllocString(This->DocString);
4607 if(pdwHelpStringContext)
4608 *pdwHelpStringContext=This->dwHelpContext;
4609 if(pbstrHelpStringDll)
4610 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4612 result = S_OK;
4614 else
4616 /* for a typeinfo */
4617 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4619 if(SUCCEEDED(result))
4621 ITypeInfo2 * pTInfo2;
4622 result = ITypeInfo_QueryInterface(pTInfo,
4623 &IID_ITypeInfo2,
4624 (LPVOID*) &pTInfo2);
4626 if(SUCCEEDED(result))
4628 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4629 MEMBERID_NIL,
4630 lcid,
4631 pbstrHelpString,
4632 pdwHelpStringContext,
4633 pbstrHelpStringDll);
4635 ITypeInfo2_Release(pTInfo2);
4638 ITypeInfo_Release(pTInfo);
4641 return result;
4644 /* ITypeLib2::GetAllCustData
4646 * Gets all custom data items for the library.
4649 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4650 ITypeLib2 * iface,
4651 CUSTDATA *pCustData)
4653 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4654 TLBCustData *pCData;
4655 int i;
4656 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4657 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4658 if(pCustData->prgCustData ){
4659 pCustData->cCustData=This->ctCustData;
4660 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4661 pCustData->prgCustData[i].guid=pCData->guid;
4662 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4664 }else{
4665 ERR(" OUT OF MEMORY!\n");
4666 return E_OUTOFMEMORY;
4668 return S_OK;
4671 static const ITypeLib2Vtbl tlbvt = {
4672 ITypeLib2_fnQueryInterface,
4673 ITypeLib2_fnAddRef,
4674 ITypeLib2_fnRelease,
4675 ITypeLib2_fnGetTypeInfoCount,
4676 ITypeLib2_fnGetTypeInfo,
4677 ITypeLib2_fnGetTypeInfoType,
4678 ITypeLib2_fnGetTypeInfoOfGuid,
4679 ITypeLib2_fnGetLibAttr,
4680 ITypeLib2_fnGetTypeComp,
4681 ITypeLib2_fnGetDocumentation,
4682 ITypeLib2_fnIsName,
4683 ITypeLib2_fnFindName,
4684 ITypeLib2_fnReleaseTLibAttr,
4686 ITypeLib2_fnGetCustData,
4687 ITypeLib2_fnGetLibStatistics,
4688 ITypeLib2_fnGetDocumentation2,
4689 ITypeLib2_fnGetAllCustData
4693 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4695 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4697 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4700 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4702 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4704 return ITypeLib2_AddRef((ITypeLib2 *)This);
4707 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4709 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4711 return ITypeLib2_Release((ITypeLib2 *)This);
4714 static HRESULT WINAPI ITypeLibComp_fnBind(
4715 ITypeComp * iface,
4716 OLECHAR * szName,
4717 ULONG lHash,
4718 WORD wFlags,
4719 ITypeInfo ** ppTInfo,
4720 DESCKIND * pDescKind,
4721 BINDPTR * pBindPtr)
4723 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4724 ITypeInfoImpl *pTypeInfo;
4725 int typemismatch=0;
4727 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4729 *pDescKind = DESCKIND_NONE;
4730 pBindPtr->lptcomp = NULL;
4731 *ppTInfo = NULL;
4733 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4735 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4737 /* FIXME: check wFlags here? */
4738 /* FIXME: we should use a hash table to look this info up using lHash
4739 * instead of an O(n) search */
4740 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4741 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4743 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4745 *pDescKind = DESCKIND_TYPECOMP;
4746 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4747 ITypeComp_AddRef(pBindPtr->lptcomp);
4748 TRACE("module or enum: %s\n", debugstr_w(szName));
4749 return S_OK;
4753 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4754 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4756 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4757 HRESULT hr;
4759 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4760 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4762 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4763 return S_OK;
4765 else if (hr == TYPE_E_TYPEMISMATCH)
4766 typemismatch = 1;
4769 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4770 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4772 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4773 HRESULT hr;
4774 ITypeInfo *subtypeinfo;
4775 BINDPTR subbindptr;
4776 DESCKIND subdesckind;
4778 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4779 &subtypeinfo, &subdesckind, &subbindptr);
4780 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4782 TYPEDESC tdesc_appobject =
4785 (TYPEDESC *)pTypeInfo->hreftype
4787 VT_USERDEFINED
4789 const VARDESC vardesc_appobject =
4791 -2, /* memid */
4792 NULL, /* lpstrSchema */
4794 0 /* oInst */
4797 /* ELEMDESC */
4799 /* TYPEDESC */
4801 &tdesc_appobject
4803 VT_PTR
4806 0, /* wVarFlags */
4807 VAR_STATIC /* varkind */
4810 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4812 /* cleanup things filled in by Bind call so we can put our
4813 * application object data in there instead */
4814 switch (subdesckind)
4816 case DESCKIND_FUNCDESC:
4817 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4818 break;
4819 case DESCKIND_VARDESC:
4820 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4821 break;
4822 default:
4823 break;
4825 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4827 if (pTypeInfo->hreftype == -1)
4828 FIXME("no hreftype for interface %p\n", pTypeInfo);
4830 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4831 if (FAILED(hr))
4832 return hr;
4834 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4835 *ppTInfo = (ITypeInfo *)pTypeInfo;
4836 ITypeInfo_AddRef(*ppTInfo);
4837 return S_OK;
4839 else if (hr == TYPE_E_TYPEMISMATCH)
4840 typemismatch = 1;
4844 if (typemismatch)
4846 TRACE("type mismatch %s\n", debugstr_w(szName));
4847 return TYPE_E_TYPEMISMATCH;
4849 else
4851 TRACE("name not found %s\n", debugstr_w(szName));
4852 return S_OK;
4856 static HRESULT WINAPI ITypeLibComp_fnBindType(
4857 ITypeComp * iface,
4858 OLECHAR * szName,
4859 ULONG lHash,
4860 ITypeInfo ** ppTInfo,
4861 ITypeComp ** ppTComp)
4863 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4864 ITypeInfoImpl *pTypeInfo;
4866 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4868 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4870 /* FIXME: should use lHash to do the search */
4871 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4873 TRACE("returning %p\n", pTypeInfo);
4874 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4875 ITypeInfo_AddRef(*ppTInfo);
4876 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4877 ITypeComp_AddRef(*ppTComp);
4878 return S_OK;
4882 TRACE("not found\n");
4883 *ppTInfo = NULL;
4884 *ppTComp = NULL;
4885 return S_OK;
4888 static const ITypeCompVtbl tlbtcvt =
4891 ITypeLibComp_fnQueryInterface,
4892 ITypeLibComp_fnAddRef,
4893 ITypeLibComp_fnRelease,
4895 ITypeLibComp_fnBind,
4896 ITypeLibComp_fnBindType
4899 /*================== ITypeInfo(2) Methods ===================================*/
4900 static ITypeInfo2 * ITypeInfo_Constructor(void)
4902 ITypeInfoImpl * pTypeInfoImpl;
4904 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4905 if (pTypeInfoImpl)
4907 pTypeInfoImpl->lpVtbl = &tinfvt;
4908 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4909 pTypeInfoImpl->ref = 0;
4910 pTypeInfoImpl->hreftype = -1;
4911 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4912 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4914 TRACE("(%p)\n", pTypeInfoImpl);
4915 return (ITypeInfo2*) pTypeInfoImpl;
4918 /* ITypeInfo::QueryInterface
4920 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4921 ITypeInfo2 *iface,
4922 REFIID riid,
4923 VOID **ppvObject)
4925 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4927 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4929 *ppvObject=NULL;
4930 if(IsEqualIID(riid, &IID_IUnknown) ||
4931 IsEqualIID(riid,&IID_ITypeInfo)||
4932 IsEqualIID(riid,&IID_ITypeInfo2))
4933 *ppvObject = This;
4935 if(*ppvObject){
4936 ITypeInfo_AddRef(iface);
4937 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4938 return S_OK;
4940 TRACE("-- Interface: E_NOINTERFACE\n");
4941 return E_NOINTERFACE;
4944 /* ITypeInfo::AddRef
4946 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4948 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4949 ULONG ref = InterlockedIncrement(&This->ref);
4951 TRACE("(%p)->ref is %u\n",This, ref);
4953 if (ref == 1 /* incremented from 0 */)
4954 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4956 return ref;
4959 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This)
4961 TLBFuncDesc *pFInfo, *pFInfoNext;
4962 TLBVarDesc *pVInfo, *pVInfoNext;
4963 TLBImplType *pImpl, *pImplNext;
4965 TRACE("destroying ITypeInfo(%p)\n",This);
4967 SysFreeString(This->Name);
4968 This->Name = NULL;
4970 SysFreeString(This->DocString);
4971 This->DocString = NULL;
4973 SysFreeString(This->DllName);
4974 This->DllName = NULL;
4976 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4978 INT i;
4979 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4981 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4982 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4984 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4985 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4987 SysFreeString(pFInfo->pParamDesc[i].Name);
4989 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4990 TLB_Free(pFInfo->pParamDesc);
4991 TLB_FreeCustData(pFInfo->pCustData);
4992 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
4993 SysFreeString(pFInfo->Entry);
4994 SysFreeString(pFInfo->HelpString);
4995 SysFreeString(pFInfo->Name);
4997 pFInfoNext = pFInfo->next;
4998 TLB_Free(pFInfo);
5000 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5002 if (pVInfo->vardesc.varkind == VAR_CONST)
5004 VariantClear(pVInfo->vardesc.u.lpvarValue);
5005 TLB_Free(pVInfo->vardesc.u.lpvarValue);
5007 TLB_FreeCustData(pVInfo->pCustData);
5008 SysFreeString(pVInfo->Name);
5009 pVInfoNext = pVInfo->next;
5010 TLB_Free(pVInfo);
5012 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5014 TLB_FreeCustData(pImpl->pCustData);
5015 pImplNext = pImpl->next;
5016 TLB_Free(pImpl);
5018 TLB_FreeCustData(This->pCustData);
5020 HeapFree(GetProcessHeap(), 0, This);
5023 /* ITypeInfo::Release
5025 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5027 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5028 ULONG ref = InterlockedDecrement(&This->ref);
5030 TRACE("(%p)->(%u)\n",This, ref);
5032 if (!ref)
5034 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5035 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5036 if (not_attached_to_typelib)
5037 HeapFree(GetProcessHeap(), 0, This);
5038 /* otherwise This will be freed when typelib is freed */
5041 return ref;
5044 /* ITypeInfo::GetTypeAttr
5046 * Retrieves a TYPEATTR structure that contains the attributes of the type
5047 * description.
5050 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5051 LPTYPEATTR *ppTypeAttr)
5053 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5054 SIZE_T size;
5056 TRACE("(%p)\n",This);
5058 size = sizeof(**ppTypeAttr);
5059 if (This->TypeAttr.typekind == TKIND_ALIAS)
5060 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5062 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5063 if (!*ppTypeAttr)
5064 return E_OUTOFMEMORY;
5066 **ppTypeAttr = This->TypeAttr;
5068 if (This->TypeAttr.typekind == TKIND_ALIAS)
5069 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5070 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5072 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5073 /* This should include all the inherited funcs */
5074 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5075 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5076 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5078 return S_OK;
5081 /* ITypeInfo::GetTypeComp
5083 * Retrieves the ITypeComp interface for the type description, which enables a
5084 * client compiler to bind to the type description's members.
5087 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5088 ITypeComp * *ppTComp)
5090 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5092 TRACE("(%p)->(%p)\n", This, ppTComp);
5094 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5095 ITypeComp_AddRef(*ppTComp);
5096 return S_OK;
5099 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5101 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5102 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5103 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5104 return size;
5107 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5109 *dest = *src;
5110 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5111 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5113 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5114 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5115 *buffer += sizeof(PARAMDESCEX);
5116 *pparamdescex_dest = *pparamdescex_src;
5117 VariantInit(&pparamdescex_dest->varDefaultValue);
5118 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5119 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5121 else
5122 dest->u.paramdesc.pparamdescex = NULL;
5123 return S_OK;
5126 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5128 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5129 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5132 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5134 FUNCDESC *dest;
5135 char *buffer;
5136 SIZE_T size = sizeof(*src);
5137 SHORT i;
5138 HRESULT hr;
5140 size += sizeof(*src->lprgscode) * src->cScodes;
5141 size += TLB_SizeElemDesc(&src->elemdescFunc);
5142 for (i = 0; i < src->cParams; i++)
5144 size += sizeof(ELEMDESC);
5145 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5148 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5149 if (!dest) return E_OUTOFMEMORY;
5151 *dest = *src;
5152 if (dispinterface) /* overwrite funckind */
5153 dest->funckind = FUNC_DISPATCH;
5154 buffer = (char *)(dest + 1);
5156 dest->lprgscode = (SCODE *)buffer;
5157 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5158 buffer += sizeof(*src->lprgscode) * src->cScodes;
5160 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5161 if (FAILED(hr))
5163 SysFreeString((BSTR)dest);
5164 return hr;
5167 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5168 buffer += sizeof(ELEMDESC) * src->cParams;
5169 for (i = 0; i < src->cParams; i++)
5171 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5172 if (FAILED(hr))
5173 break;
5175 if (FAILED(hr))
5177 /* undo the above actions */
5178 for (i = i - 1; i >= 0; i--)
5179 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5180 TLB_FreeElemDesc(&dest->elemdescFunc);
5181 SysFreeString((BSTR)dest);
5182 return hr;
5185 /* special treatment for dispinterfaces: this makes functions appear
5186 * to return their [retval] value when it is really returning an
5187 * HRESULT */
5188 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5190 if (dest->cParams &&
5191 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5193 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5194 if (elemdesc->tdesc.vt != VT_PTR)
5196 ERR("elemdesc should have started with VT_PTR instead of:\n");
5197 if (ERR_ON(ole))
5198 dump_ELEMDESC(elemdesc);
5199 return E_UNEXPECTED;
5202 /* copy last parameter to the return value. we are using a flat
5203 * buffer so there is no danger of leaking memory in
5204 * elemdescFunc */
5205 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5207 /* remove the last parameter */
5208 dest->cParams--;
5210 else
5211 /* otherwise this function is made to appear to have no return
5212 * value */
5213 dest->elemdescFunc.tdesc.vt = VT_VOID;
5217 *dest_ptr = dest;
5218 return S_OK;
5221 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5223 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5224 const TLBFuncDesc *pFDesc;
5225 UINT i;
5227 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5230 if (pFDesc)
5232 *ppFuncDesc = &pFDesc->funcdesc;
5233 return S_OK;
5236 return TYPE_E_ELEMENTNOTFOUND;
5239 /* internal function to make the inherited interfaces' methods appear
5240 * part of the interface */
5241 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5242 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5244 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5245 HRESULT hr;
5246 UINT implemented_funcs = 0;
5248 if (funcs)
5249 *funcs = 0;
5250 else
5251 *hrefoffset = DISPATCH_HREF_OFFSET;
5253 if(This->impltypelist)
5255 ITypeInfo *pSubTypeInfo;
5256 UINT sub_funcs;
5258 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5259 if (FAILED(hr))
5260 return hr;
5262 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5263 index,
5264 ppFuncDesc,
5265 &sub_funcs, hrefoffset);
5266 implemented_funcs += sub_funcs;
5267 ITypeInfo_Release(pSubTypeInfo);
5268 if (SUCCEEDED(hr))
5269 return hr;
5270 *hrefoffset += DISPATCH_HREF_OFFSET;
5273 if (funcs)
5274 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5275 else
5276 *hrefoffset = 0;
5278 if (index < implemented_funcs)
5279 return E_INVALIDARG;
5280 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5281 ppFuncDesc);
5284 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5286 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5287 while (TRUE)
5289 switch (pTypeDesc->vt)
5291 case VT_USERDEFINED:
5292 pTypeDesc->u.hreftype += hrefoffset;
5293 return;
5294 case VT_PTR:
5295 case VT_SAFEARRAY:
5296 pTypeDesc = pTypeDesc->u.lptdesc;
5297 break;
5298 case VT_CARRAY:
5299 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5300 break;
5301 default:
5302 return;
5307 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5309 SHORT i;
5310 for (i = 0; i < pFuncDesc->cParams; i++)
5311 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5312 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5315 /* ITypeInfo::GetFuncDesc
5317 * Retrieves the FUNCDESC structure that contains information about a
5318 * specified function.
5321 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5322 LPFUNCDESC *ppFuncDesc)
5324 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5325 const FUNCDESC *internal_funcdesc;
5326 HRESULT hr;
5327 UINT hrefoffset = 0;
5329 TRACE("(%p) index %d\n", This, index);
5331 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5332 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5333 &internal_funcdesc, NULL,
5334 &hrefoffset);
5335 else
5336 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5337 &internal_funcdesc);
5338 if (FAILED(hr))
5340 WARN("description for function %d not found\n", index);
5341 return hr;
5344 hr = TLB_AllocAndInitFuncDesc(
5345 internal_funcdesc,
5346 ppFuncDesc,
5347 This->TypeAttr.typekind == TKIND_DISPATCH);
5349 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5350 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5352 TRACE("-- 0x%08x\n", hr);
5353 return hr;
5356 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5358 VARDESC *dest;
5359 char *buffer;
5360 SIZE_T size = sizeof(*src);
5361 HRESULT hr;
5363 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5364 if (src->varkind == VAR_CONST)
5365 size += sizeof(VARIANT);
5366 size += TLB_SizeElemDesc(&src->elemdescVar);
5368 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5369 if (!dest) return E_OUTOFMEMORY;
5371 *dest = *src;
5372 buffer = (char *)(dest + 1);
5373 if (src->lpstrSchema)
5375 int len;
5376 dest->lpstrSchema = (LPOLESTR)buffer;
5377 len = strlenW(src->lpstrSchema);
5378 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5379 buffer += (len + 1) * sizeof(WCHAR);
5382 if (src->varkind == VAR_CONST)
5384 HRESULT hr;
5386 dest->u.lpvarValue = (VARIANT *)buffer;
5387 *dest->u.lpvarValue = *src->u.lpvarValue;
5388 buffer += sizeof(VARIANT);
5389 VariantInit(dest->u.lpvarValue);
5390 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5391 if (FAILED(hr))
5393 SysFreeString((BSTR)dest);
5394 return hr;
5397 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5398 if (FAILED(hr))
5400 if (src->varkind == VAR_CONST)
5401 VariantClear(dest->u.lpvarValue);
5402 SysFreeString((BSTR)dest);
5403 return hr;
5405 *dest_ptr = dest;
5406 return S_OK;
5409 /* ITypeInfo::GetVarDesc
5411 * Retrieves a VARDESC structure that describes the specified variable.
5414 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5415 LPVARDESC *ppVarDesc)
5417 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5418 UINT i;
5419 const TLBVarDesc *pVDesc;
5421 TRACE("(%p) index %d\n", This, index);
5423 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5426 if (pVDesc)
5427 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5429 return E_INVALIDARG;
5432 /* ITypeInfo_GetNames
5434 * Retrieves the variable with the specified member ID (or the name of the
5435 * property or method and its parameters) that correspond to the specified
5436 * function ID.
5438 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5439 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5441 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5442 const TLBFuncDesc *pFDesc;
5443 const TLBVarDesc *pVDesc;
5444 int i;
5445 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5446 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5447 if(pFDesc)
5449 /* function found, now return function and parameter names */
5450 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5452 if(!i)
5453 *rgBstrNames=SysAllocString(pFDesc->Name);
5454 else
5455 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5457 *pcNames=i;
5459 else
5461 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5462 if(pVDesc)
5464 *rgBstrNames=SysAllocString(pVDesc->Name);
5465 *pcNames=1;
5467 else
5469 if(This->impltypelist &&
5470 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5471 /* recursive search */
5472 ITypeInfo *pTInfo;
5473 HRESULT result;
5474 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5475 &pTInfo);
5476 if(SUCCEEDED(result))
5478 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5479 ITypeInfo_Release(pTInfo);
5480 return result;
5482 WARN("Could not search inherited interface!\n");
5484 else
5486 WARN("no names found\n");
5488 *pcNames=0;
5489 return TYPE_E_ELEMENTNOTFOUND;
5492 return S_OK;
5496 /* ITypeInfo::GetRefTypeOfImplType
5498 * If a type description describes a COM class, it retrieves the type
5499 * description of the implemented interface types. For an interface,
5500 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5501 * if any exist.
5504 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5505 ITypeInfo2 *iface,
5506 UINT index,
5507 HREFTYPE *pRefType)
5509 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5510 UINT i;
5511 HRESULT hr = S_OK;
5512 const TLBImplType *pImpl = This->impltypelist;
5514 TRACE("(%p) index %d\n", This, index);
5515 if (TRACE_ON(ole)) dump_TypeInfo(This);
5517 if(index==(UINT)-1)
5519 /* only valid on dual interfaces;
5520 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5522 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5524 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5526 *pRefType = -1;
5528 else
5530 hr = TYPE_E_ELEMENTNOTFOUND;
5533 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5535 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5536 *pRefType = This->pTypeLib->dispatch_href;
5538 else
5540 /* get element n from linked list */
5541 for(i=0; pImpl && i<index; i++)
5543 pImpl = pImpl->next;
5546 if (pImpl)
5547 *pRefType = pImpl->hRef;
5548 else
5549 hr = TYPE_E_ELEMENTNOTFOUND;
5552 if(TRACE_ON(ole))
5554 if(SUCCEEDED(hr))
5555 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5556 else
5557 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5560 return hr;
5563 /* ITypeInfo::GetImplTypeFlags
5565 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5566 * or base interface in a type description.
5568 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5569 UINT index, INT *pImplTypeFlags)
5571 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5572 UINT i;
5573 TLBImplType *pImpl;
5575 TRACE("(%p) index %d\n", This, index);
5576 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5577 i++, pImpl=pImpl->next)
5579 if(i==index && pImpl){
5580 *pImplTypeFlags=pImpl->implflags;
5581 return S_OK;
5583 *pImplTypeFlags=0;
5585 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5586 return S_OK;
5588 WARN("ImplType %d not found\n", index);
5589 return TYPE_E_ELEMENTNOTFOUND;
5592 /* GetIDsOfNames
5593 * Maps between member names and member IDs, and parameter names and
5594 * parameter IDs.
5596 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5597 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5599 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5600 const TLBFuncDesc *pFDesc;
5601 const TLBVarDesc *pVDesc;
5602 HRESULT ret=S_OK;
5603 UINT i;
5605 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5606 cNames);
5608 /* init out parameters in case of failure */
5609 for (i = 0; i < cNames; i++)
5610 pMemId[i] = MEMBERID_NIL;
5612 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5613 int j;
5614 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5615 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5616 for(i=1; i < cNames; i++){
5617 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5618 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5619 break;
5620 if( j<pFDesc->funcdesc.cParams)
5621 pMemId[i]=j;
5622 else
5623 ret=DISP_E_UNKNOWNNAME;
5625 TRACE("-- 0x%08x\n", ret);
5626 return ret;
5629 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5630 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5631 if(cNames) *pMemId=pVDesc->vardesc.memid;
5632 return ret;
5635 /* not found, see if it can be found in an inherited interface */
5636 if(This->impltypelist) {
5637 /* recursive search */
5638 ITypeInfo *pTInfo;
5639 ret=ITypeInfo_GetRefTypeInfo(iface,
5640 This->impltypelist->hRef, &pTInfo);
5641 if(SUCCEEDED(ret)){
5642 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5643 ITypeInfo_Release(pTInfo);
5644 return ret;
5646 WARN("Could not search inherited interface!\n");
5647 } else
5648 WARN("no names found\n");
5649 return DISP_E_UNKNOWNNAME;
5653 #ifdef __i386__
5655 extern DWORD CDECL call_method( void *func, int nb_args, const DWORD *args );
5656 __ASM_GLOBAL_FUNC( call_method,
5657 "pushl %ebp\n\t"
5658 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5659 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5660 "movl %esp,%ebp\n\t"
5661 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5662 "pushl %esi\n\t"
5663 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5664 "pushl %edi\n\t"
5665 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5666 "movl 12(%ebp),%edx\n\t"
5667 "shll $2,%edx\n\t"
5668 "jz 1f\n\t"
5669 "subl %edx,%esp\n\t"
5670 "andl $~15,%esp\n\t"
5671 "movl 12(%ebp),%ecx\n\t"
5672 "movl 16(%ebp),%esi\n\t"
5673 "movl %esp,%edi\n\t"
5674 "cld\n\t"
5675 "rep; movsl\n"
5676 "1:\tcall *8(%ebp)\n\t"
5677 "leal -8(%ebp),%esp\n\t"
5678 "popl %edi\n\t"
5679 __ASM_CFI(".cfi_same_value %edi\n\t")
5680 "popl %esi\n\t"
5681 __ASM_CFI(".cfi_same_value %esi\n\t")
5682 "popl %ebp\n\t"
5683 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5684 __ASM_CFI(".cfi_same_value %ebp\n\t")
5685 "ret" )
5687 /* ITypeInfo::Invoke
5689 * Invokes a method, or accesses a property of an object, that implements the
5690 * interface described by the type description.
5692 DWORD
5693 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5694 DWORD res;
5696 if (TRACE_ON(ole)) {
5697 int i;
5698 TRACE("Calling %p(",func);
5699 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5700 TRACE(")\n");
5703 switch (callconv) {
5704 case CC_STDCALL:
5705 case CC_CDECL:
5706 res = call_method( func, nrargs, args );
5707 break;
5708 default:
5709 FIXME("unsupported calling convention %d\n",callconv);
5710 res = -1;
5711 break;
5713 TRACE("returns %08x\n",res);
5714 return res;
5717 /* The size of the argument on the stack in DWORD units (in all x86 call
5718 * convetions the arguments on the stack are DWORD-aligned)
5720 static int _dispargsize(VARTYPE vt)
5722 switch (vt) {
5723 case VT_I8:
5724 case VT_UI8:
5725 return 8/sizeof(DWORD);
5726 case VT_R8:
5727 return sizeof(double)/sizeof(DWORD);
5728 case VT_DECIMAL:
5729 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5730 case VT_CY:
5731 return sizeof(CY)/sizeof(DWORD);
5732 case VT_DATE:
5733 return sizeof(DATE)/sizeof(DWORD);
5734 case VT_VARIANT:
5735 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5736 case VT_RECORD:
5737 FIXME("VT_RECORD not implemented\n");
5738 return 1;
5739 default:
5740 return 1;
5743 #endif /* __i386__ */
5745 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5747 HRESULT hr = S_OK;
5748 ITypeInfo *tinfo2 = NULL;
5749 TYPEATTR *tattr = NULL;
5751 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5752 if (hr)
5754 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5755 "hr = 0x%08x\n",
5756 tdesc->u.hreftype, hr);
5757 return hr;
5759 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5760 if (hr)
5762 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5763 ITypeInfo_Release(tinfo2);
5764 return hr;
5767 switch (tattr->typekind)
5769 case TKIND_ENUM:
5770 *vt |= VT_I4;
5771 break;
5773 case TKIND_ALIAS:
5774 tdesc = &tattr->tdescAlias;
5775 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5776 break;
5778 case TKIND_INTERFACE:
5779 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5780 *vt |= VT_DISPATCH;
5781 else
5782 *vt |= VT_UNKNOWN;
5783 break;
5785 case TKIND_DISPATCH:
5786 *vt |= VT_DISPATCH;
5787 break;
5789 case TKIND_COCLASS:
5790 *vt |= VT_DISPATCH;
5791 break;
5793 case TKIND_RECORD:
5794 FIXME("TKIND_RECORD unhandled.\n");
5795 hr = E_NOTIMPL;
5796 break;
5798 case TKIND_UNION:
5799 FIXME("TKIND_UNION unhandled.\n");
5800 hr = E_NOTIMPL;
5801 break;
5803 default:
5804 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5805 hr = E_NOTIMPL;
5806 break;
5808 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5809 ITypeInfo_Release(tinfo2);
5810 return hr;
5813 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5815 HRESULT hr = S_OK;
5817 /* enforce only one level of pointer indirection */
5818 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5820 tdesc = tdesc->u.lptdesc;
5822 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5823 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5824 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5825 if ((tdesc->vt == VT_USERDEFINED) ||
5826 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5828 VARTYPE vt_userdefined = 0;
5829 const TYPEDESC *tdesc_userdefined = tdesc;
5830 if (tdesc->vt == VT_PTR)
5832 vt_userdefined = VT_BYREF;
5833 tdesc_userdefined = tdesc->u.lptdesc;
5835 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5836 if ((hr == S_OK) &&
5837 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5838 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5840 *vt |= vt_userdefined;
5841 return S_OK;
5844 *vt = VT_BYREF;
5847 switch (tdesc->vt)
5849 case VT_HRESULT:
5850 *vt |= VT_ERROR;
5851 break;
5852 case VT_USERDEFINED:
5853 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5854 break;
5855 case VT_VOID:
5856 case VT_CARRAY:
5857 case VT_PTR:
5858 case VT_LPSTR:
5859 case VT_LPWSTR:
5860 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5861 hr = DISP_E_BADVARTYPE;
5862 break;
5863 case VT_SAFEARRAY:
5864 *vt |= VT_ARRAY;
5865 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5866 break;
5867 case VT_INT:
5868 *vt |= VT_I4;
5869 break;
5870 case VT_UINT:
5871 *vt |= VT_UI4;
5872 break;
5873 default:
5874 *vt |= tdesc->vt;
5875 break;
5877 return hr;
5880 /***********************************************************************
5881 * DispCallFunc (OLEAUT32.@)
5883 * Invokes a function of the specified calling convention, passing the
5884 * specified arguments and returns the result.
5886 * PARAMS
5887 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5888 * oVft [I] The offset in the vtable. See notes.
5889 * cc [I] Calling convention of the function to call.
5890 * vtReturn [I] The return type of the function.
5891 * cActuals [I] Number of parameters.
5892 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5893 * prgpvarg [I] The arguments to pass.
5894 * pvargResult [O] The return value of the function. Can be NULL.
5896 * RETURNS
5897 * Success: S_OK.
5898 * Failure: HRESULT code.
5900 * NOTES
5901 * The HRESULT return value of this function is not affected by the return
5902 * value of the user supplied function, which is returned in pvargResult.
5904 * If pvInstance is NULL then a non-object function is to be called and oVft
5905 * is the address of the function to call.
5907 * The cc parameter can be one of the following values:
5908 *|CC_FASTCALL
5909 *|CC_CDECL
5910 *|CC_PASCAL
5911 *|CC_STDCALL
5912 *|CC_FPFASTCALL
5913 *|CC_SYSCALL
5914 *|CC_MPWCDECL
5915 *|CC_MPWPASCAL
5918 HRESULT WINAPI
5919 DispCallFunc(
5920 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5921 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5923 #ifdef __i386__
5924 int argsize, argspos;
5925 UINT i;
5926 DWORD *args;
5927 HRESULT hres;
5929 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5930 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5931 pvargResult, V_VT(pvargResult));
5933 argsize = 0;
5934 if (pvInstance)
5935 argsize++; /* for This pointer */
5937 for (i=0;i<cActuals;i++)
5939 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5940 dump_Variant(prgpvarg[i]);
5941 argsize += _dispargsize(prgvt[i]);
5943 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5945 argspos = 0;
5946 if (pvInstance)
5948 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5949 argspos++;
5952 for (i=0;i<cActuals;i++)
5954 VARIANT *arg = prgpvarg[i];
5955 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5956 if (prgvt[i] == VT_VARIANT)
5957 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5958 else
5959 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5960 argspos += _dispargsize(prgvt[i]);
5963 if (pvInstance)
5965 FARPROC *vtable = *(FARPROC**)pvInstance;
5966 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5968 else
5969 /* if we aren't invoking an object then the function pointer is stored
5970 * in oVft */
5971 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5973 if (pvargResult && (vtReturn != VT_EMPTY))
5975 TRACE("Method returned 0x%08x\n",hres);
5976 V_VT(pvargResult) = vtReturn;
5977 V_UI4(pvargResult) = hres;
5979 HeapFree(GetProcessHeap(),0,args);
5980 return S_OK;
5981 #else
5982 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
5983 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
5984 return E_NOTIMPL;
5985 #endif
5988 #define INVBUF_ELEMENT_SIZE \
5989 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5990 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5991 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5992 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5993 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5994 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5995 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5996 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5998 static HRESULT WINAPI ITypeInfo_fnInvoke(
5999 ITypeInfo2 *iface,
6000 VOID *pIUnk,
6001 MEMBERID memid,
6002 UINT16 wFlags,
6003 DISPPARAMS *pDispParams,
6004 VARIANT *pVarResult,
6005 EXCEPINFO *pExcepInfo,
6006 UINT *pArgErr)
6008 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6009 int i;
6010 unsigned int var_index;
6011 TYPEKIND type_kind;
6012 HRESULT hres;
6013 const TLBFuncDesc *pFuncInfo;
6015 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6016 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6019 if (!pDispParams)
6021 ERR("NULL pDispParams not allowed\n");
6022 return E_INVALIDARG;
6025 dump_DispParms(pDispParams);
6027 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6029 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6030 pDispParams->cNamedArgs, pDispParams->cArgs);
6031 return E_INVALIDARG;
6034 /* we do this instead of using GetFuncDesc since it will return a fake
6035 * FUNCDESC for dispinterfaces and we want the real function description */
6036 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6037 if ((memid == pFuncInfo->funcdesc.memid) &&
6038 (wFlags & pFuncInfo->funcdesc.invkind))
6039 break;
6041 if (pFuncInfo) {
6042 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6044 if (TRACE_ON(ole))
6046 TRACE("invoking:\n");
6047 dump_TLBFuncDescOne(pFuncInfo);
6050 switch (func_desc->funckind) {
6051 case FUNC_PUREVIRTUAL:
6052 case FUNC_VIRTUAL: {
6053 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6054 VARIANT varresult;
6055 VARIANT retval; /* pointer for storing byref retvals in */
6056 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6057 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6058 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6059 UINT cNamedArgs = pDispParams->cNamedArgs;
6060 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6061 UINT vargs_converted=0;
6063 hres = S_OK;
6065 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6067 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6069 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6070 hres = DISP_E_PARAMNOTFOUND;
6071 goto func_fail;
6075 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6077 ERR("functions with the vararg attribute do not support named arguments\n");
6078 hres = DISP_E_NONAMEDARGS;
6079 goto func_fail;
6082 for (i = 0; i < func_desc->cParams; i++)
6084 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6085 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6086 if (FAILED(hres))
6087 goto func_fail;
6090 TRACE("changing args\n");
6091 for (i = 0; i < func_desc->cParams; i++)
6093 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6094 VARIANTARG *src_arg;
6096 if (wParamFlags & PARAMFLAG_FLCID)
6098 VARIANTARG *arg;
6099 arg = prgpvarg[i] = &rgvarg[i];
6100 V_VT(arg) = VT_I4;
6101 V_I4(arg) = This->pTypeLib->lcid;
6102 continue;
6105 src_arg = NULL;
6107 if (cNamedArgs)
6109 USHORT j;
6110 for (j = 0; j < cNamedArgs; j++)
6111 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6113 src_arg = &pDispParams->rgvarg[j];
6114 break;
6118 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6120 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6121 vargs_converted++;
6124 if (wParamFlags & PARAMFLAG_FRETVAL)
6126 /* under most conditions the caller is not allowed to
6127 * pass in a dispparam arg in the index of what would be
6128 * the retval parameter. however, there is an exception
6129 * where the extra parameter is used in an extra
6130 * IDispatch::Invoke below */
6131 if ((i < pDispParams->cArgs) &&
6132 ((func_desc->cParams != 1) || !pVarResult ||
6133 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6135 hres = DISP_E_BADPARAMCOUNT;
6136 break;
6139 /* note: this check is placed so that if the caller passes
6140 * in a VARIANTARG for the retval we just ignore it, like
6141 * native does */
6142 if (i == func_desc->cParams - 1)
6144 VARIANTARG *arg;
6145 arg = prgpvarg[i] = &rgvarg[i];
6146 memset(arg, 0, sizeof(*arg));
6147 V_VT(arg) = rgvt[i];
6148 memset(&retval, 0, sizeof(retval));
6149 V_BYREF(arg) = &retval;
6151 else
6153 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6154 hres = E_UNEXPECTED;
6155 break;
6158 else if (src_arg)
6160 dump_Variant(src_arg);
6162 if (rgvt[i] == VT_VARIANT)
6163 hres = VariantCopy(&rgvarg[i], src_arg);
6164 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6166 if (rgvt[i] == V_VT(src_arg))
6167 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6168 else
6170 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6171 if (wParamFlags & PARAMFLAG_FIN)
6172 hres = VariantCopy(&missing_arg[i], src_arg);
6173 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6175 V_VT(&rgvarg[i]) = rgvt[i];
6177 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6179 SAFEARRAY *a;
6180 SAFEARRAYBOUND bound;
6181 VARIANT *v;
6182 LONG j;
6183 bound.lLbound = 0;
6184 bound.cElements = pDispParams->cArgs-i;
6185 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6187 ERR("SafeArrayCreate failed\n");
6188 break;
6190 hres = SafeArrayAccessData(a, (LPVOID)&v);
6191 if (hres != S_OK)
6193 ERR("SafeArrayAccessData failed with %x\n", hres);
6194 break;
6196 for (j = 0; j < bound.cElements; j++)
6197 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6198 hres = SafeArrayUnaccessData(a);
6199 if (hres != S_OK)
6201 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6202 break;
6204 V_ARRAY(&rgvarg[i]) = a;
6205 V_VT(&rgvarg[i]) = rgvt[i];
6207 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6209 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6210 if (wParamFlags & PARAMFLAG_FIN)
6211 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6212 else
6213 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6214 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6215 V_VT(&rgvarg[i]) = rgvt[i];
6217 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6219 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6220 V_VT(&rgvarg[i]) = rgvt[i];
6222 else
6224 /* FIXME: this doesn't work for VT_BYREF arguments if
6225 * they are not the same type as in the paramdesc */
6226 V_VT(&rgvarg[i]) = V_VT(src_arg);
6227 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6228 V_VT(&rgvarg[i]) = rgvt[i];
6231 if (FAILED(hres))
6233 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6234 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6235 debugstr_VT(src_arg), debugstr_VF(src_arg));
6236 break;
6238 prgpvarg[i] = &rgvarg[i];
6240 else if (wParamFlags & PARAMFLAG_FOPT)
6242 VARIANTARG *arg;
6243 arg = prgpvarg[i] = &rgvarg[i];
6244 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6246 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6247 if (FAILED(hres))
6248 break;
6250 else
6252 VARIANTARG *missing_arg;
6253 /* if the function wants a pointer to a variant then
6254 * set that up, otherwise just pass the VT_ERROR in
6255 * the argument by value */
6256 if (rgvt[i] & VT_BYREF)
6258 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6259 V_VT(arg) = VT_VARIANT | VT_BYREF;
6260 V_VARIANTREF(arg) = missing_arg;
6262 else
6263 missing_arg = arg;
6264 V_VT(missing_arg) = VT_ERROR;
6265 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6268 else
6270 hres = DISP_E_BADPARAMCOUNT;
6271 break;
6274 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6276 /* VT_VOID is a special case for return types, so it is not
6277 * handled in the general function */
6278 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6279 V_VT(&varresult) = VT_EMPTY;
6280 else
6282 V_VT(&varresult) = 0;
6283 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6284 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6287 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6288 V_VT(&varresult), func_desc->cParams, rgvt,
6289 prgpvarg, &varresult);
6291 vargs_converted = 0;
6293 for (i = 0; i < func_desc->cParams; i++)
6295 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6296 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6298 if (wParamFlags & PARAMFLAG_FLCID)
6299 continue;
6300 else if (wParamFlags & PARAMFLAG_FRETVAL)
6302 if (TRACE_ON(ole))
6304 TRACE("[retval] value: ");
6305 dump_Variant(prgpvarg[i]);
6308 if (pVarResult)
6310 VariantInit(pVarResult);
6311 /* deref return value */
6312 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6315 VARIANT_ClearInd(prgpvarg[i]);
6317 else if (vargs_converted < pDispParams->cArgs)
6319 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6320 if (wParamFlags & PARAMFLAG_FOUT)
6322 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6324 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6326 if (FAILED(hres))
6328 ERR("failed to convert param %d to vt %d\n", i,
6329 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6330 break;
6334 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6335 func_desc->cParamsOpt < 0 &&
6336 i == func_desc->cParams-1)
6338 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6339 LONG j, ubound;
6340 VARIANT *v;
6341 hres = SafeArrayGetUBound(a, 1, &ubound);
6342 if (hres != S_OK)
6344 ERR("SafeArrayGetUBound failed with %x\n", hres);
6345 break;
6347 hres = SafeArrayAccessData(a, (LPVOID)&v);
6348 if (hres != S_OK)
6350 ERR("SafeArrayAccessData failed with %x\n", hres);
6351 break;
6353 for (j = 0; j <= ubound; j++)
6354 VariantClear(&v[j]);
6355 hres = SafeArrayUnaccessData(a);
6356 if (hres != S_OK)
6358 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6359 break;
6362 VariantClear(&rgvarg[i]);
6363 vargs_converted++;
6365 else if (wParamFlags & PARAMFLAG_FOPT)
6367 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6368 VariantClear(&rgvarg[i]);
6371 VariantClear(&missing_arg[i]);
6374 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6376 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6377 hres = DISP_E_EXCEPTION;
6378 if (pExcepInfo)
6380 IErrorInfo *pErrorInfo;
6381 pExcepInfo->scode = V_ERROR(&varresult);
6382 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6384 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6385 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6386 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6387 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6389 IErrorInfo_Release(pErrorInfo);
6393 if (V_VT(&varresult) != VT_ERROR)
6395 TRACE("varresult value: ");
6396 dump_Variant(&varresult);
6398 if (pVarResult)
6400 VariantClear(pVarResult);
6401 *pVarResult = varresult;
6403 else
6404 VariantClear(&varresult);
6407 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6408 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6409 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6410 (pDispParams->cArgs != 0))
6412 if (V_VT(pVarResult) == VT_DISPATCH)
6414 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6415 /* Note: not VariantClear; we still need the dispatch
6416 * pointer to be valid */
6417 VariantInit(pVarResult);
6418 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6419 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6420 pDispParams, pVarResult, pExcepInfo, pArgErr);
6421 IDispatch_Release(pDispatch);
6423 else
6425 VariantClear(pVarResult);
6426 hres = DISP_E_NOTACOLLECTION;
6430 func_fail:
6431 HeapFree(GetProcessHeap(), 0, buffer);
6432 break;
6434 case FUNC_DISPATCH: {
6435 IDispatch *disp;
6437 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6438 if (SUCCEEDED(hres)) {
6439 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6440 hres = IDispatch_Invoke(
6441 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6442 pVarResult,pExcepInfo,pArgErr
6444 if (FAILED(hres))
6445 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6446 IDispatch_Release(disp);
6447 } else
6448 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6449 break;
6451 default:
6452 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6453 hres = E_FAIL;
6454 break;
6457 TRACE("-- 0x%08x\n", hres);
6458 return hres;
6460 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6461 VARDESC *var_desc;
6463 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6464 if(FAILED(hres)) return hres;
6466 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6467 dump_VARDESC(var_desc);
6468 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6469 return E_NOTIMPL;
6472 /* not found, look for it in inherited interfaces */
6473 ITypeInfo2_GetTypeKind(iface, &type_kind);
6474 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6475 if(This->impltypelist) {
6476 /* recursive search */
6477 ITypeInfo *pTInfo;
6478 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6479 if(SUCCEEDED(hres)){
6480 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6481 ITypeInfo_Release(pTInfo);
6482 return hres;
6484 WARN("Could not search inherited interface!\n");
6487 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6488 return DISP_E_MEMBERNOTFOUND;
6491 /* ITypeInfo::GetDocumentation
6493 * Retrieves the documentation string, the complete Help file name and path,
6494 * and the context ID for the Help topic for a specified type description.
6496 * (Can be tested by the Visual Basic Editor in Word for instance.)
6498 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6499 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6500 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6502 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6503 const TLBFuncDesc *pFDesc;
6504 const TLBVarDesc *pVDesc;
6505 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6506 " HelpContext(%p) HelpFile(%p)\n",
6507 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6508 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6509 if(pBstrName)
6510 *pBstrName=SysAllocString(This->Name);
6511 if(pBstrDocString)
6512 *pBstrDocString=SysAllocString(This->DocString);
6513 if(pdwHelpContext)
6514 *pdwHelpContext=This->dwHelpContext;
6515 if(pBstrHelpFile)
6516 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6517 return S_OK;
6518 }else {/* for a member */
6519 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6520 if(pFDesc->funcdesc.memid==memid){
6521 if(pBstrName)
6522 *pBstrName = SysAllocString(pFDesc->Name);
6523 if(pBstrDocString)
6524 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6525 if(pdwHelpContext)
6526 *pdwHelpContext=pFDesc->helpcontext;
6527 return S_OK;
6529 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6530 if(pVDesc->vardesc.memid==memid){
6531 if(pBstrName)
6532 *pBstrName = SysAllocString(pVDesc->Name);
6533 if(pBstrDocString)
6534 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6535 if(pdwHelpContext)
6536 *pdwHelpContext=pVDesc->HelpContext;
6537 return S_OK;
6541 if(This->impltypelist &&
6542 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6543 /* recursive search */
6544 ITypeInfo *pTInfo;
6545 HRESULT result;
6546 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6547 &pTInfo);
6548 if(SUCCEEDED(result)) {
6549 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6550 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6551 ITypeInfo_Release(pTInfo);
6552 return result;
6554 WARN("Could not search inherited interface!\n");
6557 WARN("member %d not found\n", memid);
6558 return TYPE_E_ELEMENTNOTFOUND;
6561 /* ITypeInfo::GetDllEntry
6563 * Retrieves a description or specification of an entry point for a function
6564 * in a DLL.
6566 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6567 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6568 WORD *pwOrdinal)
6570 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6571 const TLBFuncDesc *pFDesc;
6573 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6575 if (pBstrDllName) *pBstrDllName = NULL;
6576 if (pBstrName) *pBstrName = NULL;
6577 if (pwOrdinal) *pwOrdinal = 0;
6579 if (This->TypeAttr.typekind != TKIND_MODULE)
6580 return TYPE_E_BADMODULEKIND;
6582 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6583 if(pFDesc->funcdesc.memid==memid){
6584 dump_TypeInfo(This);
6585 if (TRACE_ON(ole))
6586 dump_TLBFuncDescOne(pFDesc);
6588 if (pBstrDllName)
6589 *pBstrDllName = SysAllocString(This->DllName);
6591 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6592 if (pBstrName)
6593 *pBstrName = SysAllocString(pFDesc->Entry);
6594 if (pwOrdinal)
6595 *pwOrdinal = -1;
6596 return S_OK;
6598 if (pBstrName)
6599 *pBstrName = NULL;
6600 if (pwOrdinal)
6601 *pwOrdinal = (DWORD)pFDesc->Entry;
6602 return S_OK;
6604 return TYPE_E_ELEMENTNOTFOUND;
6607 /* internal function to make the inherited interfaces' methods appear
6608 * part of the interface */
6609 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6610 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6612 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6613 HRESULT hr;
6615 TRACE("%p, 0x%x\n", iface, *hRefType);
6617 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6619 ITypeInfo *pSubTypeInfo;
6621 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6622 if (FAILED(hr))
6623 return hr;
6625 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6626 hRefType, ppTInfo);
6627 ITypeInfo_Release(pSubTypeInfo);
6628 if (SUCCEEDED(hr))
6629 return hr;
6631 *hRefType -= DISPATCH_HREF_OFFSET;
6633 if (!(*hRefType & DISPATCH_HREF_MASK))
6634 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6635 else
6636 return E_FAIL;
6639 /* ITypeInfo::GetRefTypeInfo
6641 * If a type description references other type descriptions, it retrieves
6642 * the referenced type descriptions.
6644 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6645 ITypeInfo2 *iface,
6646 HREFTYPE hRefType,
6647 ITypeInfo **ppTInfo)
6649 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6650 HRESULT result = E_FAIL;
6652 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6654 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6655 ITypeInfo_AddRef(*ppTInfo);
6656 result = S_OK;
6658 else if (hRefType == -1 &&
6659 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6660 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6662 /* when we meet a DUAL dispinterface, we must create the interface
6663 * version of it.
6665 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6668 /* the interface version contains the same information as the dispinterface
6669 * copy the contents of the structs.
6671 *pTypeInfoImpl = *This;
6672 pTypeInfoImpl->ref = 0;
6674 /* change the type to interface */
6675 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6677 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6679 /* the AddRef implicitly adds a reference to the parent typelib, which
6680 * stops the copied data from being destroyed until the new typeinfo's
6681 * refcount goes to zero, but we need to signal to the new instance to
6682 * not free its data structures when it is destroyed */
6683 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6685 ITypeInfo_AddRef(*ppTInfo);
6687 result = S_OK;
6689 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6690 (This->TypeAttr.typekind == TKIND_DISPATCH))
6692 HREFTYPE href_dispatch = hRefType;
6693 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6694 } else {
6695 TLBRefType *ref_type;
6696 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6698 if(ref_type->reference == hRefType)
6699 break;
6701 if(&ref_type->entry == &This->pTypeLib->ref_list)
6703 FIXME("Can't find pRefType for ref %x\n", hRefType);
6704 goto end;
6706 if(hRefType != -1) {
6707 ITypeLib *pTLib = NULL;
6709 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6710 UINT Index;
6711 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6712 } else {
6713 if(ref_type->pImpTLInfo->pImpTypeLib) {
6714 TRACE("typeinfo in imported typelib that is already loaded\n");
6715 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6716 ITypeLib2_AddRef(pTLib);
6717 result = S_OK;
6718 } else {
6719 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6720 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6721 ref_type->pImpTLInfo->wVersionMajor,
6722 ref_type->pImpTLInfo->wVersionMinor,
6723 ref_type->pImpTLInfo->lcid,
6724 &pTLib);
6726 if(FAILED(result)) {
6727 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6728 result=LoadTypeLib(libnam, &pTLib);
6729 SysFreeString(libnam);
6731 if(SUCCEEDED(result)) {
6732 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6733 ITypeLib2_AddRef(pTLib);
6737 if(SUCCEEDED(result)) {
6738 if(ref_type->index == TLB_REF_USE_GUID)
6739 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6740 &ref_type->guid,
6741 ppTInfo);
6742 else
6743 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6744 ppTInfo);
6746 if (pTLib != NULL)
6747 ITypeLib2_Release(pTLib);
6751 end:
6752 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6753 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6754 return result;
6757 /* ITypeInfo::AddressOfMember
6759 * Retrieves the addresses of static functions or variables, such as those
6760 * defined in a DLL.
6762 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6763 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6765 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6766 HRESULT hr;
6767 BSTR dll, entry;
6768 WORD ordinal;
6769 HMODULE module;
6771 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6773 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6774 if (FAILED(hr))
6775 return hr;
6777 module = LoadLibraryW(dll);
6778 if (!module)
6780 ERR("couldn't load %s\n", debugstr_w(dll));
6781 SysFreeString(dll);
6782 SysFreeString(entry);
6783 return STG_E_FILENOTFOUND;
6785 /* FIXME: store library somewhere where we can free it */
6787 if (entry)
6789 LPSTR entryA;
6790 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6791 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6792 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6794 *ppv = GetProcAddress(module, entryA);
6795 if (!*ppv)
6796 ERR("function not found %s\n", debugstr_a(entryA));
6798 HeapFree(GetProcessHeap(), 0, entryA);
6800 else
6802 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6803 if (!*ppv)
6804 ERR("function not found %d\n", ordinal);
6807 SysFreeString(dll);
6808 SysFreeString(entry);
6810 if (!*ppv)
6811 return TYPE_E_DLLFUNCTIONNOTFOUND;
6813 return S_OK;
6816 /* ITypeInfo::CreateInstance
6818 * Creates a new instance of a type that describes a component object class
6819 * (coclass).
6821 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6822 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6824 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6825 HRESULT hr;
6826 TYPEATTR *pTA;
6828 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6830 *ppvObj = NULL;
6832 if(pOuterUnk)
6834 WARN("Not able to aggregate\n");
6835 return CLASS_E_NOAGGREGATION;
6838 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6839 if(FAILED(hr)) return hr;
6841 if(pTA->typekind != TKIND_COCLASS)
6843 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6844 hr = E_INVALIDARG;
6845 goto end;
6848 hr = S_FALSE;
6849 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6851 IUnknown *pUnk;
6852 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6853 TRACE("GetActiveObject rets %08x\n", hr);
6854 if(hr == S_OK)
6856 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6857 IUnknown_Release(pUnk);
6861 if(hr != S_OK)
6862 hr = CoCreateInstance(&pTA->guid, NULL,
6863 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6864 riid, ppvObj);
6866 end:
6867 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6868 return hr;
6871 /* ITypeInfo::GetMops
6873 * Retrieves marshalling information.
6875 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6876 BSTR *pBstrMops)
6878 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6879 FIXME("(%p %d) stub!\n", This, memid);
6880 *pBstrMops = NULL;
6881 return S_OK;
6884 /* ITypeInfo::GetContainingTypeLib
6886 * Retrieves the containing type library and the index of the type description
6887 * within that type library.
6889 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6890 ITypeLib * *ppTLib, UINT *pIndex)
6892 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6894 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6895 if (pIndex) {
6896 *pIndex=This->index;
6897 TRACE("returning pIndex=%d\n", *pIndex);
6900 if (ppTLib) {
6901 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6902 ITypeLib2_AddRef(*ppTLib);
6903 TRACE("returning ppTLib=%p\n", *ppTLib);
6906 return S_OK;
6909 /* ITypeInfo::ReleaseTypeAttr
6911 * Releases a TYPEATTR previously returned by GetTypeAttr.
6914 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6915 TYPEATTR* pTypeAttr)
6917 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6918 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6919 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6922 /* ITypeInfo::ReleaseFuncDesc
6924 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6926 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6927 ITypeInfo2 *iface,
6928 FUNCDESC *pFuncDesc)
6930 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6931 SHORT i;
6933 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6935 for (i = 0; i < pFuncDesc->cParams; i++)
6936 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6937 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6939 SysFreeString((BSTR)pFuncDesc);
6942 /* ITypeInfo::ReleaseVarDesc
6944 * Releases a VARDESC previously returned by GetVarDesc.
6946 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6947 VARDESC *pVarDesc)
6949 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6950 TRACE("(%p)->(%p)\n", This, pVarDesc);
6952 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6953 if (pVarDesc->varkind == VAR_CONST)
6954 VariantClear(pVarDesc->u.lpvarValue);
6955 SysFreeString((BSTR)pVarDesc);
6958 /* ITypeInfo2::GetTypeKind
6960 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6963 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6964 TYPEKIND *pTypeKind)
6966 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6967 *pTypeKind=This->TypeAttr.typekind;
6968 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6969 return S_OK;
6972 /* ITypeInfo2::GetTypeFlags
6974 * Returns the type flags without any allocations. This returns a DWORD type
6975 * flag, which expands the type flags without growing the TYPEATTR (type
6976 * attribute).
6979 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6981 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6982 *pTypeFlags=This->TypeAttr.wTypeFlags;
6983 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6984 return S_OK;
6987 /* ITypeInfo2::GetFuncIndexOfMemId
6988 * Binds to a specific member based on a known DISPID, where the member name
6989 * is not known (for example, when binding to a default member).
6992 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6993 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6995 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6996 const TLBFuncDesc *pFuncInfo;
6997 int i;
6998 HRESULT result;
7000 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7001 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7002 break;
7003 if(pFuncInfo) {
7004 *pFuncIndex = i;
7005 result = S_OK;
7006 } else
7007 result = TYPE_E_ELEMENTNOTFOUND;
7009 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7010 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7011 return result;
7014 /* TypeInfo2::GetVarIndexOfMemId
7016 * Binds to a specific member based on a known DISPID, where the member name
7017 * is not known (for example, when binding to a default member).
7020 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7021 MEMBERID memid, UINT *pVarIndex)
7023 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7024 TLBVarDesc *pVarInfo;
7025 int i;
7026 HRESULT result;
7027 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7028 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7030 if(pVarInfo) {
7031 *pVarIndex = i;
7032 result = S_OK;
7033 } else
7034 result = TYPE_E_ELEMENTNOTFOUND;
7036 TRACE("(%p) memid 0x%08x -> %s\n", This,
7037 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7038 return result;
7041 /* ITypeInfo2::GetCustData
7043 * Gets the custom data
7045 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7046 ITypeInfo2 * iface,
7047 REFGUID guid,
7048 VARIANT *pVarVal)
7050 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7051 TLBCustData *pCData;
7053 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7054 if( IsEqualIID(guid, &pCData->guid)) break;
7056 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7058 VariantInit( pVarVal);
7059 if (pCData)
7060 VariantCopy( pVarVal, &pCData->data);
7061 else
7062 VariantClear( pVarVal );
7063 return S_OK;
7066 /* ITypeInfo2::GetFuncCustData
7068 * Gets the custom data
7070 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7071 ITypeInfo2 * iface,
7072 UINT index,
7073 REFGUID guid,
7074 VARIANT *pVarVal)
7076 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7077 TLBCustData *pCData=NULL;
7078 TLBFuncDesc * pFDesc;
7079 UINT i;
7080 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7081 pFDesc=pFDesc->next);
7083 if(pFDesc)
7084 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7085 if( IsEqualIID(guid, &pCData->guid)) break;
7087 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7089 if(pCData){
7090 VariantInit( pVarVal);
7091 VariantCopy( pVarVal, &pCData->data);
7092 return S_OK;
7094 return E_INVALIDARG; /* FIXME: correct? */
7097 /* ITypeInfo2::GetParamCustData
7099 * Gets the custom data
7101 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7102 ITypeInfo2 * iface,
7103 UINT indexFunc,
7104 UINT indexParam,
7105 REFGUID guid,
7106 VARIANT *pVarVal)
7108 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7109 TLBCustData *pCData=NULL;
7110 TLBFuncDesc * pFDesc;
7111 UINT i;
7113 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7115 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7116 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7117 pCData = pCData->next)
7118 if( IsEqualIID(guid, &pCData->guid)) break;
7120 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7122 if(pCData)
7124 VariantInit( pVarVal);
7125 VariantCopy( pVarVal, &pCData->data);
7126 return S_OK;
7128 return E_INVALIDARG; /* FIXME: correct? */
7131 /* ITypeInfo2::GetVarCustData
7133 * Gets the custom data
7135 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7136 ITypeInfo2 * iface,
7137 UINT index,
7138 REFGUID guid,
7139 VARIANT *pVarVal)
7141 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7142 TLBCustData *pCData=NULL;
7143 TLBVarDesc * pVDesc;
7144 UINT i;
7146 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7148 if(pVDesc)
7150 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7152 if( IsEqualIID(guid, &pCData->guid)) break;
7156 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7158 if(pCData)
7160 VariantInit( pVarVal);
7161 VariantCopy( pVarVal, &pCData->data);
7162 return S_OK;
7164 return E_INVALIDARG; /* FIXME: correct? */
7167 /* ITypeInfo2::GetImplCustData
7169 * Gets the custom data
7171 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7172 ITypeInfo2 * iface,
7173 UINT index,
7174 REFGUID guid,
7175 VARIANT *pVarVal)
7177 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7178 TLBCustData *pCData=NULL;
7179 TLBImplType * pRDesc;
7180 UINT i;
7182 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7184 if(pRDesc)
7186 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7188 if( IsEqualIID(guid, &pCData->guid)) break;
7192 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7194 if(pCData)
7196 VariantInit( pVarVal);
7197 VariantCopy( pVarVal, &pCData->data);
7198 return S_OK;
7200 return E_INVALIDARG; /* FIXME: correct? */
7203 /* ITypeInfo2::GetDocumentation2
7205 * Retrieves the documentation string, the complete Help file name and path,
7206 * the localization context to use, and the context ID for the library Help
7207 * topic in the Help file.
7210 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7211 ITypeInfo2 * iface,
7212 MEMBERID memid,
7213 LCID lcid,
7214 BSTR *pbstrHelpString,
7215 DWORD *pdwHelpStringContext,
7216 BSTR *pbstrHelpStringDll)
7218 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7219 const TLBFuncDesc *pFDesc;
7220 const TLBVarDesc *pVDesc;
7221 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7222 "HelpStringContext(%p) HelpStringDll(%p)\n",
7223 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7224 pbstrHelpStringDll );
7225 /* the help string should be obtained from the helpstringdll,
7226 * using the _DLLGetDocumentation function, based on the supplied
7227 * lcid. Nice to do sometime...
7229 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7230 if(pbstrHelpString)
7231 *pbstrHelpString=SysAllocString(This->Name);
7232 if(pdwHelpStringContext)
7233 *pdwHelpStringContext=This->dwHelpStringContext;
7234 if(pbstrHelpStringDll)
7235 *pbstrHelpStringDll=
7236 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7237 return S_OK;
7238 }else {/* for a member */
7239 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7240 if(pFDesc->funcdesc.memid==memid){
7241 if(pbstrHelpString)
7242 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7243 if(pdwHelpStringContext)
7244 *pdwHelpStringContext=pFDesc->HelpStringContext;
7245 if(pbstrHelpStringDll)
7246 *pbstrHelpStringDll=
7247 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7248 return S_OK;
7250 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7251 if(pVDesc->vardesc.memid==memid){
7252 if(pbstrHelpString)
7253 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7254 if(pdwHelpStringContext)
7255 *pdwHelpStringContext=pVDesc->HelpStringContext;
7256 if(pbstrHelpStringDll)
7257 *pbstrHelpStringDll=
7258 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7259 return S_OK;
7262 return TYPE_E_ELEMENTNOTFOUND;
7265 /* ITypeInfo2::GetAllCustData
7267 * Gets all custom data items for the Type info.
7270 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7271 ITypeInfo2 * iface,
7272 CUSTDATA *pCustData)
7274 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7275 TLBCustData *pCData;
7276 int i;
7278 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7280 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7281 if(pCustData->prgCustData ){
7282 pCustData->cCustData=This->ctCustData;
7283 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7284 pCustData->prgCustData[i].guid=pCData->guid;
7285 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7287 }else{
7288 ERR(" OUT OF MEMORY!\n");
7289 return E_OUTOFMEMORY;
7291 return S_OK;
7294 /* ITypeInfo2::GetAllFuncCustData
7296 * Gets all custom data items for the specified Function
7299 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7300 ITypeInfo2 * iface,
7301 UINT index,
7302 CUSTDATA *pCustData)
7304 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7305 TLBCustData *pCData;
7306 TLBFuncDesc * pFDesc;
7307 UINT i;
7308 TRACE("(%p) index %d\n", This, index);
7309 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7310 pFDesc=pFDesc->next)
7312 if(pFDesc){
7313 pCustData->prgCustData =
7314 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7315 if(pCustData->prgCustData ){
7316 pCustData->cCustData=pFDesc->ctCustData;
7317 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7318 pCData = pCData->next){
7319 pCustData->prgCustData[i].guid=pCData->guid;
7320 VariantCopy(& pCustData->prgCustData[i].varValue,
7321 & pCData->data);
7323 }else{
7324 ERR(" OUT OF MEMORY!\n");
7325 return E_OUTOFMEMORY;
7327 return S_OK;
7329 return TYPE_E_ELEMENTNOTFOUND;
7332 /* ITypeInfo2::GetAllParamCustData
7334 * Gets all custom data items for the Functions
7337 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7338 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7340 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7341 TLBCustData *pCData=NULL;
7342 TLBFuncDesc * pFDesc;
7343 UINT i;
7344 TRACE("(%p) index %d\n", This, indexFunc);
7345 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7346 pFDesc=pFDesc->next)
7348 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7349 pCustData->prgCustData =
7350 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7351 sizeof(CUSTDATAITEM));
7352 if(pCustData->prgCustData ){
7353 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7354 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7355 pCData; i++, pCData = pCData->next){
7356 pCustData->prgCustData[i].guid=pCData->guid;
7357 VariantCopy(& pCustData->prgCustData[i].varValue,
7358 & pCData->data);
7360 }else{
7361 ERR(" OUT OF MEMORY!\n");
7362 return E_OUTOFMEMORY;
7364 return S_OK;
7366 return TYPE_E_ELEMENTNOTFOUND;
7369 /* ITypeInfo2::GetAllVarCustData
7371 * Gets all custom data items for the specified Variable
7374 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7375 UINT index, CUSTDATA *pCustData)
7377 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7378 TLBCustData *pCData;
7379 TLBVarDesc * pVDesc;
7380 UINT i;
7381 TRACE("(%p) index %d\n", This, index);
7382 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7383 pVDesc=pVDesc->next)
7385 if(pVDesc){
7386 pCustData->prgCustData =
7387 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7388 if(pCustData->prgCustData ){
7389 pCustData->cCustData=pVDesc->ctCustData;
7390 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7391 pCData = pCData->next){
7392 pCustData->prgCustData[i].guid=pCData->guid;
7393 VariantCopy(& pCustData->prgCustData[i].varValue,
7394 & pCData->data);
7396 }else{
7397 ERR(" OUT OF MEMORY!\n");
7398 return E_OUTOFMEMORY;
7400 return S_OK;
7402 return TYPE_E_ELEMENTNOTFOUND;
7405 /* ITypeInfo2::GetAllImplCustData
7407 * Gets all custom data items for the specified implementation type
7410 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7411 ITypeInfo2 * iface,
7412 UINT index,
7413 CUSTDATA *pCustData)
7415 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7416 TLBCustData *pCData;
7417 TLBImplType * pRDesc;
7418 UINT i;
7419 TRACE("(%p) index %d\n", This, index);
7420 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7421 pRDesc=pRDesc->next)
7423 if(pRDesc){
7424 pCustData->prgCustData =
7425 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7426 if(pCustData->prgCustData ){
7427 pCustData->cCustData=pRDesc->ctCustData;
7428 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7429 pCData = pCData->next){
7430 pCustData->prgCustData[i].guid=pCData->guid;
7431 VariantCopy(& pCustData->prgCustData[i].varValue,
7432 & pCData->data);
7434 }else{
7435 ERR(" OUT OF MEMORY!\n");
7436 return E_OUTOFMEMORY;
7438 return S_OK;
7440 return TYPE_E_ELEMENTNOTFOUND;
7443 static const ITypeInfo2Vtbl tinfvt =
7446 ITypeInfo_fnQueryInterface,
7447 ITypeInfo_fnAddRef,
7448 ITypeInfo_fnRelease,
7450 ITypeInfo_fnGetTypeAttr,
7451 ITypeInfo_fnGetTypeComp,
7452 ITypeInfo_fnGetFuncDesc,
7453 ITypeInfo_fnGetVarDesc,
7454 ITypeInfo_fnGetNames,
7455 ITypeInfo_fnGetRefTypeOfImplType,
7456 ITypeInfo_fnGetImplTypeFlags,
7457 ITypeInfo_fnGetIDsOfNames,
7458 ITypeInfo_fnInvoke,
7459 ITypeInfo_fnGetDocumentation,
7460 ITypeInfo_fnGetDllEntry,
7461 ITypeInfo_fnGetRefTypeInfo,
7462 ITypeInfo_fnAddressOfMember,
7463 ITypeInfo_fnCreateInstance,
7464 ITypeInfo_fnGetMops,
7465 ITypeInfo_fnGetContainingTypeLib,
7466 ITypeInfo_fnReleaseTypeAttr,
7467 ITypeInfo_fnReleaseFuncDesc,
7468 ITypeInfo_fnReleaseVarDesc,
7470 ITypeInfo2_fnGetTypeKind,
7471 ITypeInfo2_fnGetTypeFlags,
7472 ITypeInfo2_fnGetFuncIndexOfMemId,
7473 ITypeInfo2_fnGetVarIndexOfMemId,
7474 ITypeInfo2_fnGetCustData,
7475 ITypeInfo2_fnGetFuncCustData,
7476 ITypeInfo2_fnGetParamCustData,
7477 ITypeInfo2_fnGetVarCustData,
7478 ITypeInfo2_fnGetImplTypeCustData,
7479 ITypeInfo2_fnGetDocumentation2,
7480 ITypeInfo2_fnGetAllCustData,
7481 ITypeInfo2_fnGetAllFuncCustData,
7482 ITypeInfo2_fnGetAllParamCustData,
7483 ITypeInfo2_fnGetAllVarCustData,
7484 ITypeInfo2_fnGetAllImplTypeCustData,
7487 /******************************************************************************
7488 * CreateDispTypeInfo [OLEAUT32.31]
7490 * Build type information for an object so it can be called through an
7491 * IDispatch interface.
7493 * RETURNS
7494 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7495 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7497 * NOTES
7498 * This call allows an objects methods to be accessed through IDispatch, by
7499 * building an ITypeInfo object that IDispatch can use to call through.
7501 HRESULT WINAPI CreateDispTypeInfo(
7502 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7503 LCID lcid, /* [I] Locale Id */
7504 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7506 ITypeInfoImpl *pTIClass, *pTIIface;
7507 ITypeLibImpl *pTypeLibImpl;
7508 unsigned int param, func;
7509 TLBFuncDesc **ppFuncDesc;
7510 TLBRefType *ref;
7512 TRACE("\n");
7513 pTypeLibImpl = TypeLibImpl_Constructor();
7514 if (!pTypeLibImpl) return E_FAIL;
7516 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7517 pTIIface->pTypeLib = pTypeLibImpl;
7518 pTIIface->index = 0;
7519 pTIIface->Name = NULL;
7520 pTIIface->dwHelpContext = -1;
7521 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7522 pTIIface->TypeAttr.lcid = lcid;
7523 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7524 pTIIface->TypeAttr.wMajorVerNum = 0;
7525 pTIIface->TypeAttr.wMinorVerNum = 0;
7526 pTIIface->TypeAttr.cbAlignment = 2;
7527 pTIIface->TypeAttr.cbSizeInstance = -1;
7528 pTIIface->TypeAttr.cbSizeVft = -1;
7529 pTIIface->TypeAttr.cFuncs = 0;
7530 pTIIface->TypeAttr.cImplTypes = 0;
7531 pTIIface->TypeAttr.cVars = 0;
7532 pTIIface->TypeAttr.wTypeFlags = 0;
7534 ppFuncDesc = &pTIIface->funclist;
7535 for(func = 0; func < pidata->cMembers; func++) {
7536 METHODDATA *md = pidata->pmethdata + func;
7537 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7538 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7539 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7540 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7541 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7542 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7543 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7544 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7545 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7546 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7547 (*ppFuncDesc)->funcdesc.cScodes = 0;
7548 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7549 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7550 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7551 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7552 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7553 md->cArgs * sizeof(ELEMDESC));
7554 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7555 md->cArgs * sizeof(TLBParDesc));
7556 for(param = 0; param < md->cArgs; param++) {
7557 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7558 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7560 (*ppFuncDesc)->helpcontext = 0;
7561 (*ppFuncDesc)->HelpStringContext = 0;
7562 (*ppFuncDesc)->HelpString = NULL;
7563 (*ppFuncDesc)->Entry = NULL;
7564 (*ppFuncDesc)->ctCustData = 0;
7565 (*ppFuncDesc)->pCustData = NULL;
7566 (*ppFuncDesc)->next = NULL;
7567 pTIIface->TypeAttr.cFuncs++;
7568 ppFuncDesc = &(*ppFuncDesc)->next;
7571 dump_TypeInfo(pTIIface);
7573 pTypeLibImpl->pTypeInfo = pTIIface;
7574 pTypeLibImpl->TypeInfoCount++;
7576 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7577 pTIClass->pTypeLib = pTypeLibImpl;
7578 pTIClass->index = 1;
7579 pTIClass->Name = NULL;
7580 pTIClass->dwHelpContext = -1;
7581 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7582 pTIClass->TypeAttr.lcid = lcid;
7583 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7584 pTIClass->TypeAttr.wMajorVerNum = 0;
7585 pTIClass->TypeAttr.wMinorVerNum = 0;
7586 pTIClass->TypeAttr.cbAlignment = 2;
7587 pTIClass->TypeAttr.cbSizeInstance = -1;
7588 pTIClass->TypeAttr.cbSizeVft = -1;
7589 pTIClass->TypeAttr.cFuncs = 0;
7590 pTIClass->TypeAttr.cImplTypes = 1;
7591 pTIClass->TypeAttr.cVars = 0;
7592 pTIClass->TypeAttr.wTypeFlags = 0;
7594 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7595 pTIClass->impltypelist->hRef = 0;
7597 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7598 ref->index = 0;
7599 ref->reference = 0;
7600 ref->pImpTLInfo = TLB_REF_INTERNAL;
7601 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7603 dump_TypeInfo(pTIClass);
7605 pTIIface->next = pTIClass;
7606 pTypeLibImpl->TypeInfoCount++;
7608 *pptinfo = (ITypeInfo*)pTIClass;
7610 ITypeInfo_AddRef(*pptinfo);
7611 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7613 return S_OK;
7617 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7619 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7621 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7624 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7626 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7628 return ITypeInfo_AddRef((ITypeInfo *)This);
7631 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7633 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7635 return ITypeInfo_Release((ITypeInfo *)This);
7638 static HRESULT WINAPI ITypeComp_fnBind(
7639 ITypeComp * iface,
7640 OLECHAR * szName,
7641 ULONG lHash,
7642 WORD wFlags,
7643 ITypeInfo ** ppTInfo,
7644 DESCKIND * pDescKind,
7645 BINDPTR * pBindPtr)
7647 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7648 const TLBFuncDesc *pFDesc;
7649 const TLBVarDesc *pVDesc;
7650 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7652 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7654 *pDescKind = DESCKIND_NONE;
7655 pBindPtr->lpfuncdesc = NULL;
7656 *ppTInfo = NULL;
7658 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7659 if (!strcmpiW(pFDesc->Name, szName)) {
7660 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7661 break;
7662 else
7663 /* name found, but wrong flags */
7664 hr = TYPE_E_TYPEMISMATCH;
7667 if (pFDesc)
7669 HRESULT hr = TLB_AllocAndInitFuncDesc(
7670 &pFDesc->funcdesc,
7671 &pBindPtr->lpfuncdesc,
7672 This->TypeAttr.typekind == TKIND_DISPATCH);
7673 if (FAILED(hr))
7674 return hr;
7675 *pDescKind = DESCKIND_FUNCDESC;
7676 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7677 ITypeInfo_AddRef(*ppTInfo);
7678 return S_OK;
7679 } else {
7680 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7681 if (!strcmpiW(pVDesc->Name, szName)) {
7682 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7683 if (FAILED(hr))
7684 return hr;
7685 *pDescKind = DESCKIND_VARDESC;
7686 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7687 ITypeInfo_AddRef(*ppTInfo);
7688 return S_OK;
7692 /* FIXME: search each inherited interface, not just the first */
7693 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7694 /* recursive search */
7695 ITypeInfo *pTInfo;
7696 ITypeComp *pTComp;
7697 HRESULT hr;
7698 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7699 if (SUCCEEDED(hr))
7701 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7702 ITypeInfo_Release(pTInfo);
7704 if (SUCCEEDED(hr))
7706 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7707 ITypeComp_Release(pTComp);
7708 return hr;
7710 WARN("Could not search inherited interface!\n");
7712 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7713 return hr;
7716 static HRESULT WINAPI ITypeComp_fnBindType(
7717 ITypeComp * iface,
7718 OLECHAR * szName,
7719 ULONG lHash,
7720 ITypeInfo ** ppTInfo,
7721 ITypeComp ** ppTComp)
7723 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7725 /* strange behaviour (does nothing) but like the
7726 * original */
7728 if (!ppTInfo || !ppTComp)
7729 return E_POINTER;
7731 *ppTInfo = NULL;
7732 *ppTComp = NULL;
7734 return S_OK;
7737 static const ITypeCompVtbl tcompvt =
7740 ITypeComp_fnQueryInterface,
7741 ITypeComp_fnAddRef,
7742 ITypeComp_fnRelease,
7744 ITypeComp_fnBind,
7745 ITypeComp_fnBindType