openal32: Remove the ALCcontext wrapper.
[wine.git] / dlls / oleaut32 / typelib.c
blob468f00111926561bc10f0788fdfc86bca56a3980
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 /* Register all dispinterfaces (which includes dual interfaces) and
695 oleautomation interfaces */
696 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
697 kind == TKIND_DISPATCH)
699 /* register interface<->typelib coupling */
700 get_interface_key( &tattr->guid, keyName );
701 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
702 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
704 if (name)
705 RegSetValueExW(key, NULL, 0, REG_SZ,
706 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
708 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
709 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
710 RegSetValueExW(subKey, NULL, 0, REG_SZ,
711 (const BYTE *)PSOA, sizeof PSOA);
712 RegCloseKey(subKey);
715 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
716 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
717 RegSetValueExW(subKey, NULL, 0, REG_SZ,
718 (const BYTE *)PSOA, sizeof PSOA);
719 RegCloseKey(subKey);
722 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
723 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
725 WCHAR buffer[40];
726 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
727 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
729 StringFromGUID2(&attr->guid, buffer, 40);
730 RegSetValueExW(subKey, NULL, 0, REG_SZ,
731 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
732 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
733 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
734 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
735 RegCloseKey(subKey);
738 RegCloseKey(key);
742 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
745 ITypeInfo_Release(tinfo);
748 SysFreeString(name);
752 ITypeLib_ReleaseTLibAttr(ptlib, attr);
754 return res;
758 /******************************************************************************
759 * UnRegisterTypeLib [OLEAUT32.186]
760 * Removes information about a type library from the System Registry
761 * NOTES
763 * RETURNS
764 * Success: S_OK
765 * Failure: Status
767 HRESULT WINAPI UnRegisterTypeLib(
768 REFGUID libid, /* [in] Guid of the library */
769 WORD wVerMajor, /* [in] major version */
770 WORD wVerMinor, /* [in] minor version */
771 LCID lcid, /* [in] locale id */
772 SYSKIND syskind)
774 BSTR tlibPath = NULL;
775 DWORD tmpLength;
776 WCHAR keyName[60];
777 WCHAR subKeyName[50];
778 int result = S_OK;
779 DWORD i = 0;
780 BOOL deleteOtherStuff;
781 HKEY key = NULL;
782 HKEY subKey = NULL;
783 TYPEATTR* typeAttr = NULL;
784 TYPEKIND kind;
785 ITypeInfo* typeInfo = NULL;
786 ITypeLib* typeLib = NULL;
787 int numTypes;
789 TRACE("(IID: %s)\n",debugstr_guid(libid));
791 /* Create the path to the key */
792 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
794 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
796 TRACE("Unsupported syskind %i\n", syskind);
797 result = E_INVALIDARG;
798 goto end;
801 /* get the path to the typelib on disk */
802 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
803 result = E_INVALIDARG;
804 goto end;
807 /* Try and open the key to the type library. */
808 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
809 result = E_INVALIDARG;
810 goto end;
813 /* Try and load the type library */
814 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
815 result = TYPE_E_INVALIDSTATE;
816 goto end;
819 /* remove any types registered with this typelib */
820 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
821 for (i=0; i<numTypes; i++) {
822 /* get the kind of type */
823 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
824 goto enddeleteloop;
827 /* skip non-interfaces, and get type info for the type */
828 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
829 goto enddeleteloop;
831 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
832 goto enddeleteloop;
834 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
835 goto enddeleteloop;
838 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
839 kind == TKIND_DISPATCH)
841 /* the path to the type */
842 get_interface_key( &typeAttr->guid, subKeyName );
844 /* Delete its bits */
845 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
846 goto enddeleteloop;
848 RegDeleteKeyW(subKey, ProxyStubClsidW);
849 RegDeleteKeyW(subKey, ProxyStubClsid32W);
850 RegDeleteKeyW(subKey, TypeLibW);
851 RegCloseKey(subKey);
852 subKey = NULL;
853 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
856 enddeleteloop:
857 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
858 typeAttr = NULL;
859 if (typeInfo) ITypeInfo_Release(typeInfo);
860 typeInfo = NULL;
863 /* Now, delete the type library path subkey */
864 get_lcid_subkey( lcid, syskind, subKeyName );
865 RegDeleteKeyW(key, subKeyName);
866 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
867 RegDeleteKeyW(key, subKeyName);
869 /* check if there is anything besides the FLAGS/HELPDIR keys.
870 If there is, we don't delete them */
871 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
872 deleteOtherStuff = TRUE;
873 i = 0;
874 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
875 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
877 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
878 if (!strcmpW(subKeyName, FLAGSW)) continue;
879 if (!strcmpW(subKeyName, HELPDIRW)) continue;
880 deleteOtherStuff = FALSE;
881 break;
884 /* only delete the other parts of the key if we're absolutely sure */
885 if (deleteOtherStuff) {
886 RegDeleteKeyW(key, FLAGSW);
887 RegDeleteKeyW(key, HELPDIRW);
888 RegCloseKey(key);
889 key = NULL;
891 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
892 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
893 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
896 end:
897 SysFreeString(tlibPath);
898 if (typeLib) ITypeLib_Release(typeLib);
899 if (subKey) RegCloseKey(subKey);
900 if (key) RegCloseKey(key);
901 return result;
904 /*======================= ITypeLib implementation =======================*/
906 typedef struct tagTLBCustData
908 GUID guid;
909 VARIANT data;
910 struct tagTLBCustData* next;
911 } TLBCustData;
913 /* data structure for import typelibs */
914 typedef struct tagTLBImpLib
916 int offset; /* offset in the file (MSFT)
917 offset in nametable (SLTG)
918 just used to identify library while reading
919 data from file */
920 GUID guid; /* libid */
921 BSTR name; /* name */
923 LCID lcid; /* lcid of imported typelib */
925 WORD wVersionMajor; /* major version number */
926 WORD wVersionMinor; /* minor version number */
928 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
929 NULL if not yet loaded */
930 struct tagTLBImpLib * next;
931 } TLBImpLib;
933 /* internal ITypeLib data */
934 typedef struct tagITypeLibImpl
936 const ITypeLib2Vtbl *lpVtbl;
937 const ITypeCompVtbl *lpVtblTypeComp;
938 LONG ref;
939 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
940 LCID lcid;
942 /* strings can be stored in tlb as multibyte strings BUT they are *always*
943 * exported to the application as a UNICODE string.
945 BSTR Name;
946 BSTR DocString;
947 BSTR HelpFile;
948 BSTR HelpStringDll;
949 DWORD dwHelpContext;
950 int TypeInfoCount; /* nr of typeinfo's in librarry */
951 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
952 int ctCustData; /* number of items in cust data list */
953 TLBCustData * pCustData; /* linked list to cust data */
954 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
955 int ctTypeDesc; /* number of items in type desc array */
956 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
957 library. Only used while reading MSFT
958 typelibs */
959 struct list ref_list; /* list of ref types in this typelib */
960 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
963 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
964 struct tagITypeLibImpl *next, *prev;
965 WCHAR *path;
966 INT index;
967 } ITypeLibImpl;
969 static const ITypeLib2Vtbl tlbvt;
970 static const ITypeCompVtbl tlbtcvt;
972 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
974 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
977 /* ITypeLib methods */
978 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
979 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
981 /*======================= ITypeInfo implementation =======================*/
983 /* data for referenced types */
984 typedef struct tagTLBRefType
986 INT index; /* Type index for internal ref or for external ref
987 it the format is SLTG. -2 indicates to
988 use guid */
990 GUID guid; /* guid of the referenced type */
991 /* if index == TLB_REF_USE_GUID */
993 HREFTYPE reference; /* The href of this ref */
994 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
995 TLB_REF_INTERNAL for internal refs
996 TLB_REF_NOT_FOUND for broken refs */
998 struct list entry;
999 } TLBRefType;
1001 #define TLB_REF_USE_GUID -2
1003 #define TLB_REF_INTERNAL (void*)-2
1004 #define TLB_REF_NOT_FOUND (void*)-1
1006 /* internal Parameter data */
1007 typedef struct tagTLBParDesc
1009 BSTR Name;
1010 int ctCustData;
1011 TLBCustData * pCustData; /* linked list to cust data */
1012 } TLBParDesc;
1014 /* internal Function data */
1015 typedef struct tagTLBFuncDesc
1017 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1018 BSTR Name; /* the name of this function */
1019 TLBParDesc *pParamDesc; /* array with param names and custom data */
1020 int helpcontext;
1021 int HelpStringContext;
1022 BSTR HelpString;
1023 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1024 int ctCustData;
1025 TLBCustData * pCustData; /* linked list to cust data; */
1026 struct tagTLBFuncDesc * next;
1027 } TLBFuncDesc;
1029 /* internal Variable data */
1030 typedef struct tagTLBVarDesc
1032 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1033 BSTR Name; /* the name of this variable */
1034 int HelpContext;
1035 int HelpStringContext; /* FIXME: where? */
1036 BSTR HelpString;
1037 int ctCustData;
1038 TLBCustData * pCustData;/* linked list to cust data; */
1039 struct tagTLBVarDesc * next;
1040 } TLBVarDesc;
1042 /* internal implemented interface data */
1043 typedef struct tagTLBImplType
1045 HREFTYPE hRef; /* hRef of interface */
1046 int implflags; /* IMPLFLAG_*s */
1047 int ctCustData;
1048 TLBCustData * pCustData;/* linked list to custom data; */
1049 struct tagTLBImplType *next;
1050 } TLBImplType;
1052 /* internal TypeInfo data */
1053 typedef struct tagITypeInfoImpl
1055 const ITypeInfo2Vtbl *lpVtbl;
1056 const ITypeCompVtbl *lpVtblTypeComp;
1057 LONG ref;
1058 BOOL not_attached_to_typelib;
1059 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1060 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1061 int index; /* index in this typelib; */
1062 HREFTYPE hreftype; /* hreftype for app object binding */
1063 /* type libs seem to store the doc strings in ascii
1064 * so why should we do it in unicode?
1066 BSTR Name;
1067 BSTR DocString;
1068 BSTR DllName;
1069 DWORD dwHelpContext;
1070 DWORD dwHelpStringContext;
1072 /* functions */
1073 TLBFuncDesc * funclist; /* linked list with function descriptions */
1075 /* variables */
1076 TLBVarDesc * varlist; /* linked list with variable descriptions */
1078 /* Implemented Interfaces */
1079 TLBImplType * impltypelist;
1081 int ctCustData;
1082 TLBCustData * pCustData; /* linked list to cust data; */
1083 struct tagITypeInfoImpl * next;
1084 } ITypeInfoImpl;
1086 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1088 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1091 static const ITypeInfo2Vtbl tinfvt;
1092 static const ITypeCompVtbl tcompvt;
1094 static ITypeInfo2 * ITypeInfo_Constructor(void);
1095 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This);
1097 typedef struct tagTLBContext
1099 unsigned int oStart; /* start of TLB in file */
1100 unsigned int pos; /* current pos */
1101 unsigned int length; /* total length */
1102 void *mapping; /* memory mapping */
1103 MSFT_SegDir * pTblDir;
1104 ITypeLibImpl* pLibInfo;
1105 } TLBContext;
1108 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1111 debug
1113 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1114 if (pTD->vt & VT_RESERVED)
1115 szVarType += strlen(strcpy(szVarType, "reserved | "));
1116 if (pTD->vt & VT_BYREF)
1117 szVarType += strlen(strcpy(szVarType, "ref to "));
1118 if (pTD->vt & VT_ARRAY)
1119 szVarType += strlen(strcpy(szVarType, "array of "));
1120 if (pTD->vt & VT_VECTOR)
1121 szVarType += strlen(strcpy(szVarType, "vector of "));
1122 switch(pTD->vt & VT_TYPEMASK) {
1123 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1124 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1125 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1126 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1127 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1128 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1129 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1130 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1131 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1132 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1133 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1134 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1135 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1136 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1137 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1138 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1139 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1140 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1141 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1142 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1143 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1144 pTD->u.hreftype); break;
1145 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1146 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1147 case VT_PTR: sprintf(szVarType, "ptr to ");
1148 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1149 break;
1150 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1151 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1152 break;
1153 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1154 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1155 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1156 break;
1158 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1162 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1163 char buf[200];
1164 USHORT flags = edesc->u.paramdesc.wParamFlags;
1165 dump_TypeDesc(&edesc->tdesc,buf);
1166 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1167 MESSAGE("\t\tu.paramdesc.wParamFlags");
1168 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1169 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1170 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1171 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1172 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1173 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1174 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1175 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1176 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1178 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1179 int i;
1180 MESSAGE("memid is %08x\n",funcdesc->memid);
1181 for (i=0;i<funcdesc->cParams;i++) {
1182 MESSAGE("Param %d:\n",i);
1183 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1185 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1186 switch (funcdesc->funckind) {
1187 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1188 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1189 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1190 case FUNC_STATIC: MESSAGE("static");break;
1191 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1192 default: MESSAGE("unknown");break;
1194 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1195 switch (funcdesc->invkind) {
1196 case INVOKE_FUNC: MESSAGE("func");break;
1197 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1198 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1199 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1201 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1202 switch (funcdesc->callconv) {
1203 case CC_CDECL: MESSAGE("cdecl");break;
1204 case CC_PASCAL: MESSAGE("pascal");break;
1205 case CC_STDCALL: MESSAGE("stdcall");break;
1206 case CC_SYSCALL: MESSAGE("syscall");break;
1207 default:break;
1209 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1210 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1211 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1213 MESSAGE("\telemdescFunc (return value type):\n");
1214 dump_ELEMDESC(&funcdesc->elemdescFunc);
1217 static const char * const typekind_desc[] =
1219 "TKIND_ENUM",
1220 "TKIND_RECORD",
1221 "TKIND_MODULE",
1222 "TKIND_INTERFACE",
1223 "TKIND_DISPATCH",
1224 "TKIND_COCLASS",
1225 "TKIND_ALIAS",
1226 "TKIND_UNION",
1227 "TKIND_MAX"
1230 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1232 int i;
1233 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1234 for (i=0;i<pfd->funcdesc.cParams;i++)
1235 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1238 dump_FUNCDESC(&(pfd->funcdesc));
1240 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1241 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1243 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1245 while (pfd)
1247 dump_TLBFuncDescOne(pfd);
1248 pfd = pfd->next;
1251 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1253 while (pvd)
1255 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1256 pvd = pvd->next;
1260 static void dump_TLBImpLib(const TLBImpLib *import)
1262 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1263 debugstr_w(import->name));
1264 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1265 import->wVersionMinor, import->lcid, import->offset);
1268 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1270 TLBRefType *ref;
1272 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1274 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1275 if(ref->index == -1)
1276 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1277 else
1278 TRACE_(typelib)("type no: %d\n", ref->index);
1280 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1282 TRACE_(typelib)("in lib\n");
1283 dump_TLBImpLib(ref->pImpTLInfo);
1288 static void dump_TLBImplType(const TLBImplType * impl)
1290 while (impl) {
1291 TRACE_(typelib)(
1292 "implementing/inheriting interface hRef = %x implflags %x\n",
1293 impl->hRef, impl->implflags);
1294 impl = impl->next;
1298 static void dump_Variant(const VARIANT * pvar)
1300 SYSTEMTIME st;
1302 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1304 if (pvar)
1306 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1307 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1309 TRACE(",%p", V_BYREF(pvar));
1311 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1313 TRACE(",%p", V_ARRAY(pvar));
1315 else switch (V_TYPE(pvar))
1317 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1318 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1319 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1320 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1321 case VT_INT:
1322 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1323 case VT_UINT:
1324 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1325 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1326 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1327 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1328 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1329 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1330 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1331 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1332 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1333 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1334 V_CY(pvar).s.Lo); break;
1335 case VT_DATE:
1336 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1337 TRACE(",<invalid>");
1338 else
1339 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1340 st.wHour, st.wMinute, st.wSecond);
1341 break;
1342 case VT_ERROR:
1343 case VT_VOID:
1344 case VT_USERDEFINED:
1345 case VT_EMPTY:
1346 case VT_NULL: break;
1347 default: TRACE(",?"); break;
1350 TRACE("}\n");
1353 static void dump_DispParms(const DISPPARAMS * pdp)
1355 unsigned int index;
1357 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1359 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1361 TRACE("named args:\n");
1362 for (index = 0; index < pdp->cNamedArgs; index++)
1363 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1366 if (pdp->cArgs && pdp->rgvarg)
1368 TRACE("args:\n");
1369 for (index = 0; index < pdp->cArgs; index++)
1370 dump_Variant( &pdp->rgvarg[index] );
1374 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1376 TRACE("%p ref=%u\n", pty, pty->ref);
1377 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1378 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1379 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1380 TRACE("fct:%u var:%u impl:%u\n",
1381 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1382 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1383 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1384 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1385 if (TRACE_ON(ole))
1386 dump_TLBFuncDesc(pty->funclist);
1387 dump_TLBVarDesc(pty->varlist);
1388 dump_TLBImplType(pty->impltypelist);
1391 static void dump_VARDESC(const VARDESC *v)
1393 MESSAGE("memid %d\n",v->memid);
1394 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1395 MESSAGE("oInst %d\n",v->u.oInst);
1396 dump_ELEMDESC(&(v->elemdescVar));
1397 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1398 MESSAGE("varkind %d\n",v->varkind);
1401 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1403 /* VT_LPWSTR is largest type that */
1404 /* may appear in type description*/
1405 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1406 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1407 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1408 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1409 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1410 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1411 {{0},30},{{0},31}
1414 static void TLB_abort(void)
1416 DebugBreak();
1419 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1420 static void * TLB_Alloc(unsigned size)
1422 void * ret;
1423 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1424 /* FIXME */
1425 ERR("cannot allocate memory\n");
1427 return ret;
1430 static void TLB_Free(void * ptr)
1432 HeapFree(GetProcessHeap(), 0, ptr);
1435 /* returns the size required for a deep copy of a typedesc into a
1436 * flat buffer */
1437 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1439 SIZE_T size = 0;
1441 if (alloc_initial_space)
1442 size += sizeof(TYPEDESC);
1444 switch (tdesc->vt)
1446 case VT_PTR:
1447 case VT_SAFEARRAY:
1448 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1449 break;
1450 case VT_CARRAY:
1451 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1452 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1453 break;
1455 return size;
1458 /* deep copy a typedesc into a flat buffer */
1459 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1461 if (!dest)
1463 dest = buffer;
1464 buffer = (char *)buffer + sizeof(TYPEDESC);
1467 *dest = *src;
1469 switch (src->vt)
1471 case VT_PTR:
1472 case VT_SAFEARRAY:
1473 dest->u.lptdesc = buffer;
1474 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1475 break;
1476 case VT_CARRAY:
1477 dest->u.lpadesc = buffer;
1478 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1479 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1480 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1481 break;
1483 return buffer;
1486 /* free custom data allocated by MSFT_CustData */
1487 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1489 TLBCustData *pCustDataNext;
1490 for (; pCustData; pCustData = pCustDataNext)
1492 VariantClear(&pCustData->data);
1494 pCustDataNext = pCustData->next;
1495 TLB_Free(pCustData);
1499 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1501 DWORD len;
1502 BSTR ret;
1504 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1505 ret = SysAllocStringLen(NULL, len - 1);
1506 if (!ret) return ret;
1507 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1508 return ret;
1511 /**********************************************************************
1513 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1515 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1517 return pcx->pos;
1520 static inline void MSFT_Seek(TLBContext *pcx, long where)
1522 if (where != DO_NOT_SEEK)
1524 where += pcx->oStart;
1525 if (where > pcx->length)
1527 /* FIXME */
1528 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1529 TLB_abort();
1531 pcx->pos = where;
1535 /* read function */
1536 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1538 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1539 pcx->pos, count, pcx->oStart, pcx->length, where);
1541 MSFT_Seek(pcx, where);
1542 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1543 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1544 pcx->pos += count;
1545 return count;
1548 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1549 long where )
1551 DWORD ret;
1553 ret = MSFT_Read(buffer, count, pcx, where);
1554 FromLEDWords(buffer, ret);
1556 return ret;
1559 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1560 long where )
1562 DWORD ret;
1564 ret = MSFT_Read(buffer, count, pcx, where);
1565 FromLEWords(buffer, ret);
1567 return ret;
1570 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1572 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1573 memset(pGuid,0, sizeof(GUID));
1574 return;
1576 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1577 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1578 pGuid->Data2 = FromLEWord(pGuid->Data2);
1579 pGuid->Data3 = FromLEWord(pGuid->Data3);
1580 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1583 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1585 MSFT_NameIntro niName;
1587 if (offset < 0)
1589 ERR_(typelib)("bad offset %d\n", offset);
1590 return -1;
1593 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1594 pcx->pTblDir->pNametab.offset+offset);
1596 return niName.hreftype;
1599 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1601 char * name;
1602 MSFT_NameIntro niName;
1603 int lengthInChars;
1604 BSTR bstrName = NULL;
1606 if (offset < 0)
1608 ERR_(typelib)("bad offset %d\n", offset);
1609 return NULL;
1611 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1612 pcx->pTblDir->pNametab.offset+offset);
1613 niName.namelen &= 0xFF; /* FIXME: correct ? */
1614 name=TLB_Alloc((niName.namelen & 0xff) +1);
1615 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1616 name[niName.namelen & 0xff]='\0';
1618 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1619 name, -1, NULL, 0);
1621 /* no invalid characters in string */
1622 if (lengthInChars)
1624 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1626 /* don't check for invalid character since this has been done previously */
1627 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1629 TLB_Free(name);
1631 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1632 return bstrName;
1635 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1637 char * string;
1638 INT16 length;
1639 int lengthInChars;
1640 BSTR bstr = NULL;
1642 if(offset<0) return NULL;
1643 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1644 if(length <= 0) return 0;
1645 string=TLB_Alloc(length +1);
1646 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1647 string[length]='\0';
1649 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1650 string, -1, NULL, 0);
1652 /* no invalid characters in string */
1653 if (lengthInChars)
1655 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1657 /* don't check for invalid character since this has been done previously */
1658 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1660 TLB_Free(string);
1662 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1663 return bstr;
1666 * read a value and fill a VARIANT structure
1668 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1670 int size;
1672 TRACE_(typelib)("\n");
1674 if(offset <0) { /* data are packed in here */
1675 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1676 V_I4(pVar) = offset & 0x3ffffff;
1677 return;
1679 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1680 pcx->pTblDir->pCustData.offset + offset );
1681 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1682 switch (V_VT(pVar)){
1683 case VT_EMPTY: /* FIXME: is this right? */
1684 case VT_NULL: /* FIXME: is this right? */
1685 case VT_I2 : /* this should not happen */
1686 case VT_I4 :
1687 case VT_R4 :
1688 case VT_ERROR :
1689 case VT_BOOL :
1690 case VT_I1 :
1691 case VT_UI1 :
1692 case VT_UI2 :
1693 case VT_UI4 :
1694 case VT_INT :
1695 case VT_UINT :
1696 case VT_VOID : /* FIXME: is this right? */
1697 case VT_HRESULT :
1698 size=4; break;
1699 case VT_R8 :
1700 case VT_CY :
1701 case VT_DATE :
1702 case VT_I8 :
1703 case VT_UI8 :
1704 case VT_DECIMAL : /* FIXME: is this right? */
1705 case VT_FILETIME :
1706 size=8;break;
1707 /* pointer types with known behaviour */
1708 case VT_BSTR :{
1709 char * ptr;
1710 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1711 if(size < 0) {
1712 char next;
1713 DWORD origPos = MSFT_Tell(pcx), nullPos;
1715 do {
1716 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1717 } while (next);
1718 nullPos = MSFT_Tell(pcx);
1719 size = nullPos - origPos;
1720 MSFT_Seek(pcx, origPos);
1722 ptr=TLB_Alloc(size);/* allocate temp buffer */
1723 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1724 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1725 /* FIXME: do we need a AtoW conversion here? */
1726 V_UNION(pVar, bstrVal[size])='\0';
1727 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1728 TLB_Free(ptr);
1730 size=-4; break;
1731 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1732 case VT_DISPATCH :
1733 case VT_VARIANT :
1734 case VT_UNKNOWN :
1735 case VT_PTR :
1736 case VT_SAFEARRAY :
1737 case VT_CARRAY :
1738 case VT_USERDEFINED :
1739 case VT_LPSTR :
1740 case VT_LPWSTR :
1741 case VT_BLOB :
1742 case VT_STREAM :
1743 case VT_STORAGE :
1744 case VT_STREAMED_OBJECT :
1745 case VT_STORED_OBJECT :
1746 case VT_BLOB_OBJECT :
1747 case VT_CF :
1748 case VT_CLSID :
1749 default:
1750 size=0;
1751 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1752 V_VT(pVar));
1755 if(size>0) /* (big|small) endian correct? */
1756 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1757 return;
1760 * create a linked list with custom data
1762 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1764 MSFT_CDGuid entry;
1765 TLBCustData* pNew;
1766 int count=0;
1768 TRACE_(typelib)("\n");
1770 while(offset >=0){
1771 count++;
1772 pNew=TLB_Alloc(sizeof(TLBCustData));
1773 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1774 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1775 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1776 /* add new custom data at head of the list */
1777 pNew->next=*ppCustData;
1778 *ppCustData=pNew;
1779 offset = entry.next;
1781 return count;
1784 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1785 ITypeInfoImpl *pTI)
1787 if(type <0)
1788 pTd->vt=type & VT_TYPEMASK;
1789 else
1790 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1792 if(pTd->vt == VT_USERDEFINED)
1793 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1795 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1798 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1800 /* resolve referenced type if any */
1801 while (lpTypeDesc)
1803 switch (lpTypeDesc->vt)
1805 case VT_PTR:
1806 lpTypeDesc = lpTypeDesc->u.lptdesc;
1807 break;
1809 case VT_CARRAY:
1810 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1811 break;
1813 case VT_USERDEFINED:
1814 MSFT_DoRefType(pcx, pTI->pTypeLib,
1815 lpTypeDesc->u.hreftype);
1817 lpTypeDesc = NULL;
1818 break;
1820 default:
1821 lpTypeDesc = NULL;
1826 static void
1827 MSFT_DoFuncs(TLBContext* pcx,
1828 ITypeInfoImpl* pTI,
1829 int cFuncs,
1830 int cVars,
1831 int offset,
1832 TLBFuncDesc** pptfd)
1835 * member information is stored in a data structure at offset
1836 * indicated by the memoffset field of the typeinfo structure
1837 * There are several distinctive parts.
1838 * The first part starts with a field that holds the total length
1839 * of this (first) part excluding this field. Then follow the records,
1840 * for each member there is one record.
1842 * The first entry is always the length of the record (including this
1843 * length word).
1844 * The rest of the record depends on the type of the member. If there is
1845 * a field indicating the member type (function, variable, interface, etc)
1846 * I have not found it yet. At this time we depend on the information
1847 * in the type info and the usual order how things are stored.
1849 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1850 * for each member;
1852 * Third is an equal sized array with file offsets to the name entry
1853 * of each member.
1855 * The fourth and last (?) part is an array with offsets to the records
1856 * in the first part of this file segment.
1859 int infolen, nameoffset, reclength, nrattributes, i;
1860 int recoffset = offset + sizeof(INT);
1862 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1863 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1864 TLBFuncDesc *ptfd_prev = NULL;
1866 TRACE_(typelib)("\n");
1868 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1870 for ( i = 0; i < cFuncs ; i++ )
1872 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1874 /* name, eventually add to a hash table */
1875 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1876 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1878 /* nameoffset is sometimes -1 on the second half of a propget/propput
1879 * pair of functions */
1880 if ((nameoffset == -1) && (i > 0))
1881 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1882 else
1883 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1885 /* read the function information record */
1886 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1888 reclength &= 0xffff;
1890 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1892 /* do the attributes */
1893 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1894 / sizeof(int);
1896 if ( nrattributes > 0 )
1898 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1900 if ( nrattributes > 1 )
1902 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1903 pFuncRec->OptAttr[1]) ;
1905 if ( nrattributes > 2 )
1907 if ( pFuncRec->FKCCIC & 0x2000 )
1909 if (!IS_INTRESOURCE(pFuncRec->OptAttr[2]))
1910 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->OptAttr[2]);
1911 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1913 else
1915 (*pptfd)->Entry = MSFT_ReadString(pcx,
1916 pFuncRec->OptAttr[2]);
1918 if( nrattributes > 5 )
1920 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1922 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1924 MSFT_CustData(pcx,
1925 pFuncRec->OptAttr[6],
1926 &(*pptfd)->pCustData);
1930 else
1932 (*pptfd)->Entry = (BSTR)-1;
1937 /* fill the FuncDesc Structure */
1938 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1939 offset + infolen + ( i + 1) * sizeof(INT));
1941 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1942 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1943 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1944 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1945 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1946 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1947 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1949 MSFT_GetTdesc(pcx,
1950 pFuncRec->DataType,
1951 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1952 pTI);
1953 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1955 /* do the parameters/arguments */
1956 if(pFuncRec->nrargs)
1958 int j = 0;
1959 MSFT_ParameterInfo paraminfo;
1961 (*pptfd)->funcdesc.lprgelemdescParam =
1962 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1964 (*pptfd)->pParamDesc =
1965 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1967 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1968 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1970 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1972 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1974 MSFT_GetTdesc(pcx,
1975 paraminfo.DataType,
1976 &elemdesc->tdesc,
1977 pTI);
1979 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1981 /* name */
1982 if (paraminfo.oName == -1)
1983 /* this occurs for [propput] or [propget] methods, so
1984 * we should just set the name of the parameter to the
1985 * name of the method. */
1986 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1987 else
1988 (*pptfd)->pParamDesc[j].Name =
1989 MSFT_ReadName( pcx, paraminfo.oName );
1990 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1992 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1994 /* default value */
1995 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1996 (pFuncRec->FKCCIC & 0x1000) )
1998 INT* pInt = (INT *)((char *)pFuncRec +
1999 reclength -
2000 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
2002 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2004 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
2005 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2007 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2008 pInt[j], pcx);
2010 else
2011 elemdesc->u.paramdesc.pparamdescex = NULL;
2012 /* custom info */
2013 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2015 MSFT_CustData(pcx,
2016 pFuncRec->OptAttr[7+j],
2017 &(*pptfd)->pParamDesc[j].pCustData);
2020 /* SEEK value = jump to offset,
2021 * from there jump to the end of record,
2022 * go back by (j-1) arguments
2024 MSFT_ReadLEDWords( &paraminfo ,
2025 sizeof(MSFT_ParameterInfo), pcx,
2026 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2027 * sizeof(MSFT_ParameterInfo)));
2031 /* scode is not used: archaic win16 stuff FIXME: right? */
2032 (*pptfd)->funcdesc.cScodes = 0 ;
2033 (*pptfd)->funcdesc.lprgscode = NULL ;
2035 ptfd_prev = *pptfd;
2036 pptfd = & ((*pptfd)->next);
2037 recoffset += reclength;
2039 HeapFree(GetProcessHeap(), 0, recbuf);
2042 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2043 int cVars, int offset, TLBVarDesc ** pptvd)
2045 int infolen, nameoffset, reclength;
2046 char recbuf[256];
2047 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2048 int i;
2049 int recoffset;
2051 TRACE_(typelib)("\n");
2053 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2054 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2055 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2056 recoffset += offset+sizeof(INT);
2057 for(i=0;i<cVars;i++){
2058 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2059 /* name, eventually add to a hash table */
2060 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2061 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2062 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2063 /* read the variable information record */
2064 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2065 reclength &=0xff;
2066 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2067 /* Optional data */
2068 if(reclength >(6*sizeof(INT)) )
2069 (*pptvd)->HelpContext=pVarRec->HelpContext;
2070 if(reclength >(7*sizeof(INT)) )
2071 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2072 if(reclength >(8*sizeof(INT)) )
2073 if(reclength >(9*sizeof(INT)) )
2074 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2075 /* fill the VarDesc Structure */
2076 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2077 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2078 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2079 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2080 MSFT_GetTdesc(pcx, pVarRec->DataType,
2081 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2082 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2083 if(pVarRec->VarKind == VAR_CONST ){
2084 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2085 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2086 pVarRec->OffsValue, pcx);
2087 } else
2088 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2089 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2090 pptvd=&((*pptvd)->next);
2091 recoffset += reclength;
2094 /* fill in data for a hreftype (offset). When the referenced type is contained
2095 * in the typelib, it's just an (file) offset in the type info base dir.
2096 * If comes from import, it's an offset+1 in the ImpInfo table
2097 * */
2098 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2099 int offset)
2101 TLBRefType *ref;
2103 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2105 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2107 if(ref->reference == offset) return;
2110 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2111 list_add_tail(&pTL->ref_list, &ref->entry);
2113 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2114 /* external typelib */
2115 MSFT_ImpInfo impinfo;
2116 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2118 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2120 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2121 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2122 while (pImpLib){ /* search the known offsets of all import libraries */
2123 if(pImpLib->offset==impinfo.oImpFile) break;
2124 pImpLib=pImpLib->next;
2126 if(pImpLib){
2127 ref->reference = offset;
2128 ref->pImpTLInfo = pImpLib;
2129 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2130 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2131 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2132 ref->index = TLB_REF_USE_GUID;
2133 } else
2134 ref->index = impinfo.oGuid;
2135 }else{
2136 ERR("Cannot find a reference\n");
2137 ref->reference = -1;
2138 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2140 }else{
2141 /* in this typelib */
2142 ref->index = MSFT_HREFTYPE_INDEX(offset);
2143 ref->reference = offset;
2144 ref->pImpTLInfo = TLB_REF_INTERNAL;
2148 /* process Implemented Interfaces of a com class */
2149 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2150 int offset)
2152 int i;
2153 MSFT_RefRecord refrec;
2154 TLBImplType **ppImpl = &pTI->impltypelist;
2156 TRACE_(typelib)("\n");
2158 for(i=0;i<count;i++){
2159 if(offset<0) break; /* paranoia */
2160 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2161 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2162 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2163 (*ppImpl)->hRef = refrec.reftype;
2164 (*ppImpl)->implflags=refrec.flags;
2165 (*ppImpl)->ctCustData=
2166 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2167 offset=refrec.onext;
2168 ppImpl=&((*ppImpl)->next);
2172 * process a typeinfo record
2174 static ITypeInfoImpl * MSFT_DoTypeInfo(
2175 TLBContext *pcx,
2176 int count,
2177 ITypeLibImpl * pLibInfo)
2179 MSFT_TypeInfoBase tiBase;
2180 ITypeInfoImpl *ptiRet;
2182 TRACE_(typelib)("count=%u\n", count);
2184 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2185 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2186 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2188 /* this is where we are coming from */
2189 ptiRet->pTypeLib = pLibInfo;
2190 ptiRet->index=count;
2191 /* fill in the typeattr fields */
2193 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2194 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2195 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2196 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2197 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2198 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2199 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2200 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2201 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2202 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2203 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2204 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2205 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2206 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2207 MSFT_GetTdesc(pcx, tiBase.datatype1,
2208 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2210 /* FIXME: */
2211 /* IDLDESC idldescType; *//* never saw this one != zero */
2213 /* name, eventually add to a hash table */
2214 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2215 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2216 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2217 /* help info */
2218 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2219 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2220 ptiRet->dwHelpContext=tiBase.helpcontext;
2222 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2223 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2225 /* note: InfoType's Help file and HelpStringDll come from the containing
2226 * library. Further HelpString and Docstring appear to be the same thing :(
2228 /* functions */
2229 if(ptiRet->TypeAttr.cFuncs >0 )
2230 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2231 ptiRet->TypeAttr.cVars,
2232 tiBase.memoffset, & ptiRet->funclist);
2233 /* variables */
2234 if(ptiRet->TypeAttr.cVars >0 )
2235 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2236 ptiRet->TypeAttr.cVars,
2237 tiBase.memoffset, & ptiRet->varlist);
2238 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2239 switch(ptiRet->TypeAttr.typekind)
2241 case TKIND_COCLASS:
2242 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2243 tiBase.datatype1);
2244 break;
2245 case TKIND_DISPATCH:
2246 /* This is not -1 when the interface is a non-base dual interface or
2247 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2248 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2249 not this interface.
2252 if (tiBase.datatype1 != -1)
2254 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2255 ptiRet->impltypelist->hRef = tiBase.datatype1;
2256 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2258 break;
2259 default:
2260 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2261 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2262 ptiRet->impltypelist->hRef = tiBase.datatype1;
2263 break;
2266 ptiRet->ctCustData=
2267 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2269 TRACE_(typelib)("%s guid: %s kind:%s\n",
2270 debugstr_w(ptiRet->Name),
2271 debugstr_guid(&ptiRet->TypeAttr.guid),
2272 typekind_desc[ptiRet->TypeAttr.typekind]);
2273 if (TRACE_ON(typelib))
2274 dump_TypeInfo(ptiRet);
2276 return ptiRet;
2279 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2280 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2281 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2282 * tradeoff here.
2284 static ITypeLibImpl *tlb_cache_first;
2285 static CRITICAL_SECTION cache_section;
2286 static CRITICAL_SECTION_DEBUG cache_section_debug =
2288 0, 0, &cache_section,
2289 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2290 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2292 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2295 typedef struct TLB_PEFile
2297 const IUnknownVtbl *lpvtbl;
2298 LONG refs;
2299 HMODULE dll;
2300 HRSRC typelib_resource;
2301 HGLOBAL typelib_global;
2302 LPVOID typelib_base;
2303 } TLB_PEFile;
2305 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2307 if (IsEqualIID(riid, &IID_IUnknown))
2309 *ppv = iface;
2310 IUnknown_AddRef(iface);
2311 return S_OK;
2313 *ppv = NULL;
2314 return E_NOINTERFACE;
2317 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2319 TLB_PEFile *This = (TLB_PEFile *)iface;
2320 return InterlockedIncrement(&This->refs);
2323 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2325 TLB_PEFile *This = (TLB_PEFile *)iface;
2326 ULONG refs = InterlockedDecrement(&This->refs);
2327 if (!refs)
2329 if (This->typelib_global)
2330 FreeResource(This->typelib_global);
2331 if (This->dll)
2332 FreeLibrary(This->dll);
2333 HeapFree(GetProcessHeap(), 0, This);
2335 return refs;
2338 static const IUnknownVtbl TLB_PEFile_Vtable =
2340 TLB_PEFile_QueryInterface,
2341 TLB_PEFile_AddRef,
2342 TLB_PEFile_Release
2345 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2347 TLB_PEFile *This;
2349 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2350 if (!This)
2351 return E_OUTOFMEMORY;
2353 This->lpvtbl = &TLB_PEFile_Vtable;
2354 This->refs = 1;
2355 This->dll = NULL;
2356 This->typelib_resource = NULL;
2357 This->typelib_global = NULL;
2358 This->typelib_base = NULL;
2360 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2361 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2363 if (This->dll)
2365 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2366 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2367 if (This->typelib_resource)
2369 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2370 if (This->typelib_global)
2372 This->typelib_base = LockResource(This->typelib_global);
2374 if (This->typelib_base)
2376 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2377 *ppBase = This->typelib_base;
2378 *ppFile = (IUnknown *)&This->lpvtbl;
2379 return S_OK;
2385 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2386 return TYPE_E_CANTLOADLIBRARY;
2389 typedef struct TLB_NEFile
2391 const IUnknownVtbl *lpvtbl;
2392 LONG refs;
2393 LPVOID typelib_base;
2394 } TLB_NEFile;
2396 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2398 if (IsEqualIID(riid, &IID_IUnknown))
2400 *ppv = iface;
2401 IUnknown_AddRef(iface);
2402 return S_OK;
2404 *ppv = NULL;
2405 return E_NOINTERFACE;
2408 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2410 TLB_NEFile *This = (TLB_NEFile *)iface;
2411 return InterlockedIncrement(&This->refs);
2414 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2416 TLB_NEFile *This = (TLB_NEFile *)iface;
2417 ULONG refs = InterlockedDecrement(&This->refs);
2418 if (!refs)
2420 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2421 HeapFree(GetProcessHeap(), 0, This);
2423 return refs;
2426 static const IUnknownVtbl TLB_NEFile_Vtable =
2428 TLB_NEFile_QueryInterface,
2429 TLB_NEFile_AddRef,
2430 TLB_NEFile_Release
2433 /***********************************************************************
2434 * read_xx_header [internal]
2436 static int read_xx_header( HFILE lzfd )
2438 IMAGE_DOS_HEADER mzh;
2439 char magic[3];
2441 LZSeek( lzfd, 0, SEEK_SET );
2442 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2443 return 0;
2444 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2445 return 0;
2447 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2448 if ( 2 != LZRead( lzfd, magic, 2 ) )
2449 return 0;
2451 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2453 if ( magic[0] == 'N' && magic[1] == 'E' )
2454 return IMAGE_OS2_SIGNATURE;
2455 if ( magic[0] == 'P' && magic[1] == 'E' )
2456 return IMAGE_NT_SIGNATURE;
2458 magic[2] = '\0';
2459 WARN("Can't handle %s files.\n", magic );
2460 return 0;
2464 /***********************************************************************
2465 * find_ne_resource [internal]
2467 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2468 DWORD *resLen, DWORD *resOff )
2470 IMAGE_OS2_HEADER nehd;
2471 NE_TYPEINFO *typeInfo;
2472 NE_NAMEINFO *nameInfo;
2473 DWORD nehdoffset;
2474 LPBYTE resTab;
2475 DWORD resTabSize;
2476 int count;
2478 /* Read in NE header */
2479 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2480 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2482 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2483 if ( !resTabSize )
2485 TRACE("No resources in NE dll\n" );
2486 return FALSE;
2489 /* Read in resource table */
2490 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2491 if ( !resTab ) return FALSE;
2493 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2494 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2496 HeapFree( GetProcessHeap(), 0, resTab );
2497 return FALSE;
2500 /* Find resource */
2501 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2503 if (!IS_INTRESOURCE(typeid)) /* named type */
2505 BYTE len = strlen( typeid );
2506 while (typeInfo->type_id)
2508 if (!(typeInfo->type_id & 0x8000))
2510 BYTE *p = resTab + typeInfo->type_id;
2511 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2513 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2514 typeInfo->count * sizeof(NE_NAMEINFO));
2517 else /* numeric type id */
2519 WORD id = LOWORD(typeid) | 0x8000;
2520 while (typeInfo->type_id)
2522 if (typeInfo->type_id == id) goto found_type;
2523 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2524 typeInfo->count * sizeof(NE_NAMEINFO));
2527 TRACE("No typeid entry found for %p\n", typeid );
2528 HeapFree( GetProcessHeap(), 0, resTab );
2529 return FALSE;
2531 found_type:
2532 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2534 if (!IS_INTRESOURCE(resid)) /* named resource */
2536 BYTE len = strlen( resid );
2537 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2539 BYTE *p = resTab + nameInfo->id;
2540 if (nameInfo->id & 0x8000) continue;
2541 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2544 else /* numeric resource id */
2546 WORD id = LOWORD(resid) | 0x8000;
2547 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2548 if (nameInfo->id == id) goto found_name;
2550 TRACE("No resid entry found for %p\n", typeid );
2551 HeapFree( GetProcessHeap(), 0, resTab );
2552 return FALSE;
2554 found_name:
2555 /* Return resource data */
2556 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2557 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2559 HeapFree( GetProcessHeap(), 0, resTab );
2560 return TRUE;
2563 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2565 HFILE lzfd = -1;
2566 OFSTRUCT ofs;
2567 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2568 TLB_NEFile *This = NULL;
2570 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2571 if (!This) return E_OUTOFMEMORY;
2573 This->lpvtbl = &TLB_NEFile_Vtable;
2574 This->refs = 1;
2575 This->typelib_base = NULL;
2577 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2578 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2580 DWORD reslen, offset;
2581 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2583 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2584 if( !This->typelib_base )
2585 hr = E_OUTOFMEMORY;
2586 else
2588 LZSeek( lzfd, offset, SEEK_SET );
2589 reslen = LZRead( lzfd, This->typelib_base, reslen );
2590 LZClose( lzfd );
2591 *ppBase = This->typelib_base;
2592 *pdwTLBLength = reslen;
2593 *ppFile = (IUnknown *)&This->lpvtbl;
2594 return S_OK;
2599 if( lzfd >= 0) LZClose( lzfd );
2600 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2601 return hr;
2604 typedef struct TLB_Mapping
2606 const IUnknownVtbl *lpvtbl;
2607 LONG refs;
2608 HANDLE file;
2609 HANDLE mapping;
2610 LPVOID typelib_base;
2611 } TLB_Mapping;
2613 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2615 if (IsEqualIID(riid, &IID_IUnknown))
2617 *ppv = iface;
2618 IUnknown_AddRef(iface);
2619 return S_OK;
2621 *ppv = NULL;
2622 return E_NOINTERFACE;
2625 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2627 TLB_Mapping *This = (TLB_Mapping *)iface;
2628 return InterlockedIncrement(&This->refs);
2631 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2633 TLB_Mapping *This = (TLB_Mapping *)iface;
2634 ULONG refs = InterlockedDecrement(&This->refs);
2635 if (!refs)
2637 if (This->typelib_base)
2638 UnmapViewOfFile(This->typelib_base);
2639 if (This->mapping)
2640 CloseHandle(This->mapping);
2641 if (This->file != INVALID_HANDLE_VALUE)
2642 CloseHandle(This->file);
2643 HeapFree(GetProcessHeap(), 0, This);
2645 return refs;
2648 static const IUnknownVtbl TLB_Mapping_Vtable =
2650 TLB_Mapping_QueryInterface,
2651 TLB_Mapping_AddRef,
2652 TLB_Mapping_Release
2655 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2657 TLB_Mapping *This;
2659 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2660 if (!This)
2661 return E_OUTOFMEMORY;
2663 This->lpvtbl = &TLB_Mapping_Vtable;
2664 This->refs = 1;
2665 This->file = INVALID_HANDLE_VALUE;
2666 This->mapping = NULL;
2667 This->typelib_base = NULL;
2669 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2670 if (INVALID_HANDLE_VALUE != This->file)
2672 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2673 if (This->mapping)
2675 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2676 if(This->typelib_base)
2678 /* retrieve file size */
2679 *pdwTLBLength = GetFileSize(This->file, NULL);
2680 *ppBase = This->typelib_base;
2681 *ppFile = (IUnknown *)&This->lpvtbl;
2682 return S_OK;
2687 IUnknown_Release((IUnknown *)&This->lpvtbl);
2688 return TYPE_E_CANTLOADLIBRARY;
2691 /****************************************************************************
2692 * TLB_ReadTypeLib
2694 * find the type of the typelib file and map the typelib resource into
2695 * the memory
2697 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2698 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2699 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2701 ITypeLibImpl *entry;
2702 HRESULT ret;
2703 INT index = 1;
2704 LPWSTR index_str, file = (LPWSTR)pszFileName;
2705 LPVOID pBase = NULL;
2706 DWORD dwTLBLength = 0;
2707 IUnknown *pFile = NULL;
2709 *ppTypeLib = NULL;
2711 index_str = strrchrW(pszFileName, '\\');
2712 if(index_str && *++index_str != '\0')
2714 LPWSTR end_ptr;
2715 long idx = strtolW(index_str, &end_ptr, 10);
2716 if(*end_ptr == '\0')
2718 int str_len = index_str - pszFileName - 1;
2719 index = idx;
2720 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2721 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2722 file[str_len] = 0;
2726 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2728 if(strchrW(file, '\\'))
2730 lstrcpyW(pszPath, file);
2732 else
2734 int len = GetSystemDirectoryW(pszPath, cchPath);
2735 pszPath[len] = '\\';
2736 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2740 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2742 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2744 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2745 EnterCriticalSection(&cache_section);
2746 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2748 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2750 TRACE("cache hit\n");
2751 *ppTypeLib = (ITypeLib2*)entry;
2752 ITypeLib_AddRef(*ppTypeLib);
2753 LeaveCriticalSection(&cache_section);
2754 return S_OK;
2757 LeaveCriticalSection(&cache_section);
2759 /* now actually load and parse the typelib */
2761 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2762 if (ret == TYPE_E_CANTLOADLIBRARY)
2763 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2764 if (ret == TYPE_E_CANTLOADLIBRARY)
2765 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2766 if (SUCCEEDED(ret))
2768 if (dwTLBLength >= 4)
2770 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2771 if (dwSignature == MSFT_SIGNATURE)
2772 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2773 else if (dwSignature == SLTG_SIGNATURE)
2774 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2775 else
2777 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2778 ret = TYPE_E_CANTLOADLIBRARY;
2781 else
2782 ret = TYPE_E_CANTLOADLIBRARY;
2783 IUnknown_Release(pFile);
2786 if(*ppTypeLib) {
2787 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2789 TRACE("adding to cache\n");
2790 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2791 lstrcpyW(impl->path, pszPath);
2792 /* We should really canonicalise the path here. */
2793 impl->index = index;
2795 /* FIXME: check if it has added already in the meantime */
2796 EnterCriticalSection(&cache_section);
2797 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2798 impl->prev = NULL;
2799 tlb_cache_first = impl;
2800 LeaveCriticalSection(&cache_section);
2801 ret = S_OK;
2802 } else
2803 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2805 return ret;
2808 /*================== ITypeLib(2) Methods ===================================*/
2810 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2812 ITypeLibImpl* pTypeLibImpl;
2814 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2815 if (!pTypeLibImpl) return NULL;
2817 pTypeLibImpl->lpVtbl = &tlbvt;
2818 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2819 pTypeLibImpl->ref = 1;
2821 list_init(&pTypeLibImpl->ref_list);
2822 pTypeLibImpl->dispatch_href = -1;
2824 return pTypeLibImpl;
2827 /****************************************************************************
2828 * ITypeLib2_Constructor_MSFT
2830 * loading an MSFT typelib from an in-memory image
2832 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2834 TLBContext cx;
2835 long lPSegDir;
2836 MSFT_Header tlbHeader;
2837 MSFT_SegDir tlbSegDir;
2838 ITypeLibImpl * pTypeLibImpl;
2840 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2842 pTypeLibImpl = TypeLibImpl_Constructor();
2843 if (!pTypeLibImpl) return NULL;
2845 /* get pointer to beginning of typelib data */
2846 cx.pos = 0;
2847 cx.oStart=0;
2848 cx.mapping = pLib;
2849 cx.pLibInfo = pTypeLibImpl;
2850 cx.length = dwTLBLength;
2852 /* read header */
2853 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2854 TRACE_(typelib)("header:\n");
2855 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2856 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2857 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2858 return NULL;
2860 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2862 /* there is a small amount of information here until the next important
2863 * part:
2864 * the segment directory . Try to calculate the amount of data */
2865 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2867 /* now read the segment directory */
2868 TRACE("read segment directory (at %ld)\n",lPSegDir);
2869 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2870 cx.pTblDir = &tlbSegDir;
2872 /* just check two entries */
2873 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2875 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2876 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2877 return NULL;
2880 /* now fill our internal data */
2881 /* TLIBATTR fields */
2882 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2884 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2885 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2886 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2887 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2888 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2890 pTypeLibImpl->lcid = tlbHeader.lcid;
2892 /* name, eventually add to a hash table */
2893 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2895 /* help info */
2896 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2897 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2899 if( tlbHeader.varflags & HELPDLLFLAG)
2901 int offset;
2902 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2903 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2906 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2908 /* custom data */
2909 if(tlbHeader.CustomDataOffset >= 0)
2911 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2914 /* fill in type descriptions */
2915 if(tlbSegDir.pTypdescTab.length > 0)
2917 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2918 INT16 td[4];
2919 pTypeLibImpl->ctTypeDesc = cTD;
2920 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2921 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2922 for(i=0; i<cTD; )
2924 /* FIXME: add several sanity checks here */
2925 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2926 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2928 /* FIXME: check safearray */
2929 if(td[3] < 0)
2930 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2931 else
2932 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2934 else if(td[0] == VT_CARRAY)
2936 /* array descr table here */
2937 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2939 else if(td[0] == VT_USERDEFINED)
2941 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2943 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2946 /* second time around to fill the array subscript info */
2947 for(i=0;i<cTD;i++)
2949 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2950 if(tlbSegDir.pArrayDescriptions.offset>0)
2952 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2953 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2955 if(td[1]<0)
2956 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2957 else
2958 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
2960 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2962 for(j = 0; j<td[2]; j++)
2964 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2965 sizeof(INT), &cx, DO_NOT_SEEK);
2966 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2967 sizeof(INT), &cx, DO_NOT_SEEK);
2970 else
2972 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2973 ERR("didn't find array description data\n");
2978 /* imported type libs */
2979 if(tlbSegDir.pImpFiles.offset>0)
2981 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2982 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2983 UINT16 size;
2985 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2987 char *name;
2989 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2990 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2991 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2993 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2994 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2995 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2996 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2998 size >>= 2;
2999 name = TLB_Alloc(size+1);
3000 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3001 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3002 TLB_Free(name);
3004 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3005 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3007 ppImpLib = &(*ppImpLib)->next;
3011 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3012 if(pTypeLibImpl->dispatch_href != -1)
3013 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3015 /* type info's */
3016 if(tlbHeader.nrtypeinfos >= 0 )
3018 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3019 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3020 int i;
3022 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3024 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3026 ppTI = &((*ppTI)->next);
3027 (pTypeLibImpl->TypeInfoCount)++;
3031 TRACE("(%p)\n", pTypeLibImpl);
3032 return (ITypeLib2*) pTypeLibImpl;
3036 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3038 char b[3];
3039 int i;
3040 short s;
3042 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3043 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3044 return FALSE;
3047 guid->Data4[0] = s >> 8;
3048 guid->Data4[1] = s & 0xff;
3050 b[2] = '\0';
3051 for(i = 0; i < 6; i++) {
3052 memcpy(b, str + 24 + 2 * i, 2);
3053 guid->Data4[i + 2] = strtol(b, NULL, 16);
3055 return TRUE;
3058 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3060 WORD bytelen;
3061 DWORD len;
3063 *pBstr = NULL;
3064 bytelen = *(const WORD*)ptr;
3065 if(bytelen == 0xffff) return 2;
3066 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3067 *pBstr = SysAllocStringLen(NULL, len);
3068 if (*pBstr)
3069 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3070 return bytelen + 2;
3073 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3075 WORD bytelen;
3077 *str = NULL;
3078 bytelen = *(const WORD*)ptr;
3079 if(bytelen == 0xffff) return 2;
3080 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3081 memcpy(*str, ptr + 2, bytelen);
3082 (*str)[bytelen] = '\0';
3083 return bytelen + 2;
3086 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3088 char *ptr = pLibBlk;
3089 WORD w;
3091 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3092 FIXME("libblk magic = %04x\n", w);
3093 return 0;
3096 ptr += 6;
3097 if((w = *(WORD*)ptr) != 0xffff) {
3098 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3099 ptr += w;
3101 ptr += 2;
3103 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3105 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3107 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3108 ptr += 4;
3110 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3111 ptr += 2;
3113 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3114 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3115 else
3116 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3117 ptr += 2;
3119 ptr += 4; /* skip res12 */
3121 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3122 ptr += 2;
3124 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3125 ptr += 2;
3127 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3128 ptr += 2;
3130 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3131 ptr += sizeof(GUID);
3133 return ptr - (char*)pLibBlk;
3136 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3137 typedef struct
3139 unsigned int num;
3140 HREFTYPE refs[1];
3141 } sltg_ref_lookup_t;
3143 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3144 HREFTYPE *typelib_ref)
3146 if(table && typeinfo_ref < table->num)
3148 *typelib_ref = table->refs[typeinfo_ref];
3149 return S_OK;
3152 ERR_(typelib)("Unable to find reference\n");
3153 *typelib_ref = -1;
3154 return E_FAIL;
3157 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3159 BOOL done = FALSE;
3161 while(!done) {
3162 if((*pType & 0xe00) == 0xe00) {
3163 pTD->vt = VT_PTR;
3164 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3165 sizeof(TYPEDESC));
3166 pTD = pTD->u.lptdesc;
3168 switch(*pType & 0x3f) {
3169 case VT_PTR:
3170 pTD->vt = VT_PTR;
3171 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3172 sizeof(TYPEDESC));
3173 pTD = pTD->u.lptdesc;
3174 break;
3176 case VT_USERDEFINED:
3177 pTD->vt = VT_USERDEFINED;
3178 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3179 done = TRUE;
3180 break;
3182 case VT_CARRAY:
3184 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3185 array */
3187 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3189 pTD->vt = VT_CARRAY;
3190 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3191 sizeof(ARRAYDESC) +
3192 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3193 pTD->u.lpadesc->cDims = pSA->cDims;
3194 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3195 pSA->cDims * sizeof(SAFEARRAYBOUND));
3197 pTD = &pTD->u.lpadesc->tdescElem;
3198 break;
3201 case VT_SAFEARRAY:
3203 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3204 useful? */
3206 pType++;
3207 pTD->vt = VT_SAFEARRAY;
3208 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3209 sizeof(TYPEDESC));
3210 pTD = pTD->u.lptdesc;
3211 break;
3213 default:
3214 pTD->vt = *pType & 0x3f;
3215 done = TRUE;
3216 break;
3218 pType++;
3220 return pType;
3223 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3224 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3226 /* Handle [in/out] first */
3227 if((*pType & 0xc000) == 0xc000)
3228 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3229 else if(*pType & 0x8000)
3230 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3231 else if(*pType & 0x4000)
3232 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3233 else
3234 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3236 if(*pType & 0x2000)
3237 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3239 if(*pType & 0x80)
3240 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3242 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3246 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3247 char *pNameTable)
3249 unsigned int ref;
3250 char *name;
3251 TLBRefType *ref_type;
3252 sltg_ref_lookup_t *table;
3253 HREFTYPE typelib_ref;
3255 if(pRef->magic != SLTG_REF_MAGIC) {
3256 FIXME("Ref magic = %x\n", pRef->magic);
3257 return NULL;
3259 name = ( (char*)pRef->names + pRef->number);
3261 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3262 table->num = pRef->number >> 3;
3264 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3266 /* We don't want the first href to be 0 */
3267 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3269 for(ref = 0; ref < pRef->number >> 3; ref++) {
3270 char *refname;
3271 unsigned int lib_offs, type_num;
3273 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3275 name += SLTG_ReadStringA(name, &refname);
3276 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3277 FIXME_(typelib)("Can't sscanf ref\n");
3278 if(lib_offs != 0xffff) {
3279 TLBImpLib **import = &pTL->pImpLibs;
3281 while(*import) {
3282 if((*import)->offset == lib_offs)
3283 break;
3284 import = &(*import)->next;
3286 if(!*import) {
3287 char fname[MAX_PATH+1];
3288 int len;
3290 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3291 sizeof(**import));
3292 (*import)->offset = lib_offs;
3293 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3294 &(*import)->guid);
3295 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3296 &(*import)->wVersionMajor,
3297 &(*import)->wVersionMinor,
3298 &(*import)->lcid, fname) != 4) {
3299 FIXME_(typelib)("can't sscanf ref %s\n",
3300 pNameTable + lib_offs + 40);
3302 len = strlen(fname);
3303 if(fname[len-1] != '#')
3304 FIXME("fname = %s\n", fname);
3305 fname[len-1] = '\0';
3306 (*import)->name = TLB_MultiByteToBSTR(fname);
3308 ref_type->pImpTLInfo = *import;
3310 /* Store a reference to IDispatch */
3311 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3312 pTL->dispatch_href = typelib_ref;
3314 } else { /* internal ref */
3315 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3317 ref_type->reference = typelib_ref;
3318 ref_type->index = type_num;
3320 HeapFree(GetProcessHeap(), 0, refname);
3321 list_add_tail(&pTL->ref_list, &ref_type->entry);
3323 table->refs[ref] = typelib_ref;
3324 typelib_ref += 4;
3326 if((BYTE)*name != SLTG_REF_MAGIC)
3327 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3328 dump_TLBRefType(pTL);
3329 return table;
3332 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3333 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3335 SLTG_ImplInfo *info;
3336 TLBImplType **ppImplType = &pTI->impltypelist;
3337 /* I don't really get this structure, usually it's 0x16 bytes
3338 long, but iuser.tlb contains some that are 0x18 bytes long.
3339 That's ok because we can use the next ptr to jump to the next
3340 one. But how do we know the length of the last one? The WORD
3341 at offs 0x8 might be the clue. For now I'm just assuming that
3342 the last one is the regular 0x16 bytes. */
3344 info = (SLTG_ImplInfo*)pBlk;
3345 while(1) {
3346 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3347 sizeof(**ppImplType));
3348 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3349 (*ppImplType)->implflags = info->impltypeflags;
3350 pTI->TypeAttr.cImplTypes++;
3351 ppImplType = &(*ppImplType)->next;
3353 if(info->next == 0xffff)
3354 break;
3355 if(OneOnly)
3356 FIXME_(typelib)("Interface inheriting more than one interface\n");
3357 info = (SLTG_ImplInfo*)(pBlk + info->next);
3359 info++; /* see comment at top of function */
3360 return (char*)info;
3363 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3364 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3366 TLBVarDesc **ppVarDesc = &pTI->varlist;
3367 BSTR bstrPrevName = NULL;
3368 SLTG_Variable *pItem;
3369 unsigned short i;
3370 WORD *pType;
3372 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3373 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3375 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3376 sizeof(**ppVarDesc));
3377 (*ppVarDesc)->vardesc.memid = pItem->memid;
3379 if (pItem->magic != SLTG_VAR_MAGIC &&
3380 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3381 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3382 return;
3385 if (pItem->name == 0xfffe)
3386 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3387 else
3388 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3390 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3391 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3392 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3394 if(pItem->flags & 0x02)
3395 pType = &pItem->type;
3396 else
3397 pType = (WORD*)(pBlk + pItem->type);
3399 if (pItem->flags & ~0xda)
3400 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3402 SLTG_DoElem(pType, pBlk,
3403 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3405 if (TRACE_ON(typelib)) {
3406 char buf[300];
3407 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3408 TRACE_(typelib)("elemdescVar: %s\n", buf);
3411 if (pItem->flags & 0x40) {
3412 TRACE_(typelib)("VAR_DISPATCH\n");
3413 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3415 else if (pItem->flags & 0x10) {
3416 TRACE_(typelib)("VAR_CONST\n");
3417 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3418 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3419 sizeof(VARIANT));
3420 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3421 if (pItem->flags & 0x08)
3422 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3423 else {
3424 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3426 case VT_LPSTR:
3427 case VT_LPWSTR:
3428 case VT_BSTR:
3430 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3431 BSTR str;
3432 TRACE_(typelib)("len = %u\n", len);
3433 if (len == 0xffff) {
3434 str = NULL;
3435 } else {
3436 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3437 str = SysAllocStringLen(NULL, alloc_len);
3438 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3440 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3441 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3442 break;
3444 case VT_I2:
3445 case VT_UI2:
3446 case VT_I4:
3447 case VT_UI4:
3448 case VT_INT:
3449 case VT_UINT:
3450 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3451 *(INT*)(pBlk + pItem->byte_offs);
3452 break;
3453 default:
3454 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3458 else {
3459 TRACE_(typelib)("VAR_PERINSTANCE\n");
3460 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3461 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3464 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3465 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3467 if (pItem->flags & 0x80)
3468 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3470 bstrPrevName = (*ppVarDesc)->Name;
3471 ppVarDesc = &((*ppVarDesc)->next);
3473 pTI->TypeAttr.cVars = cVars;
3476 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3477 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3479 SLTG_Function *pFunc;
3480 unsigned short i;
3481 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3483 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3484 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3486 int param;
3487 WORD *pType, *pArg;
3489 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3490 sizeof(**ppFuncDesc));
3492 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3493 case SLTG_FUNCTION_MAGIC:
3494 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3495 break;
3496 case SLTG_DISPATCH_FUNCTION_MAGIC:
3497 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3498 break;
3499 case SLTG_STATIC_FUNCTION_MAGIC:
3500 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3501 break;
3502 default:
3503 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3504 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3505 *ppFuncDesc = NULL;
3506 return;
3508 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3510 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3511 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3512 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3513 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3514 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3515 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3517 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3518 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3520 if(pFunc->retnextopt & 0x80)
3521 pType = &pFunc->rettype;
3522 else
3523 pType = (WORD*)(pBlk + pFunc->rettype);
3525 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3527 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3528 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3529 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3530 (*ppFuncDesc)->pParamDesc =
3531 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3532 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3534 pArg = (WORD*)(pBlk + pFunc->arg_off);
3536 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3537 char *paramName = pNameTable + *pArg;
3538 BOOL HaveOffs;
3539 /* If arg type follows then paramName points to the 2nd
3540 letter of the name, else the next WORD is an offset to
3541 the arg type and paramName points to the first letter.
3542 So let's take one char off paramName and see if we're
3543 pointing at an alpha-numeric char. However if *pArg is
3544 0xffff or 0xfffe then the param has no name, the former
3545 meaning that the next WORD is the type, the latter
3546 meaning that the next WORD is an offset to the type. */
3548 HaveOffs = FALSE;
3549 if(*pArg == 0xffff)
3550 paramName = NULL;
3551 else if(*pArg == 0xfffe) {
3552 paramName = NULL;
3553 HaveOffs = TRUE;
3555 else if(paramName[-1] && !isalnum(paramName[-1]))
3556 HaveOffs = TRUE;
3558 pArg++;
3560 if(HaveOffs) { /* the next word is an offset to type */
3561 pType = (WORD*)(pBlk + *pArg);
3562 SLTG_DoElem(pType, pBlk,
3563 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3564 pArg++;
3565 } else {
3566 if(paramName)
3567 paramName--;
3568 pArg = SLTG_DoElem(pArg, pBlk,
3569 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3572 /* Are we an optional param ? */
3573 if((*ppFuncDesc)->funcdesc.cParams - param <=
3574 (*ppFuncDesc)->funcdesc.cParamsOpt)
3575 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3577 if(paramName) {
3578 (*ppFuncDesc)->pParamDesc[param].Name =
3579 TLB_MultiByteToBSTR(paramName);
3580 } else {
3581 (*ppFuncDesc)->pParamDesc[param].Name =
3582 SysAllocString((*ppFuncDesc)->Name);
3586 ppFuncDesc = &((*ppFuncDesc)->next);
3587 if(pFunc->next == 0xffff) break;
3589 pTI->TypeAttr.cFuncs = cFuncs;
3592 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3593 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3594 SLTG_TypeInfoTail *pTITail)
3596 char *pFirstItem;
3597 sltg_ref_lookup_t *ref_lookup = NULL;
3599 if(pTIHeader->href_table != 0xffffffff) {
3600 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3601 pNameTable);
3604 pFirstItem = pBlk;
3606 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3607 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3609 HeapFree(GetProcessHeap(), 0, ref_lookup);
3613 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3614 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3615 const SLTG_TypeInfoTail *pTITail)
3617 char *pFirstItem;
3618 sltg_ref_lookup_t *ref_lookup = NULL;
3620 if(pTIHeader->href_table != 0xffffffff) {
3621 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3622 pNameTable);
3625 pFirstItem = pBlk;
3627 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3628 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3631 if (pTITail->funcs_off != 0xffff)
3632 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3634 HeapFree(GetProcessHeap(), 0, ref_lookup);
3636 if (TRACE_ON(typelib))
3637 dump_TLBFuncDesc(pTI->funclist);
3640 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3641 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3642 const SLTG_TypeInfoTail *pTITail)
3644 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3647 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3648 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3649 const SLTG_TypeInfoTail *pTITail)
3651 WORD *pType;
3652 sltg_ref_lookup_t *ref_lookup = NULL;
3654 if (pTITail->simple_alias) {
3655 /* if simple alias, no more processing required */
3656 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3657 return;
3660 if(pTIHeader->href_table != 0xffffffff) {
3661 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3662 pNameTable);
3665 /* otherwise it is an offset to a type */
3666 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3668 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3670 HeapFree(GetProcessHeap(), 0, ref_lookup);
3673 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3674 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3675 const SLTG_TypeInfoTail *pTITail)
3677 sltg_ref_lookup_t *ref_lookup = NULL;
3678 if (pTIHeader->href_table != 0xffffffff)
3679 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3680 pNameTable);
3682 if (pTITail->vars_off != 0xffff)
3683 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3685 if (pTITail->funcs_off != 0xffff)
3686 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3688 if (pTITail->impls_off != 0xffff)
3689 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3691 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3692 * of dispinterface functions including the IDispatch ones, so
3693 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3694 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3696 HeapFree(GetProcessHeap(), 0, ref_lookup);
3697 if (TRACE_ON(typelib))
3698 dump_TLBFuncDesc(pTI->funclist);
3701 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3702 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3703 const SLTG_TypeInfoTail *pTITail)
3705 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3708 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3709 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3710 const SLTG_TypeInfoTail *pTITail)
3712 sltg_ref_lookup_t *ref_lookup = NULL;
3713 if (pTIHeader->href_table != 0xffffffff)
3714 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3715 pNameTable);
3717 if (pTITail->vars_off != 0xffff)
3718 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3720 if (pTITail->funcs_off != 0xffff)
3721 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3722 HeapFree(GetProcessHeap(), 0, ref_lookup);
3723 if (TRACE_ON(typelib))
3724 dump_TypeInfo(pTI);
3727 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3728 managable copy of it into this */
3729 typedef struct {
3730 WORD small_no;
3731 char *index_name;
3732 char *other_name;
3733 WORD res1a;
3734 WORD name_offs;
3735 WORD more_bytes;
3736 char *extra;
3737 WORD res20;
3738 DWORD helpcontext;
3739 WORD res26;
3740 GUID uuid;
3741 } SLTG_InternalOtherTypeInfo;
3743 /****************************************************************************
3744 * ITypeLib2_Constructor_SLTG
3746 * loading a SLTG typelib from an in-memory image
3748 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3750 ITypeLibImpl *pTypeLibImpl;
3751 SLTG_Header *pHeader;
3752 SLTG_BlkEntry *pBlkEntry;
3753 SLTG_Magic *pMagic;
3754 SLTG_Index *pIndex;
3755 SLTG_Pad9 *pPad9;
3756 LPVOID pBlk, pFirstBlk;
3757 SLTG_LibBlk *pLibBlk;
3758 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3759 char *pAfterOTIBlks = NULL;
3760 char *pNameTable, *ptr;
3761 int i;
3762 DWORD len, order;
3763 ITypeInfoImpl **ppTypeInfoImpl;
3765 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3768 pTypeLibImpl = TypeLibImpl_Constructor();
3769 if (!pTypeLibImpl) return NULL;
3771 pHeader = pLib;
3773 TRACE_(typelib)("header:\n");
3774 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3775 pHeader->nrOfFileBlks );
3776 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3777 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3778 pHeader->SLTG_magic);
3779 return NULL;
3782 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3783 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3785 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3786 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3788 /* Next we have a magic block */
3789 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3791 /* Let's see if we're still in sync */
3792 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3793 sizeof(SLTG_COMPOBJ_MAGIC))) {
3794 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3795 return NULL;
3797 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3798 sizeof(SLTG_DIR_MAGIC))) {
3799 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3800 return NULL;
3803 pIndex = (SLTG_Index*)(pMagic+1);
3805 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3807 pFirstBlk = pPad9 + 1;
3809 /* We'll set up a ptr to the main library block, which is the last one. */
3811 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3812 pBlkEntry[order].next != 0;
3813 order = pBlkEntry[order].next - 1, i++) {
3814 pBlk = (char*)pBlk + pBlkEntry[order].len;
3816 pLibBlk = pBlk;
3818 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3820 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3821 interspersed */
3823 len += 0x40;
3825 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3827 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3828 sizeof(*pOtherTypeInfoBlks) *
3829 pTypeLibImpl->TypeInfoCount);
3832 ptr = (char*)pLibBlk + len;
3834 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3835 WORD w, extra;
3836 len = 0;
3838 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3840 w = *(WORD*)(ptr + 2);
3841 if(w != 0xffff) {
3842 len += w;
3843 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3844 w+1);
3845 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3846 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3848 w = *(WORD*)(ptr + 4 + len);
3849 if(w != 0xffff) {
3850 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3851 len += w;
3852 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3853 w+1);
3854 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3855 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3857 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3858 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3859 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3860 if(extra) {
3861 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3862 extra);
3863 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3864 len += extra;
3866 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3867 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3868 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3869 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3870 len += sizeof(SLTG_OtherTypeInfo);
3871 ptr += len;
3874 pAfterOTIBlks = ptr;
3876 /* Skip this WORD and get the next DWORD */
3877 len = *(DWORD*)(pAfterOTIBlks + 2);
3879 /* Now add this to pLibBLk look at what we're pointing at and
3880 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3881 dust and we should be pointing at the beginning of the name
3882 table */
3884 pNameTable = (char*)pLibBlk + len;
3886 switch(*(WORD*)pNameTable) {
3887 case 0xffff:
3888 break;
3889 case 0x0200:
3890 pNameTable += 0x20;
3891 break;
3892 default:
3893 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3894 break;
3897 pNameTable += 0x216;
3899 pNameTable += 2;
3901 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3903 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3906 /* Hopefully we now have enough ptrs set up to actually read in
3907 some TypeInfos. It's not clear which order to do them in, so
3908 I'll just follow the links along the BlkEntry chain and read
3909 them in the order in which they are in the file */
3911 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3913 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3914 pBlkEntry[order].next != 0;
3915 order = pBlkEntry[order].next - 1, i++) {
3917 SLTG_TypeInfoHeader *pTIHeader;
3918 SLTG_TypeInfoTail *pTITail;
3919 SLTG_MemberHeader *pMemHeader;
3921 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3922 pOtherTypeInfoBlks[i].index_name)) {
3923 FIXME_(typelib)("Index strings don't match\n");
3924 return NULL;
3927 pTIHeader = pBlk;
3928 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3929 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3930 return NULL;
3932 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3933 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3934 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3936 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3937 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3938 (*ppTypeInfoImpl)->index = i;
3939 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3940 pOtherTypeInfoBlks[i].name_offs +
3941 pNameTable);
3942 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3943 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3944 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3945 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3946 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3947 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3948 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3950 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3951 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3953 if((pTIHeader->typeflags1 & 7) != 2)
3954 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3955 if(pTIHeader->typeflags3 != 2)
3956 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3958 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3959 debugstr_w((*ppTypeInfoImpl)->Name),
3960 typekind_desc[pTIHeader->typekind],
3961 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3962 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3964 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3966 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3968 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3969 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3970 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3972 switch(pTIHeader->typekind) {
3973 case TKIND_ENUM:
3974 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3975 pTIHeader, pTITail);
3976 break;
3978 case TKIND_RECORD:
3979 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3980 pTIHeader, pTITail);
3981 break;
3983 case TKIND_INTERFACE:
3984 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3985 pTIHeader, pTITail);
3986 break;
3988 case TKIND_COCLASS:
3989 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3990 pTIHeader, pTITail);
3991 break;
3993 case TKIND_ALIAS:
3994 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3995 pTIHeader, pTITail);
3996 break;
3998 case TKIND_DISPATCH:
3999 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4000 pTIHeader, pTITail);
4001 break;
4003 case TKIND_MODULE:
4004 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4005 pTIHeader, pTITail);
4006 break;
4008 default:
4009 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4010 break;
4014 /* could get cFuncs, cVars and cImplTypes from here
4015 but we've already set those */
4016 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4017 X(06);
4018 X(16);
4019 X(18);
4020 X(1a);
4021 X(1e);
4022 X(24);
4023 X(26);
4024 X(2a);
4025 X(2c);
4026 X(2e);
4027 X(30);
4028 X(32);
4029 X(34);
4030 #undef X
4031 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4032 pBlk = (char*)pBlk + pBlkEntry[order].len;
4035 if(i != pTypeLibImpl->TypeInfoCount) {
4036 FIXME("Somehow processed %d TypeInfos\n", i);
4037 return NULL;
4040 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4041 return (ITypeLib2*)pTypeLibImpl;
4044 /* ITypeLib::QueryInterface
4046 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4047 ITypeLib2 * iface,
4048 REFIID riid,
4049 VOID **ppvObject)
4051 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4053 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4055 *ppvObject=NULL;
4056 if(IsEqualIID(riid, &IID_IUnknown) ||
4057 IsEqualIID(riid,&IID_ITypeLib)||
4058 IsEqualIID(riid,&IID_ITypeLib2))
4060 *ppvObject = This;
4063 if(*ppvObject)
4065 ITypeLib2_AddRef(iface);
4066 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4067 return S_OK;
4069 TRACE("-- Interface: E_NOINTERFACE\n");
4070 return E_NOINTERFACE;
4073 /* ITypeLib::AddRef
4075 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4077 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4078 ULONG ref = InterlockedIncrement(&This->ref);
4080 TRACE("(%p)->ref was %u\n",This, ref - 1);
4082 return ref;
4085 /* ITypeLib::Release
4087 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4089 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4090 ULONG ref = InterlockedDecrement(&This->ref);
4092 TRACE("(%p)->(%u)\n",This, ref);
4094 if (!ref)
4096 TLBImpLib *pImpLib, *pImpLibNext;
4097 TLBCustData *pCustData, *pCustDataNext;
4098 TLBRefType *ref_type;
4099 void *cursor2;
4100 int i;
4101 ITypeInfoImpl *pTI, *pTINext;
4103 /* remove cache entry */
4104 if(This->path)
4106 TRACE("removing from cache list\n");
4107 EnterCriticalSection(&cache_section);
4108 if (This->next) This->next->prev = This->prev;
4109 if (This->prev) This->prev->next = This->next;
4110 else tlb_cache_first = This->next;
4111 LeaveCriticalSection(&cache_section);
4112 HeapFree(GetProcessHeap(), 0, This->path);
4114 TRACE(" destroying ITypeLib(%p)\n",This);
4116 SysFreeString(This->Name);
4117 This->Name = NULL;
4119 SysFreeString(This->DocString);
4120 This->DocString = NULL;
4122 SysFreeString(This->HelpFile);
4123 This->HelpFile = NULL;
4125 SysFreeString(This->HelpStringDll);
4126 This->HelpStringDll = NULL;
4128 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4130 VariantClear(&pCustData->data);
4132 pCustDataNext = pCustData->next;
4133 TLB_Free(pCustData);
4136 for (i = 0; i < This->ctTypeDesc; i++)
4137 if (This->pTypeDesc[i].vt == VT_CARRAY)
4138 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4140 TLB_Free(This->pTypeDesc);
4142 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4144 if (pImpLib->pImpTypeLib)
4145 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4146 SysFreeString(pImpLib->name);
4148 pImpLibNext = pImpLib->next;
4149 TLB_Free(pImpLib);
4152 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4154 list_remove(&ref_type->entry);
4155 TLB_Free(ref_type);
4158 for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
4160 pTINext = pTI->next;
4161 ITypeInfo_fnDestroy(pTI);
4163 HeapFree(GetProcessHeap(),0,This);
4164 return 0;
4167 return ref;
4170 /* ITypeLib::GetTypeInfoCount
4172 * Returns the number of type descriptions in the type library
4174 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4176 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4177 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4178 return This->TypeInfoCount;
4181 /* ITypeLib::GetTypeInfo
4183 * retrieves the specified type description in the library.
4185 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4186 ITypeLib2 *iface,
4187 UINT index,
4188 ITypeInfo **ppTInfo)
4190 UINT i;
4192 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4193 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4195 TRACE("(%p)->(index=%d)\n", This, index);
4197 if (!ppTInfo) return E_INVALIDARG;
4199 /* search element n in list */
4200 for(i=0; i < index; i++)
4202 pTypeInfo = pTypeInfo->next;
4203 if (!pTypeInfo)
4205 TRACE("-- element not found\n");
4206 return TYPE_E_ELEMENTNOTFOUND;
4210 *ppTInfo = (ITypeInfo *) pTypeInfo;
4212 ITypeInfo_AddRef(*ppTInfo);
4213 TRACE("-- found (%p)\n",*ppTInfo);
4214 return S_OK;
4218 /* ITypeLibs::GetTypeInfoType
4220 * Retrieves the type of a type description.
4222 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4223 ITypeLib2 *iface,
4224 UINT index,
4225 TYPEKIND *pTKind)
4227 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4228 UINT i;
4229 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4231 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4232 return TYPE_E_ELEMENTNOTFOUND;
4234 TRACE("(%p) index %d\n", This, index);
4236 if(!pTKind) return E_INVALIDARG;
4238 /* search element n in list */
4239 for(i=0; i < index; i++)
4241 if(!pTInfo)
4243 TRACE("-- element not found\n");
4244 return TYPE_E_ELEMENTNOTFOUND;
4246 pTInfo = pTInfo->next;
4249 *pTKind = pTInfo->TypeAttr.typekind;
4250 TRACE("-- found Type (%d)\n", *pTKind);
4251 return S_OK;
4254 /* ITypeLib::GetTypeInfoOfGuid
4256 * Retrieves the type description that corresponds to the specified GUID.
4259 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4260 ITypeLib2 *iface,
4261 REFGUID guid,
4262 ITypeInfo **ppTInfo)
4264 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4265 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4267 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4269 if (!pTypeInfo)
4271 WARN("-- element not found\n");
4272 return TYPE_E_ELEMENTNOTFOUND;
4275 /* search linked list for guid */
4276 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4278 pTypeInfo = pTypeInfo->next;
4280 if (!pTypeInfo)
4282 /* end of list reached */
4283 WARN("-- element not found\n");
4284 return TYPE_E_ELEMENTNOTFOUND;
4288 TRACE("-- found (%p, %s)\n",
4289 pTypeInfo,
4290 debugstr_w(pTypeInfo->Name));
4292 *ppTInfo = (ITypeInfo*)pTypeInfo;
4293 ITypeInfo_AddRef(*ppTInfo);
4294 return S_OK;
4297 /* ITypeLib::GetLibAttr
4299 * Retrieves the structure that contains the library's attributes.
4302 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4303 ITypeLib2 *iface,
4304 LPTLIBATTR *ppTLibAttr)
4306 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4307 TRACE("(%p)\n",This);
4308 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4309 **ppTLibAttr = This->LibAttr;
4310 return S_OK;
4313 /* ITypeLib::GetTypeComp
4315 * Enables a client compiler to bind to a library's types, variables,
4316 * constants, and global functions.
4319 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4320 ITypeLib2 *iface,
4321 ITypeComp **ppTComp)
4323 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4325 TRACE("(%p)->(%p)\n",This,ppTComp);
4326 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4327 ITypeComp_AddRef(*ppTComp);
4329 return S_OK;
4332 /* ITypeLib::GetDocumentation
4334 * Retrieves the library's documentation string, the complete Help file name
4335 * and path, and the context identifier for the library Help topic in the Help
4336 * file.
4338 * On a successful return all non-null BSTR pointers will have been set,
4339 * possibly to NULL.
4341 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4342 ITypeLib2 *iface,
4343 INT index,
4344 BSTR *pBstrName,
4345 BSTR *pBstrDocString,
4346 DWORD *pdwHelpContext,
4347 BSTR *pBstrHelpFile)
4349 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4351 HRESULT result = E_INVALIDARG;
4353 ITypeInfo *pTInfo;
4356 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4357 This, index,
4358 pBstrName, pBstrDocString,
4359 pdwHelpContext, pBstrHelpFile);
4361 if(index<0)
4363 /* documentation for the typelib */
4364 if(pBstrName)
4366 if (This->Name)
4368 if(!(*pBstrName = SysAllocString(This->Name)))
4369 goto memerr1;
4371 else
4372 *pBstrName = NULL;
4374 if(pBstrDocString)
4376 if (This->DocString)
4378 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4379 goto memerr2;
4381 else if (This->Name)
4383 if(!(*pBstrDocString = SysAllocString(This->Name)))
4384 goto memerr2;
4386 else
4387 *pBstrDocString = NULL;
4389 if(pdwHelpContext)
4391 *pdwHelpContext = This->dwHelpContext;
4393 if(pBstrHelpFile)
4395 if (This->HelpFile)
4397 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4398 goto memerr3;
4400 else
4401 *pBstrHelpFile = NULL;
4404 result = S_OK;
4406 else
4408 /* for a typeinfo */
4409 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4411 if(SUCCEEDED(result))
4413 result = ITypeInfo_GetDocumentation(pTInfo,
4414 MEMBERID_NIL,
4415 pBstrName,
4416 pBstrDocString,
4417 pdwHelpContext, pBstrHelpFile);
4419 ITypeInfo_Release(pTInfo);
4422 return result;
4423 memerr3:
4424 if (pBstrDocString) SysFreeString (*pBstrDocString);
4425 memerr2:
4426 if (pBstrName) SysFreeString (*pBstrName);
4427 memerr1:
4428 return STG_E_INSUFFICIENTMEMORY;
4431 /* ITypeLib::IsName
4433 * Indicates whether a passed-in string contains the name of a type or member
4434 * described in the library.
4437 static HRESULT WINAPI ITypeLib2_fnIsName(
4438 ITypeLib2 *iface,
4439 LPOLESTR szNameBuf,
4440 ULONG lHashVal,
4441 BOOL *pfName)
4443 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4444 ITypeInfoImpl *pTInfo;
4445 TLBFuncDesc *pFInfo;
4446 TLBVarDesc *pVInfo;
4447 int i;
4448 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4450 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4451 pfName);
4453 *pfName=TRUE;
4454 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4455 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4456 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4457 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4458 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4459 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4460 goto ITypeLib2_fnIsName_exit;
4462 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4463 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4466 *pfName=FALSE;
4468 ITypeLib2_fnIsName_exit:
4469 TRACE("(%p)slow! search for %s: %s found!\n", This,
4470 debugstr_w(szNameBuf), *pfName?"NOT":"");
4472 return S_OK;
4475 /* ITypeLib::FindName
4477 * Finds occurrences of a type description in a type library. This may be used
4478 * to quickly verify that a name exists in a type library.
4481 static HRESULT WINAPI ITypeLib2_fnFindName(
4482 ITypeLib2 *iface,
4483 LPOLESTR szNameBuf,
4484 ULONG lHashVal,
4485 ITypeInfo **ppTInfo,
4486 MEMBERID *rgMemId,
4487 UINT16 *pcFound)
4489 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4490 ITypeInfoImpl *pTInfo;
4491 TLBFuncDesc *pFInfo;
4492 TLBVarDesc *pVInfo;
4493 int i,j = 0;
4494 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4496 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4497 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4498 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4499 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4500 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4501 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4502 goto ITypeLib2_fnFindName_exit;
4505 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4506 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4507 continue;
4508 ITypeLib2_fnFindName_exit:
4509 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4510 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4511 j++;
4513 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4514 This, *pcFound, debugstr_w(szNameBuf), j);
4516 *pcFound=j;
4518 return S_OK;
4521 /* ITypeLib::ReleaseTLibAttr
4523 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4526 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4527 ITypeLib2 *iface,
4528 TLIBATTR *pTLibAttr)
4530 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4531 TRACE("freeing (%p)\n",This);
4532 HeapFree(GetProcessHeap(),0,pTLibAttr);
4536 /* ITypeLib2::GetCustData
4538 * gets the custom data
4540 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4541 ITypeLib2 * iface,
4542 REFGUID guid,
4543 VARIANT *pVarVal)
4545 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4546 TLBCustData *pCData;
4548 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4550 if( IsEqualIID(guid, &pCData->guid)) break;
4553 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4555 if(pCData)
4557 VariantInit( pVarVal);
4558 VariantCopy( pVarVal, &pCData->data);
4559 return S_OK;
4561 return E_INVALIDARG; /* FIXME: correct? */
4564 /* ITypeLib2::GetLibStatistics
4566 * Returns statistics about a type library that are required for efficient
4567 * sizing of hash tables.
4570 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4571 ITypeLib2 * iface,
4572 ULONG *pcUniqueNames,
4573 ULONG *pcchUniqueNames)
4575 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4577 FIXME("(%p): stub!\n", This);
4579 if(pcUniqueNames) *pcUniqueNames=1;
4580 if(pcchUniqueNames) *pcchUniqueNames=1;
4581 return S_OK;
4584 /* ITypeLib2::GetDocumentation2
4586 * Retrieves the library's documentation string, the complete Help file name
4587 * and path, the localization context to use, and the context ID for the
4588 * library Help topic in the Help file.
4591 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4592 ITypeLib2 * iface,
4593 INT index,
4594 LCID lcid,
4595 BSTR *pbstrHelpString,
4596 DWORD *pdwHelpStringContext,
4597 BSTR *pbstrHelpStringDll)
4599 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4600 HRESULT result;
4601 ITypeInfo *pTInfo;
4603 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4605 /* the help string should be obtained from the helpstringdll,
4606 * using the _DLLGetDocumentation function, based on the supplied
4607 * lcid. Nice to do sometime...
4609 if(index<0)
4611 /* documentation for the typelib */
4612 if(pbstrHelpString)
4613 *pbstrHelpString=SysAllocString(This->DocString);
4614 if(pdwHelpStringContext)
4615 *pdwHelpStringContext=This->dwHelpContext;
4616 if(pbstrHelpStringDll)
4617 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4619 result = S_OK;
4621 else
4623 /* for a typeinfo */
4624 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4626 if(SUCCEEDED(result))
4628 ITypeInfo2 * pTInfo2;
4629 result = ITypeInfo_QueryInterface(pTInfo,
4630 &IID_ITypeInfo2,
4631 (LPVOID*) &pTInfo2);
4633 if(SUCCEEDED(result))
4635 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4636 MEMBERID_NIL,
4637 lcid,
4638 pbstrHelpString,
4639 pdwHelpStringContext,
4640 pbstrHelpStringDll);
4642 ITypeInfo2_Release(pTInfo2);
4645 ITypeInfo_Release(pTInfo);
4648 return result;
4651 /* ITypeLib2::GetAllCustData
4653 * Gets all custom data items for the library.
4656 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4657 ITypeLib2 * iface,
4658 CUSTDATA *pCustData)
4660 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4661 TLBCustData *pCData;
4662 int i;
4663 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4664 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4665 if(pCustData->prgCustData ){
4666 pCustData->cCustData=This->ctCustData;
4667 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4668 pCustData->prgCustData[i].guid=pCData->guid;
4669 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4671 }else{
4672 ERR(" OUT OF MEMORY!\n");
4673 return E_OUTOFMEMORY;
4675 return S_OK;
4678 static const ITypeLib2Vtbl tlbvt = {
4679 ITypeLib2_fnQueryInterface,
4680 ITypeLib2_fnAddRef,
4681 ITypeLib2_fnRelease,
4682 ITypeLib2_fnGetTypeInfoCount,
4683 ITypeLib2_fnGetTypeInfo,
4684 ITypeLib2_fnGetTypeInfoType,
4685 ITypeLib2_fnGetTypeInfoOfGuid,
4686 ITypeLib2_fnGetLibAttr,
4687 ITypeLib2_fnGetTypeComp,
4688 ITypeLib2_fnGetDocumentation,
4689 ITypeLib2_fnIsName,
4690 ITypeLib2_fnFindName,
4691 ITypeLib2_fnReleaseTLibAttr,
4693 ITypeLib2_fnGetCustData,
4694 ITypeLib2_fnGetLibStatistics,
4695 ITypeLib2_fnGetDocumentation2,
4696 ITypeLib2_fnGetAllCustData
4700 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4702 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4704 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4707 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4709 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4711 return ITypeLib2_AddRef((ITypeLib2 *)This);
4714 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4716 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4718 return ITypeLib2_Release((ITypeLib2 *)This);
4721 static HRESULT WINAPI ITypeLibComp_fnBind(
4722 ITypeComp * iface,
4723 OLECHAR * szName,
4724 ULONG lHash,
4725 WORD wFlags,
4726 ITypeInfo ** ppTInfo,
4727 DESCKIND * pDescKind,
4728 BINDPTR * pBindPtr)
4730 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4731 ITypeInfoImpl *pTypeInfo;
4732 int typemismatch=0;
4734 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4736 *pDescKind = DESCKIND_NONE;
4737 pBindPtr->lptcomp = NULL;
4738 *ppTInfo = NULL;
4740 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4742 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4744 /* FIXME: check wFlags here? */
4745 /* FIXME: we should use a hash table to look this info up using lHash
4746 * instead of an O(n) search */
4747 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4748 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4750 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4752 *pDescKind = DESCKIND_TYPECOMP;
4753 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4754 ITypeComp_AddRef(pBindPtr->lptcomp);
4755 TRACE("module or enum: %s\n", debugstr_w(szName));
4756 return S_OK;
4760 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4761 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4763 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4764 HRESULT hr;
4766 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4767 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4769 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4770 return S_OK;
4772 else if (hr == TYPE_E_TYPEMISMATCH)
4773 typemismatch = 1;
4776 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4777 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4779 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4780 HRESULT hr;
4781 ITypeInfo *subtypeinfo;
4782 BINDPTR subbindptr;
4783 DESCKIND subdesckind;
4785 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4786 &subtypeinfo, &subdesckind, &subbindptr);
4787 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4789 TYPEDESC tdesc_appobject =
4792 (TYPEDESC *)pTypeInfo->hreftype
4794 VT_USERDEFINED
4796 const VARDESC vardesc_appobject =
4798 -2, /* memid */
4799 NULL, /* lpstrSchema */
4801 0 /* oInst */
4804 /* ELEMDESC */
4806 /* TYPEDESC */
4808 &tdesc_appobject
4810 VT_PTR
4813 0, /* wVarFlags */
4814 VAR_STATIC /* varkind */
4817 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4819 /* cleanup things filled in by Bind call so we can put our
4820 * application object data in there instead */
4821 switch (subdesckind)
4823 case DESCKIND_FUNCDESC:
4824 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4825 break;
4826 case DESCKIND_VARDESC:
4827 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4828 break;
4829 default:
4830 break;
4832 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4834 if (pTypeInfo->hreftype == -1)
4835 FIXME("no hreftype for interface %p\n", pTypeInfo);
4837 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4838 if (FAILED(hr))
4839 return hr;
4841 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4842 *ppTInfo = (ITypeInfo *)pTypeInfo;
4843 ITypeInfo_AddRef(*ppTInfo);
4844 return S_OK;
4846 else if (hr == TYPE_E_TYPEMISMATCH)
4847 typemismatch = 1;
4851 if (typemismatch)
4853 TRACE("type mismatch %s\n", debugstr_w(szName));
4854 return TYPE_E_TYPEMISMATCH;
4856 else
4858 TRACE("name not found %s\n", debugstr_w(szName));
4859 return S_OK;
4863 static HRESULT WINAPI ITypeLibComp_fnBindType(
4864 ITypeComp * iface,
4865 OLECHAR * szName,
4866 ULONG lHash,
4867 ITypeInfo ** ppTInfo,
4868 ITypeComp ** ppTComp)
4870 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4871 ITypeInfoImpl *pTypeInfo;
4873 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4875 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4877 /* FIXME: should use lHash to do the search */
4878 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4880 TRACE("returning %p\n", pTypeInfo);
4881 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4882 ITypeInfo_AddRef(*ppTInfo);
4883 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4884 ITypeComp_AddRef(*ppTComp);
4885 return S_OK;
4889 TRACE("not found\n");
4890 *ppTInfo = NULL;
4891 *ppTComp = NULL;
4892 return S_OK;
4895 static const ITypeCompVtbl tlbtcvt =
4898 ITypeLibComp_fnQueryInterface,
4899 ITypeLibComp_fnAddRef,
4900 ITypeLibComp_fnRelease,
4902 ITypeLibComp_fnBind,
4903 ITypeLibComp_fnBindType
4906 /*================== ITypeInfo(2) Methods ===================================*/
4907 static ITypeInfo2 * ITypeInfo_Constructor(void)
4909 ITypeInfoImpl * pTypeInfoImpl;
4911 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4912 if (pTypeInfoImpl)
4914 pTypeInfoImpl->lpVtbl = &tinfvt;
4915 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4916 pTypeInfoImpl->ref = 0;
4917 pTypeInfoImpl->hreftype = -1;
4918 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4919 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4921 TRACE("(%p)\n", pTypeInfoImpl);
4922 return (ITypeInfo2*) pTypeInfoImpl;
4925 /* ITypeInfo::QueryInterface
4927 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4928 ITypeInfo2 *iface,
4929 REFIID riid,
4930 VOID **ppvObject)
4932 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4934 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4936 *ppvObject=NULL;
4937 if(IsEqualIID(riid, &IID_IUnknown) ||
4938 IsEqualIID(riid,&IID_ITypeInfo)||
4939 IsEqualIID(riid,&IID_ITypeInfo2))
4940 *ppvObject = This;
4942 if(*ppvObject){
4943 ITypeInfo_AddRef(iface);
4944 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4945 return S_OK;
4947 TRACE("-- Interface: E_NOINTERFACE\n");
4948 return E_NOINTERFACE;
4951 /* ITypeInfo::AddRef
4953 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4955 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4956 ULONG ref = InterlockedIncrement(&This->ref);
4958 TRACE("(%p)->ref is %u\n",This, ref);
4960 if (ref == 1 /* incremented from 0 */)
4961 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4963 return ref;
4966 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This)
4968 TLBFuncDesc *pFInfo, *pFInfoNext;
4969 TLBVarDesc *pVInfo, *pVInfoNext;
4970 TLBImplType *pImpl, *pImplNext;
4972 TRACE("destroying ITypeInfo(%p)\n",This);
4974 SysFreeString(This->Name);
4975 This->Name = NULL;
4977 SysFreeString(This->DocString);
4978 This->DocString = NULL;
4980 SysFreeString(This->DllName);
4981 This->DllName = NULL;
4983 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4985 INT i;
4986 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4988 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4989 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4991 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4992 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4994 SysFreeString(pFInfo->pParamDesc[i].Name);
4996 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4997 TLB_Free(pFInfo->pParamDesc);
4998 TLB_FreeCustData(pFInfo->pCustData);
4999 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5000 SysFreeString(pFInfo->Entry);
5001 SysFreeString(pFInfo->HelpString);
5002 SysFreeString(pFInfo->Name);
5004 pFInfoNext = pFInfo->next;
5005 TLB_Free(pFInfo);
5007 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5009 if (pVInfo->vardesc.varkind == VAR_CONST)
5011 VariantClear(pVInfo->vardesc.u.lpvarValue);
5012 TLB_Free(pVInfo->vardesc.u.lpvarValue);
5014 TLB_FreeCustData(pVInfo->pCustData);
5015 SysFreeString(pVInfo->Name);
5016 pVInfoNext = pVInfo->next;
5017 TLB_Free(pVInfo);
5019 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5021 TLB_FreeCustData(pImpl->pCustData);
5022 pImplNext = pImpl->next;
5023 TLB_Free(pImpl);
5025 TLB_FreeCustData(This->pCustData);
5027 HeapFree(GetProcessHeap(), 0, This);
5030 /* ITypeInfo::Release
5032 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5034 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5035 ULONG ref = InterlockedDecrement(&This->ref);
5037 TRACE("(%p)->(%u)\n",This, ref);
5039 if (!ref)
5041 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5042 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5043 if (not_attached_to_typelib)
5044 HeapFree(GetProcessHeap(), 0, This);
5045 /* otherwise This will be freed when typelib is freed */
5048 return ref;
5051 /* ITypeInfo::GetTypeAttr
5053 * Retrieves a TYPEATTR structure that contains the attributes of the type
5054 * description.
5057 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5058 LPTYPEATTR *ppTypeAttr)
5060 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5061 SIZE_T size;
5063 TRACE("(%p)\n",This);
5065 size = sizeof(**ppTypeAttr);
5066 if (This->TypeAttr.typekind == TKIND_ALIAS)
5067 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5069 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5070 if (!*ppTypeAttr)
5071 return E_OUTOFMEMORY;
5073 **ppTypeAttr = This->TypeAttr;
5075 if (This->TypeAttr.typekind == TKIND_ALIAS)
5076 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5077 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5079 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5080 /* This should include all the inherited funcs */
5081 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5082 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5083 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5085 return S_OK;
5088 /* ITypeInfo::GetTypeComp
5090 * Retrieves the ITypeComp interface for the type description, which enables a
5091 * client compiler to bind to the type description's members.
5094 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5095 ITypeComp * *ppTComp)
5097 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5099 TRACE("(%p)->(%p)\n", This, ppTComp);
5101 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5102 ITypeComp_AddRef(*ppTComp);
5103 return S_OK;
5106 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5108 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5109 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5110 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5111 return size;
5114 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5116 *dest = *src;
5117 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5118 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5120 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5121 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5122 *buffer += sizeof(PARAMDESCEX);
5123 *pparamdescex_dest = *pparamdescex_src;
5124 VariantInit(&pparamdescex_dest->varDefaultValue);
5125 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5126 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5128 else
5129 dest->u.paramdesc.pparamdescex = NULL;
5130 return S_OK;
5133 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5135 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5136 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5139 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5141 FUNCDESC *dest;
5142 char *buffer;
5143 SIZE_T size = sizeof(*src);
5144 SHORT i;
5145 HRESULT hr;
5147 size += sizeof(*src->lprgscode) * src->cScodes;
5148 size += TLB_SizeElemDesc(&src->elemdescFunc);
5149 for (i = 0; i < src->cParams; i++)
5151 size += sizeof(ELEMDESC);
5152 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5155 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5156 if (!dest) return E_OUTOFMEMORY;
5158 *dest = *src;
5159 if (dispinterface) /* overwrite funckind */
5160 dest->funckind = FUNC_DISPATCH;
5161 buffer = (char *)(dest + 1);
5163 dest->lprgscode = (SCODE *)buffer;
5164 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5165 buffer += sizeof(*src->lprgscode) * src->cScodes;
5167 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5168 if (FAILED(hr))
5170 SysFreeString((BSTR)dest);
5171 return hr;
5174 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5175 buffer += sizeof(ELEMDESC) * src->cParams;
5176 for (i = 0; i < src->cParams; i++)
5178 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5179 if (FAILED(hr))
5180 break;
5182 if (FAILED(hr))
5184 /* undo the above actions */
5185 for (i = i - 1; i >= 0; i--)
5186 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5187 TLB_FreeElemDesc(&dest->elemdescFunc);
5188 SysFreeString((BSTR)dest);
5189 return hr;
5192 /* special treatment for dispinterfaces: this makes functions appear
5193 * to return their [retval] value when it is really returning an
5194 * HRESULT */
5195 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5197 if (dest->cParams &&
5198 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5200 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5201 if (elemdesc->tdesc.vt != VT_PTR)
5203 ERR("elemdesc should have started with VT_PTR instead of:\n");
5204 if (ERR_ON(ole))
5205 dump_ELEMDESC(elemdesc);
5206 return E_UNEXPECTED;
5209 /* copy last parameter to the return value. we are using a flat
5210 * buffer so there is no danger of leaking memory in
5211 * elemdescFunc */
5212 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5214 /* remove the last parameter */
5215 dest->cParams--;
5217 else
5218 /* otherwise this function is made to appear to have no return
5219 * value */
5220 dest->elemdescFunc.tdesc.vt = VT_VOID;
5224 *dest_ptr = dest;
5225 return S_OK;
5228 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5230 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5231 const TLBFuncDesc *pFDesc;
5232 UINT i;
5234 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5237 if (pFDesc)
5239 *ppFuncDesc = &pFDesc->funcdesc;
5240 return S_OK;
5243 return TYPE_E_ELEMENTNOTFOUND;
5246 /* internal function to make the inherited interfaces' methods appear
5247 * part of the interface */
5248 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5249 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5251 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5252 HRESULT hr;
5253 UINT implemented_funcs = 0;
5255 if (funcs)
5256 *funcs = 0;
5257 else
5258 *hrefoffset = DISPATCH_HREF_OFFSET;
5260 if(This->impltypelist)
5262 ITypeInfo *pSubTypeInfo;
5263 UINT sub_funcs;
5265 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5266 if (FAILED(hr))
5267 return hr;
5269 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5270 index,
5271 ppFuncDesc,
5272 &sub_funcs, hrefoffset);
5273 implemented_funcs += sub_funcs;
5274 ITypeInfo_Release(pSubTypeInfo);
5275 if (SUCCEEDED(hr))
5276 return hr;
5277 *hrefoffset += DISPATCH_HREF_OFFSET;
5280 if (funcs)
5281 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5282 else
5283 *hrefoffset = 0;
5285 if (index < implemented_funcs)
5286 return E_INVALIDARG;
5287 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5288 ppFuncDesc);
5291 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5293 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5294 while (TRUE)
5296 switch (pTypeDesc->vt)
5298 case VT_USERDEFINED:
5299 pTypeDesc->u.hreftype += hrefoffset;
5300 return;
5301 case VT_PTR:
5302 case VT_SAFEARRAY:
5303 pTypeDesc = pTypeDesc->u.lptdesc;
5304 break;
5305 case VT_CARRAY:
5306 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5307 break;
5308 default:
5309 return;
5314 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5316 SHORT i;
5317 for (i = 0; i < pFuncDesc->cParams; i++)
5318 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5319 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5322 /* ITypeInfo::GetFuncDesc
5324 * Retrieves the FUNCDESC structure that contains information about a
5325 * specified function.
5328 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5329 LPFUNCDESC *ppFuncDesc)
5331 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5332 const FUNCDESC *internal_funcdesc;
5333 HRESULT hr;
5334 UINT hrefoffset = 0;
5336 TRACE("(%p) index %d\n", This, index);
5338 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5339 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5340 &internal_funcdesc, NULL,
5341 &hrefoffset);
5342 else
5343 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5344 &internal_funcdesc);
5345 if (FAILED(hr))
5347 WARN("description for function %d not found\n", index);
5348 return hr;
5351 hr = TLB_AllocAndInitFuncDesc(
5352 internal_funcdesc,
5353 ppFuncDesc,
5354 This->TypeAttr.typekind == TKIND_DISPATCH);
5356 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5357 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5359 TRACE("-- 0x%08x\n", hr);
5360 return hr;
5363 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5365 VARDESC *dest;
5366 char *buffer;
5367 SIZE_T size = sizeof(*src);
5368 HRESULT hr;
5370 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5371 if (src->varkind == VAR_CONST)
5372 size += sizeof(VARIANT);
5373 size += TLB_SizeElemDesc(&src->elemdescVar);
5375 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5376 if (!dest) return E_OUTOFMEMORY;
5378 *dest = *src;
5379 buffer = (char *)(dest + 1);
5380 if (src->lpstrSchema)
5382 int len;
5383 dest->lpstrSchema = (LPOLESTR)buffer;
5384 len = strlenW(src->lpstrSchema);
5385 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5386 buffer += (len + 1) * sizeof(WCHAR);
5389 if (src->varkind == VAR_CONST)
5391 HRESULT hr;
5393 dest->u.lpvarValue = (VARIANT *)buffer;
5394 *dest->u.lpvarValue = *src->u.lpvarValue;
5395 buffer += sizeof(VARIANT);
5396 VariantInit(dest->u.lpvarValue);
5397 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5398 if (FAILED(hr))
5400 SysFreeString((BSTR)dest);
5401 return hr;
5404 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5405 if (FAILED(hr))
5407 if (src->varkind == VAR_CONST)
5408 VariantClear(dest->u.lpvarValue);
5409 SysFreeString((BSTR)dest);
5410 return hr;
5412 *dest_ptr = dest;
5413 return S_OK;
5416 /* ITypeInfo::GetVarDesc
5418 * Retrieves a VARDESC structure that describes the specified variable.
5421 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5422 LPVARDESC *ppVarDesc)
5424 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5425 UINT i;
5426 const TLBVarDesc *pVDesc;
5428 TRACE("(%p) index %d\n", This, index);
5430 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5433 if (pVDesc)
5434 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5436 return E_INVALIDARG;
5439 /* ITypeInfo_GetNames
5441 * Retrieves the variable with the specified member ID (or the name of the
5442 * property or method and its parameters) that correspond to the specified
5443 * function ID.
5445 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5446 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5448 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5449 const TLBFuncDesc *pFDesc;
5450 const TLBVarDesc *pVDesc;
5451 int i;
5452 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5453 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5454 if(pFDesc)
5456 /* function found, now return function and parameter names */
5457 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5459 if(!i)
5460 *rgBstrNames=SysAllocString(pFDesc->Name);
5461 else
5462 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5464 *pcNames=i;
5466 else
5468 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5469 if(pVDesc)
5471 *rgBstrNames=SysAllocString(pVDesc->Name);
5472 *pcNames=1;
5474 else
5476 if(This->impltypelist &&
5477 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5478 /* recursive search */
5479 ITypeInfo *pTInfo;
5480 HRESULT result;
5481 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5482 &pTInfo);
5483 if(SUCCEEDED(result))
5485 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5486 ITypeInfo_Release(pTInfo);
5487 return result;
5489 WARN("Could not search inherited interface!\n");
5491 else
5493 WARN("no names found\n");
5495 *pcNames=0;
5496 return TYPE_E_ELEMENTNOTFOUND;
5499 return S_OK;
5503 /* ITypeInfo::GetRefTypeOfImplType
5505 * If a type description describes a COM class, it retrieves the type
5506 * description of the implemented interface types. For an interface,
5507 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5508 * if any exist.
5511 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5512 ITypeInfo2 *iface,
5513 UINT index,
5514 HREFTYPE *pRefType)
5516 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5517 UINT i;
5518 HRESULT hr = S_OK;
5519 const TLBImplType *pImpl = This->impltypelist;
5521 TRACE("(%p) index %d\n", This, index);
5522 if (TRACE_ON(ole)) dump_TypeInfo(This);
5524 if(index==(UINT)-1)
5526 /* only valid on dual interfaces;
5527 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5529 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5531 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5533 *pRefType = -1;
5535 else
5537 hr = TYPE_E_ELEMENTNOTFOUND;
5540 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5542 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5543 *pRefType = This->pTypeLib->dispatch_href;
5545 else
5547 /* get element n from linked list */
5548 for(i=0; pImpl && i<index; i++)
5550 pImpl = pImpl->next;
5553 if (pImpl)
5554 *pRefType = pImpl->hRef;
5555 else
5556 hr = TYPE_E_ELEMENTNOTFOUND;
5559 if(TRACE_ON(ole))
5561 if(SUCCEEDED(hr))
5562 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5563 else
5564 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5567 return hr;
5570 /* ITypeInfo::GetImplTypeFlags
5572 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5573 * or base interface in a type description.
5575 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5576 UINT index, INT *pImplTypeFlags)
5578 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5579 UINT i;
5580 TLBImplType *pImpl;
5582 TRACE("(%p) index %d\n", This, index);
5583 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5584 i++, pImpl=pImpl->next)
5586 if(i==index && pImpl){
5587 *pImplTypeFlags=pImpl->implflags;
5588 return S_OK;
5590 *pImplTypeFlags=0;
5592 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5593 return S_OK;
5595 WARN("ImplType %d not found\n", index);
5596 return TYPE_E_ELEMENTNOTFOUND;
5599 /* GetIDsOfNames
5600 * Maps between member names and member IDs, and parameter names and
5601 * parameter IDs.
5603 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5604 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5606 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5607 const TLBFuncDesc *pFDesc;
5608 const TLBVarDesc *pVDesc;
5609 HRESULT ret=S_OK;
5610 UINT i;
5612 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5613 cNames);
5615 /* init out parameters in case of failure */
5616 for (i = 0; i < cNames; i++)
5617 pMemId[i] = MEMBERID_NIL;
5619 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5620 int j;
5621 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5622 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5623 for(i=1; i < cNames; i++){
5624 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5625 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5626 break;
5627 if( j<pFDesc->funcdesc.cParams)
5628 pMemId[i]=j;
5629 else
5630 ret=DISP_E_UNKNOWNNAME;
5632 TRACE("-- 0x%08x\n", ret);
5633 return ret;
5636 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5637 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5638 if(cNames) *pMemId=pVDesc->vardesc.memid;
5639 return ret;
5642 /* not found, see if it can be found in an inherited interface */
5643 if(This->impltypelist) {
5644 /* recursive search */
5645 ITypeInfo *pTInfo;
5646 ret=ITypeInfo_GetRefTypeInfo(iface,
5647 This->impltypelist->hRef, &pTInfo);
5648 if(SUCCEEDED(ret)){
5649 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5650 ITypeInfo_Release(pTInfo);
5651 return ret;
5653 WARN("Could not search inherited interface!\n");
5654 } else
5655 WARN("no names found\n");
5656 return DISP_E_UNKNOWNNAME;
5660 #ifdef __i386__
5662 extern DWORD CDECL call_method( void *func, int nb_args, const DWORD *args );
5663 __ASM_GLOBAL_FUNC( call_method,
5664 "pushl %ebp\n\t"
5665 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5666 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5667 "movl %esp,%ebp\n\t"
5668 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5669 "pushl %esi\n\t"
5670 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5671 "pushl %edi\n\t"
5672 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5673 "movl 12(%ebp),%edx\n\t"
5674 "shll $2,%edx\n\t"
5675 "jz 1f\n\t"
5676 "subl %edx,%esp\n\t"
5677 "andl $~15,%esp\n\t"
5678 "movl 12(%ebp),%ecx\n\t"
5679 "movl 16(%ebp),%esi\n\t"
5680 "movl %esp,%edi\n\t"
5681 "cld\n\t"
5682 "rep; movsl\n"
5683 "1:\tcall *8(%ebp)\n\t"
5684 "leal -8(%ebp),%esp\n\t"
5685 "popl %edi\n\t"
5686 __ASM_CFI(".cfi_same_value %edi\n\t")
5687 "popl %esi\n\t"
5688 __ASM_CFI(".cfi_same_value %esi\n\t")
5689 "popl %ebp\n\t"
5690 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5691 __ASM_CFI(".cfi_same_value %ebp\n\t")
5692 "ret" )
5694 /* ITypeInfo::Invoke
5696 * Invokes a method, or accesses a property of an object, that implements the
5697 * interface described by the type description.
5699 DWORD
5700 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5701 DWORD res;
5703 if (TRACE_ON(ole)) {
5704 int i;
5705 TRACE("Calling %p(",func);
5706 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5707 TRACE(")\n");
5710 switch (callconv) {
5711 case CC_STDCALL:
5712 case CC_CDECL:
5713 res = call_method( func, nrargs, args );
5714 break;
5715 default:
5716 FIXME("unsupported calling convention %d\n",callconv);
5717 res = -1;
5718 break;
5720 TRACE("returns %08x\n",res);
5721 return res;
5724 /* The size of the argument on the stack in DWORD units (in all x86 call
5725 * convetions the arguments on the stack are DWORD-aligned)
5727 static int _dispargsize(VARTYPE vt)
5729 switch (vt) {
5730 case VT_I8:
5731 case VT_UI8:
5732 return 8/sizeof(DWORD);
5733 case VT_R8:
5734 return sizeof(double)/sizeof(DWORD);
5735 case VT_DECIMAL:
5736 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5737 case VT_CY:
5738 return sizeof(CY)/sizeof(DWORD);
5739 case VT_DATE:
5740 return sizeof(DATE)/sizeof(DWORD);
5741 case VT_VARIANT:
5742 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5743 case VT_RECORD:
5744 FIXME("VT_RECORD not implemented\n");
5745 return 1;
5746 default:
5747 return 1;
5750 #endif /* __i386__ */
5752 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5754 HRESULT hr = S_OK;
5755 ITypeInfo *tinfo2 = NULL;
5756 TYPEATTR *tattr = NULL;
5758 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5759 if (hr)
5761 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5762 "hr = 0x%08x\n",
5763 tdesc->u.hreftype, hr);
5764 return hr;
5766 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5767 if (hr)
5769 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5770 ITypeInfo_Release(tinfo2);
5771 return hr;
5774 switch (tattr->typekind)
5776 case TKIND_ENUM:
5777 *vt |= VT_I4;
5778 break;
5780 case TKIND_ALIAS:
5781 tdesc = &tattr->tdescAlias;
5782 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5783 break;
5785 case TKIND_INTERFACE:
5786 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5787 *vt |= VT_DISPATCH;
5788 else
5789 *vt |= VT_UNKNOWN;
5790 break;
5792 case TKIND_DISPATCH:
5793 *vt |= VT_DISPATCH;
5794 break;
5796 case TKIND_COCLASS:
5797 *vt |= VT_DISPATCH;
5798 break;
5800 case TKIND_RECORD:
5801 FIXME("TKIND_RECORD unhandled.\n");
5802 hr = E_NOTIMPL;
5803 break;
5805 case TKIND_UNION:
5806 FIXME("TKIND_UNION unhandled.\n");
5807 hr = E_NOTIMPL;
5808 break;
5810 default:
5811 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5812 hr = E_NOTIMPL;
5813 break;
5815 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5816 ITypeInfo_Release(tinfo2);
5817 return hr;
5820 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5822 HRESULT hr = S_OK;
5824 /* enforce only one level of pointer indirection */
5825 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5827 tdesc = tdesc->u.lptdesc;
5829 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5830 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5831 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5832 if ((tdesc->vt == VT_USERDEFINED) ||
5833 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5835 VARTYPE vt_userdefined = 0;
5836 const TYPEDESC *tdesc_userdefined = tdesc;
5837 if (tdesc->vt == VT_PTR)
5839 vt_userdefined = VT_BYREF;
5840 tdesc_userdefined = tdesc->u.lptdesc;
5842 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5843 if ((hr == S_OK) &&
5844 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5845 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5847 *vt |= vt_userdefined;
5848 return S_OK;
5851 *vt = VT_BYREF;
5854 switch (tdesc->vt)
5856 case VT_HRESULT:
5857 *vt |= VT_ERROR;
5858 break;
5859 case VT_USERDEFINED:
5860 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5861 break;
5862 case VT_VOID:
5863 case VT_CARRAY:
5864 case VT_PTR:
5865 case VT_LPSTR:
5866 case VT_LPWSTR:
5867 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5868 hr = DISP_E_BADVARTYPE;
5869 break;
5870 case VT_SAFEARRAY:
5871 *vt |= VT_ARRAY;
5872 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5873 break;
5874 case VT_INT:
5875 *vt |= VT_I4;
5876 break;
5877 case VT_UINT:
5878 *vt |= VT_UI4;
5879 break;
5880 default:
5881 *vt |= tdesc->vt;
5882 break;
5884 return hr;
5887 /***********************************************************************
5888 * DispCallFunc (OLEAUT32.@)
5890 * Invokes a function of the specified calling convention, passing the
5891 * specified arguments and returns the result.
5893 * PARAMS
5894 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5895 * oVft [I] The offset in the vtable. See notes.
5896 * cc [I] Calling convention of the function to call.
5897 * vtReturn [I] The return type of the function.
5898 * cActuals [I] Number of parameters.
5899 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5900 * prgpvarg [I] The arguments to pass.
5901 * pvargResult [O] The return value of the function. Can be NULL.
5903 * RETURNS
5904 * Success: S_OK.
5905 * Failure: HRESULT code.
5907 * NOTES
5908 * The HRESULT return value of this function is not affected by the return
5909 * value of the user supplied function, which is returned in pvargResult.
5911 * If pvInstance is NULL then a non-object function is to be called and oVft
5912 * is the address of the function to call.
5914 * The cc parameter can be one of the following values:
5915 *|CC_FASTCALL
5916 *|CC_CDECL
5917 *|CC_PASCAL
5918 *|CC_STDCALL
5919 *|CC_FPFASTCALL
5920 *|CC_SYSCALL
5921 *|CC_MPWCDECL
5922 *|CC_MPWPASCAL
5925 HRESULT WINAPI
5926 DispCallFunc(
5927 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5928 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5930 #ifdef __i386__
5931 int argsize, argspos;
5932 UINT i;
5933 DWORD *args;
5934 HRESULT hres;
5936 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5937 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5938 pvargResult, V_VT(pvargResult));
5940 argsize = 0;
5941 if (pvInstance)
5942 argsize++; /* for This pointer */
5944 for (i=0;i<cActuals;i++)
5946 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5947 dump_Variant(prgpvarg[i]);
5948 argsize += _dispargsize(prgvt[i]);
5950 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5952 argspos = 0;
5953 if (pvInstance)
5955 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5956 argspos++;
5959 for (i=0;i<cActuals;i++)
5961 VARIANT *arg = prgpvarg[i];
5962 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5963 if (prgvt[i] == VT_VARIANT)
5964 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5965 else
5966 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5967 argspos += _dispargsize(prgvt[i]);
5970 if (pvInstance)
5972 FARPROC *vtable = *(FARPROC**)pvInstance;
5973 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5975 else
5976 /* if we aren't invoking an object then the function pointer is stored
5977 * in oVft */
5978 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5980 if (pvargResult && (vtReturn != VT_EMPTY))
5982 TRACE("Method returned 0x%08x\n",hres);
5983 V_VT(pvargResult) = vtReturn;
5984 V_UI4(pvargResult) = hres;
5986 HeapFree(GetProcessHeap(),0,args);
5987 return S_OK;
5988 #else
5989 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
5990 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
5991 return E_NOTIMPL;
5992 #endif
5995 #define INVBUF_ELEMENT_SIZE \
5996 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5997 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5998 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5999 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6000 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6001 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6002 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6003 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6005 static HRESULT WINAPI ITypeInfo_fnInvoke(
6006 ITypeInfo2 *iface,
6007 VOID *pIUnk,
6008 MEMBERID memid,
6009 UINT16 wFlags,
6010 DISPPARAMS *pDispParams,
6011 VARIANT *pVarResult,
6012 EXCEPINFO *pExcepInfo,
6013 UINT *pArgErr)
6015 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6016 int i;
6017 unsigned int var_index;
6018 TYPEKIND type_kind;
6019 HRESULT hres;
6020 const TLBFuncDesc *pFuncInfo;
6022 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6023 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6026 if (!pDispParams)
6028 ERR("NULL pDispParams not allowed\n");
6029 return E_INVALIDARG;
6032 dump_DispParms(pDispParams);
6034 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6036 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6037 pDispParams->cNamedArgs, pDispParams->cArgs);
6038 return E_INVALIDARG;
6041 /* we do this instead of using GetFuncDesc since it will return a fake
6042 * FUNCDESC for dispinterfaces and we want the real function description */
6043 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6044 if ((memid == pFuncInfo->funcdesc.memid) &&
6045 (wFlags & pFuncInfo->funcdesc.invkind))
6046 break;
6048 if (pFuncInfo) {
6049 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6051 if (TRACE_ON(ole))
6053 TRACE("invoking:\n");
6054 dump_TLBFuncDescOne(pFuncInfo);
6057 switch (func_desc->funckind) {
6058 case FUNC_PUREVIRTUAL:
6059 case FUNC_VIRTUAL: {
6060 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6061 VARIANT varresult;
6062 VARIANT retval; /* pointer for storing byref retvals in */
6063 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6064 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6065 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6066 UINT cNamedArgs = pDispParams->cNamedArgs;
6067 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6068 UINT vargs_converted=0;
6070 hres = S_OK;
6072 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6074 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6076 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6077 hres = DISP_E_PARAMNOTFOUND;
6078 goto func_fail;
6082 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6084 ERR("functions with the vararg attribute do not support named arguments\n");
6085 hres = DISP_E_NONAMEDARGS;
6086 goto func_fail;
6089 for (i = 0; i < func_desc->cParams; i++)
6091 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6092 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6093 if (FAILED(hres))
6094 goto func_fail;
6097 TRACE("changing args\n");
6098 for (i = 0; i < func_desc->cParams; i++)
6100 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6101 VARIANTARG *src_arg;
6103 if (wParamFlags & PARAMFLAG_FLCID)
6105 VARIANTARG *arg;
6106 arg = prgpvarg[i] = &rgvarg[i];
6107 V_VT(arg) = VT_I4;
6108 V_I4(arg) = This->pTypeLib->lcid;
6109 continue;
6112 src_arg = NULL;
6114 if (cNamedArgs)
6116 USHORT j;
6117 for (j = 0; j < cNamedArgs; j++)
6118 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6120 src_arg = &pDispParams->rgvarg[j];
6121 break;
6125 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6127 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6128 vargs_converted++;
6131 if (wParamFlags & PARAMFLAG_FRETVAL)
6133 /* under most conditions the caller is not allowed to
6134 * pass in a dispparam arg in the index of what would be
6135 * the retval parameter. however, there is an exception
6136 * where the extra parameter is used in an extra
6137 * IDispatch::Invoke below */
6138 if ((i < pDispParams->cArgs) &&
6139 ((func_desc->cParams != 1) || !pVarResult ||
6140 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6142 hres = DISP_E_BADPARAMCOUNT;
6143 break;
6146 /* note: this check is placed so that if the caller passes
6147 * in a VARIANTARG for the retval we just ignore it, like
6148 * native does */
6149 if (i == func_desc->cParams - 1)
6151 VARIANTARG *arg;
6152 arg = prgpvarg[i] = &rgvarg[i];
6153 memset(arg, 0, sizeof(*arg));
6154 V_VT(arg) = rgvt[i];
6155 memset(&retval, 0, sizeof(retval));
6156 V_BYREF(arg) = &retval;
6158 else
6160 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6161 hres = E_UNEXPECTED;
6162 break;
6165 else if (src_arg)
6167 dump_Variant(src_arg);
6169 if (rgvt[i] == VT_VARIANT)
6170 hres = VariantCopy(&rgvarg[i], src_arg);
6171 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6173 if (rgvt[i] == V_VT(src_arg))
6174 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6175 else
6177 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6178 if (wParamFlags & PARAMFLAG_FIN)
6179 hres = VariantCopy(&missing_arg[i], src_arg);
6180 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6182 V_VT(&rgvarg[i]) = rgvt[i];
6184 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6186 SAFEARRAY *a;
6187 SAFEARRAYBOUND bound;
6188 VARIANT *v;
6189 LONG j;
6190 bound.lLbound = 0;
6191 bound.cElements = pDispParams->cArgs-i;
6192 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6194 ERR("SafeArrayCreate failed\n");
6195 break;
6197 hres = SafeArrayAccessData(a, (LPVOID)&v);
6198 if (hres != S_OK)
6200 ERR("SafeArrayAccessData failed with %x\n", hres);
6201 break;
6203 for (j = 0; j < bound.cElements; j++)
6204 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6205 hres = SafeArrayUnaccessData(a);
6206 if (hres != S_OK)
6208 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6209 break;
6211 V_ARRAY(&rgvarg[i]) = a;
6212 V_VT(&rgvarg[i]) = rgvt[i];
6214 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6216 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6217 if (wParamFlags & PARAMFLAG_FIN)
6218 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6219 else
6220 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6221 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6222 V_VT(&rgvarg[i]) = rgvt[i];
6224 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6226 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6227 V_VT(&rgvarg[i]) = rgvt[i];
6229 else
6231 /* FIXME: this doesn't work for VT_BYREF arguments if
6232 * they are not the same type as in the paramdesc */
6233 V_VT(&rgvarg[i]) = V_VT(src_arg);
6234 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6235 V_VT(&rgvarg[i]) = rgvt[i];
6238 if (FAILED(hres))
6240 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6241 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6242 debugstr_VT(src_arg), debugstr_VF(src_arg));
6243 break;
6245 prgpvarg[i] = &rgvarg[i];
6247 else if (wParamFlags & PARAMFLAG_FOPT)
6249 VARIANTARG *arg;
6250 arg = prgpvarg[i] = &rgvarg[i];
6251 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6253 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6254 if (FAILED(hres))
6255 break;
6257 else
6259 VARIANTARG *missing_arg;
6260 /* if the function wants a pointer to a variant then
6261 * set that up, otherwise just pass the VT_ERROR in
6262 * the argument by value */
6263 if (rgvt[i] & VT_BYREF)
6265 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6266 V_VT(arg) = VT_VARIANT | VT_BYREF;
6267 V_VARIANTREF(arg) = missing_arg;
6269 else
6270 missing_arg = arg;
6271 V_VT(missing_arg) = VT_ERROR;
6272 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6275 else
6277 hres = DISP_E_BADPARAMCOUNT;
6278 break;
6281 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6283 /* VT_VOID is a special case for return types, so it is not
6284 * handled in the general function */
6285 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6286 V_VT(&varresult) = VT_EMPTY;
6287 else
6289 V_VT(&varresult) = 0;
6290 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6291 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6294 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6295 V_VT(&varresult), func_desc->cParams, rgvt,
6296 prgpvarg, &varresult);
6298 vargs_converted = 0;
6300 for (i = 0; i < func_desc->cParams; i++)
6302 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6303 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6305 if (wParamFlags & PARAMFLAG_FLCID)
6306 continue;
6307 else if (wParamFlags & PARAMFLAG_FRETVAL)
6309 if (TRACE_ON(ole))
6311 TRACE("[retval] value: ");
6312 dump_Variant(prgpvarg[i]);
6315 if (pVarResult)
6317 VariantInit(pVarResult);
6318 /* deref return value */
6319 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6322 VARIANT_ClearInd(prgpvarg[i]);
6324 else if (vargs_converted < pDispParams->cArgs)
6326 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6327 if (wParamFlags & PARAMFLAG_FOUT)
6329 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6331 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6333 if (FAILED(hres))
6335 ERR("failed to convert param %d to vt %d\n", i,
6336 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6337 break;
6341 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6342 func_desc->cParamsOpt < 0 &&
6343 i == func_desc->cParams-1)
6345 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6346 LONG j, ubound;
6347 VARIANT *v;
6348 hres = SafeArrayGetUBound(a, 1, &ubound);
6349 if (hres != S_OK)
6351 ERR("SafeArrayGetUBound failed with %x\n", hres);
6352 break;
6354 hres = SafeArrayAccessData(a, (LPVOID)&v);
6355 if (hres != S_OK)
6357 ERR("SafeArrayAccessData failed with %x\n", hres);
6358 break;
6360 for (j = 0; j <= ubound; j++)
6361 VariantClear(&v[j]);
6362 hres = SafeArrayUnaccessData(a);
6363 if (hres != S_OK)
6365 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6366 break;
6369 VariantClear(&rgvarg[i]);
6370 vargs_converted++;
6372 else if (wParamFlags & PARAMFLAG_FOPT)
6374 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6375 VariantClear(&rgvarg[i]);
6378 VariantClear(&missing_arg[i]);
6381 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6383 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6384 hres = DISP_E_EXCEPTION;
6385 if (pExcepInfo)
6387 IErrorInfo *pErrorInfo;
6388 pExcepInfo->scode = V_ERROR(&varresult);
6389 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6391 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6392 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6393 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6394 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6396 IErrorInfo_Release(pErrorInfo);
6400 if (V_VT(&varresult) != VT_ERROR)
6402 TRACE("varresult value: ");
6403 dump_Variant(&varresult);
6405 if (pVarResult)
6407 VariantClear(pVarResult);
6408 *pVarResult = varresult;
6410 else
6411 VariantClear(&varresult);
6414 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6415 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6416 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6417 (pDispParams->cArgs != 0))
6419 if (V_VT(pVarResult) == VT_DISPATCH)
6421 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6422 /* Note: not VariantClear; we still need the dispatch
6423 * pointer to be valid */
6424 VariantInit(pVarResult);
6425 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6426 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6427 pDispParams, pVarResult, pExcepInfo, pArgErr);
6428 IDispatch_Release(pDispatch);
6430 else
6432 VariantClear(pVarResult);
6433 hres = DISP_E_NOTACOLLECTION;
6437 func_fail:
6438 HeapFree(GetProcessHeap(), 0, buffer);
6439 break;
6441 case FUNC_DISPATCH: {
6442 IDispatch *disp;
6444 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6445 if (SUCCEEDED(hres)) {
6446 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6447 hres = IDispatch_Invoke(
6448 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6449 pVarResult,pExcepInfo,pArgErr
6451 if (FAILED(hres))
6452 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6453 IDispatch_Release(disp);
6454 } else
6455 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6456 break;
6458 default:
6459 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6460 hres = E_FAIL;
6461 break;
6464 TRACE("-- 0x%08x\n", hres);
6465 return hres;
6467 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6468 VARDESC *var_desc;
6470 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6471 if(FAILED(hres)) return hres;
6473 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6474 dump_VARDESC(var_desc);
6475 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6476 return E_NOTIMPL;
6479 /* not found, look for it in inherited interfaces */
6480 ITypeInfo2_GetTypeKind(iface, &type_kind);
6481 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6482 if(This->impltypelist) {
6483 /* recursive search */
6484 ITypeInfo *pTInfo;
6485 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6486 if(SUCCEEDED(hres)){
6487 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6488 ITypeInfo_Release(pTInfo);
6489 return hres;
6491 WARN("Could not search inherited interface!\n");
6494 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6495 return DISP_E_MEMBERNOTFOUND;
6498 /* ITypeInfo::GetDocumentation
6500 * Retrieves the documentation string, the complete Help file name and path,
6501 * and the context ID for the Help topic for a specified type description.
6503 * (Can be tested by the Visual Basic Editor in Word for instance.)
6505 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6506 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6507 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6509 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6510 const TLBFuncDesc *pFDesc;
6511 const TLBVarDesc *pVDesc;
6512 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6513 " HelpContext(%p) HelpFile(%p)\n",
6514 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6515 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6516 if(pBstrName)
6517 *pBstrName=SysAllocString(This->Name);
6518 if(pBstrDocString)
6519 *pBstrDocString=SysAllocString(This->DocString);
6520 if(pdwHelpContext)
6521 *pdwHelpContext=This->dwHelpContext;
6522 if(pBstrHelpFile)
6523 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6524 return S_OK;
6525 }else {/* for a member */
6526 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6527 if(pFDesc->funcdesc.memid==memid){
6528 if(pBstrName)
6529 *pBstrName = SysAllocString(pFDesc->Name);
6530 if(pBstrDocString)
6531 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6532 if(pdwHelpContext)
6533 *pdwHelpContext=pFDesc->helpcontext;
6534 return S_OK;
6536 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6537 if(pVDesc->vardesc.memid==memid){
6538 if(pBstrName)
6539 *pBstrName = SysAllocString(pVDesc->Name);
6540 if(pBstrDocString)
6541 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6542 if(pdwHelpContext)
6543 *pdwHelpContext=pVDesc->HelpContext;
6544 return S_OK;
6548 if(This->impltypelist &&
6549 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6550 /* recursive search */
6551 ITypeInfo *pTInfo;
6552 HRESULT result;
6553 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6554 &pTInfo);
6555 if(SUCCEEDED(result)) {
6556 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6557 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6558 ITypeInfo_Release(pTInfo);
6559 return result;
6561 WARN("Could not search inherited interface!\n");
6564 WARN("member %d not found\n", memid);
6565 return TYPE_E_ELEMENTNOTFOUND;
6568 /* ITypeInfo::GetDllEntry
6570 * Retrieves a description or specification of an entry point for a function
6571 * in a DLL.
6573 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6574 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6575 WORD *pwOrdinal)
6577 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6578 const TLBFuncDesc *pFDesc;
6580 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6582 if (pBstrDllName) *pBstrDllName = NULL;
6583 if (pBstrName) *pBstrName = NULL;
6584 if (pwOrdinal) *pwOrdinal = 0;
6586 if (This->TypeAttr.typekind != TKIND_MODULE)
6587 return TYPE_E_BADMODULEKIND;
6589 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6590 if(pFDesc->funcdesc.memid==memid){
6591 dump_TypeInfo(This);
6592 if (TRACE_ON(ole))
6593 dump_TLBFuncDescOne(pFDesc);
6595 if (pBstrDllName)
6596 *pBstrDllName = SysAllocString(This->DllName);
6598 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6599 if (pBstrName)
6600 *pBstrName = SysAllocString(pFDesc->Entry);
6601 if (pwOrdinal)
6602 *pwOrdinal = -1;
6603 return S_OK;
6605 if (pBstrName)
6606 *pBstrName = NULL;
6607 if (pwOrdinal)
6608 *pwOrdinal = (DWORD)pFDesc->Entry;
6609 return S_OK;
6611 return TYPE_E_ELEMENTNOTFOUND;
6614 /* internal function to make the inherited interfaces' methods appear
6615 * part of the interface */
6616 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6617 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6619 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6620 HRESULT hr;
6622 TRACE("%p, 0x%x\n", iface, *hRefType);
6624 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6626 ITypeInfo *pSubTypeInfo;
6628 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6629 if (FAILED(hr))
6630 return hr;
6632 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6633 hRefType, ppTInfo);
6634 ITypeInfo_Release(pSubTypeInfo);
6635 if (SUCCEEDED(hr))
6636 return hr;
6638 *hRefType -= DISPATCH_HREF_OFFSET;
6640 if (!(*hRefType & DISPATCH_HREF_MASK))
6641 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6642 else
6643 return E_FAIL;
6646 /* ITypeInfo::GetRefTypeInfo
6648 * If a type description references other type descriptions, it retrieves
6649 * the referenced type descriptions.
6651 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6652 ITypeInfo2 *iface,
6653 HREFTYPE hRefType,
6654 ITypeInfo **ppTInfo)
6656 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6657 HRESULT result = E_FAIL;
6659 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6661 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6662 ITypeInfo_AddRef(*ppTInfo);
6663 result = S_OK;
6665 else if (hRefType == -1 &&
6666 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6667 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6669 /* when we meet a DUAL dispinterface, we must create the interface
6670 * version of it.
6672 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6675 /* the interface version contains the same information as the dispinterface
6676 * copy the contents of the structs.
6678 *pTypeInfoImpl = *This;
6679 pTypeInfoImpl->ref = 0;
6681 /* change the type to interface */
6682 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6684 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6686 /* the AddRef implicitly adds a reference to the parent typelib, which
6687 * stops the copied data from being destroyed until the new typeinfo's
6688 * refcount goes to zero, but we need to signal to the new instance to
6689 * not free its data structures when it is destroyed */
6690 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6692 ITypeInfo_AddRef(*ppTInfo);
6694 result = S_OK;
6696 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6697 (This->TypeAttr.typekind == TKIND_DISPATCH))
6699 HREFTYPE href_dispatch = hRefType;
6700 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6701 } else {
6702 TLBRefType *ref_type;
6703 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6705 if(ref_type->reference == hRefType)
6706 break;
6708 if(&ref_type->entry == &This->pTypeLib->ref_list)
6710 FIXME("Can't find pRefType for ref %x\n", hRefType);
6711 goto end;
6713 if(hRefType != -1) {
6714 ITypeLib *pTLib = NULL;
6716 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6717 UINT Index;
6718 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6719 } else {
6720 if(ref_type->pImpTLInfo->pImpTypeLib) {
6721 TRACE("typeinfo in imported typelib that is already loaded\n");
6722 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6723 ITypeLib2_AddRef(pTLib);
6724 result = S_OK;
6725 } else {
6726 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6727 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6728 ref_type->pImpTLInfo->wVersionMajor,
6729 ref_type->pImpTLInfo->wVersionMinor,
6730 ref_type->pImpTLInfo->lcid,
6731 &pTLib);
6733 if(FAILED(result)) {
6734 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6735 result=LoadTypeLib(libnam, &pTLib);
6736 SysFreeString(libnam);
6738 if(SUCCEEDED(result)) {
6739 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6740 ITypeLib2_AddRef(pTLib);
6744 if(SUCCEEDED(result)) {
6745 if(ref_type->index == TLB_REF_USE_GUID)
6746 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6747 &ref_type->guid,
6748 ppTInfo);
6749 else
6750 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6751 ppTInfo);
6753 if (pTLib != NULL)
6754 ITypeLib2_Release(pTLib);
6758 end:
6759 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6760 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6761 return result;
6764 /* ITypeInfo::AddressOfMember
6766 * Retrieves the addresses of static functions or variables, such as those
6767 * defined in a DLL.
6769 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6770 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6772 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6773 HRESULT hr;
6774 BSTR dll, entry;
6775 WORD ordinal;
6776 HMODULE module;
6778 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6780 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6781 if (FAILED(hr))
6782 return hr;
6784 module = LoadLibraryW(dll);
6785 if (!module)
6787 ERR("couldn't load %s\n", debugstr_w(dll));
6788 SysFreeString(dll);
6789 SysFreeString(entry);
6790 return STG_E_FILENOTFOUND;
6792 /* FIXME: store library somewhere where we can free it */
6794 if (entry)
6796 LPSTR entryA;
6797 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6798 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6799 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6801 *ppv = GetProcAddress(module, entryA);
6802 if (!*ppv)
6803 ERR("function not found %s\n", debugstr_a(entryA));
6805 HeapFree(GetProcessHeap(), 0, entryA);
6807 else
6809 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6810 if (!*ppv)
6811 ERR("function not found %d\n", ordinal);
6814 SysFreeString(dll);
6815 SysFreeString(entry);
6817 if (!*ppv)
6818 return TYPE_E_DLLFUNCTIONNOTFOUND;
6820 return S_OK;
6823 /* ITypeInfo::CreateInstance
6825 * Creates a new instance of a type that describes a component object class
6826 * (coclass).
6828 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6829 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6831 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6832 HRESULT hr;
6833 TYPEATTR *pTA;
6835 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6837 *ppvObj = NULL;
6839 if(pOuterUnk)
6841 WARN("Not able to aggregate\n");
6842 return CLASS_E_NOAGGREGATION;
6845 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6846 if(FAILED(hr)) return hr;
6848 if(pTA->typekind != TKIND_COCLASS)
6850 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6851 hr = E_INVALIDARG;
6852 goto end;
6855 hr = S_FALSE;
6856 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6858 IUnknown *pUnk;
6859 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6860 TRACE("GetActiveObject rets %08x\n", hr);
6861 if(hr == S_OK)
6863 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6864 IUnknown_Release(pUnk);
6868 if(hr != S_OK)
6869 hr = CoCreateInstance(&pTA->guid, NULL,
6870 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6871 riid, ppvObj);
6873 end:
6874 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6875 return hr;
6878 /* ITypeInfo::GetMops
6880 * Retrieves marshalling information.
6882 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6883 BSTR *pBstrMops)
6885 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6886 FIXME("(%p %d) stub!\n", This, memid);
6887 *pBstrMops = NULL;
6888 return S_OK;
6891 /* ITypeInfo::GetContainingTypeLib
6893 * Retrieves the containing type library and the index of the type description
6894 * within that type library.
6896 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6897 ITypeLib * *ppTLib, UINT *pIndex)
6899 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6901 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6902 if (pIndex) {
6903 *pIndex=This->index;
6904 TRACE("returning pIndex=%d\n", *pIndex);
6907 if (ppTLib) {
6908 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6909 ITypeLib2_AddRef(*ppTLib);
6910 TRACE("returning ppTLib=%p\n", *ppTLib);
6913 return S_OK;
6916 /* ITypeInfo::ReleaseTypeAttr
6918 * Releases a TYPEATTR previously returned by GetTypeAttr.
6921 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6922 TYPEATTR* pTypeAttr)
6924 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6925 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6926 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6929 /* ITypeInfo::ReleaseFuncDesc
6931 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6933 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6934 ITypeInfo2 *iface,
6935 FUNCDESC *pFuncDesc)
6937 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6938 SHORT i;
6940 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6942 for (i = 0; i < pFuncDesc->cParams; i++)
6943 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6944 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6946 SysFreeString((BSTR)pFuncDesc);
6949 /* ITypeInfo::ReleaseVarDesc
6951 * Releases a VARDESC previously returned by GetVarDesc.
6953 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6954 VARDESC *pVarDesc)
6956 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6957 TRACE("(%p)->(%p)\n", This, pVarDesc);
6959 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6960 if (pVarDesc->varkind == VAR_CONST)
6961 VariantClear(pVarDesc->u.lpvarValue);
6962 SysFreeString((BSTR)pVarDesc);
6965 /* ITypeInfo2::GetTypeKind
6967 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6970 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6971 TYPEKIND *pTypeKind)
6973 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6974 *pTypeKind=This->TypeAttr.typekind;
6975 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6976 return S_OK;
6979 /* ITypeInfo2::GetTypeFlags
6981 * Returns the type flags without any allocations. This returns a DWORD type
6982 * flag, which expands the type flags without growing the TYPEATTR (type
6983 * attribute).
6986 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6988 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6989 *pTypeFlags=This->TypeAttr.wTypeFlags;
6990 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6991 return S_OK;
6994 /* ITypeInfo2::GetFuncIndexOfMemId
6995 * Binds to a specific member based on a known DISPID, where the member name
6996 * is not known (for example, when binding to a default member).
6999 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7000 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7002 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7003 const TLBFuncDesc *pFuncInfo;
7004 int i;
7005 HRESULT result;
7007 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7008 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7009 break;
7010 if(pFuncInfo) {
7011 *pFuncIndex = i;
7012 result = S_OK;
7013 } else
7014 result = TYPE_E_ELEMENTNOTFOUND;
7016 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7017 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7018 return result;
7021 /* TypeInfo2::GetVarIndexOfMemId
7023 * Binds to a specific member based on a known DISPID, where the member name
7024 * is not known (for example, when binding to a default member).
7027 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7028 MEMBERID memid, UINT *pVarIndex)
7030 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7031 TLBVarDesc *pVarInfo;
7032 int i;
7033 HRESULT result;
7034 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7035 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7037 if(pVarInfo) {
7038 *pVarIndex = i;
7039 result = S_OK;
7040 } else
7041 result = TYPE_E_ELEMENTNOTFOUND;
7043 TRACE("(%p) memid 0x%08x -> %s\n", This,
7044 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7045 return result;
7048 /* ITypeInfo2::GetCustData
7050 * Gets the custom data
7052 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7053 ITypeInfo2 * iface,
7054 REFGUID guid,
7055 VARIANT *pVarVal)
7057 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7058 TLBCustData *pCData;
7060 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7061 if( IsEqualIID(guid, &pCData->guid)) break;
7063 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7065 VariantInit( pVarVal);
7066 if (pCData)
7067 VariantCopy( pVarVal, &pCData->data);
7068 else
7069 VariantClear( pVarVal );
7070 return S_OK;
7073 /* ITypeInfo2::GetFuncCustData
7075 * Gets the custom data
7077 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7078 ITypeInfo2 * iface,
7079 UINT index,
7080 REFGUID guid,
7081 VARIANT *pVarVal)
7083 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7084 TLBCustData *pCData=NULL;
7085 TLBFuncDesc * pFDesc;
7086 UINT i;
7087 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7088 pFDesc=pFDesc->next);
7090 if(pFDesc)
7091 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7092 if( IsEqualIID(guid, &pCData->guid)) break;
7094 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7096 if(pCData){
7097 VariantInit( pVarVal);
7098 VariantCopy( pVarVal, &pCData->data);
7099 return S_OK;
7101 return E_INVALIDARG; /* FIXME: correct? */
7104 /* ITypeInfo2::GetParamCustData
7106 * Gets the custom data
7108 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7109 ITypeInfo2 * iface,
7110 UINT indexFunc,
7111 UINT indexParam,
7112 REFGUID guid,
7113 VARIANT *pVarVal)
7115 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7116 TLBCustData *pCData=NULL;
7117 TLBFuncDesc * pFDesc;
7118 UINT i;
7120 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7122 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7123 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7124 pCData = pCData->next)
7125 if( IsEqualIID(guid, &pCData->guid)) break;
7127 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7129 if(pCData)
7131 VariantInit( pVarVal);
7132 VariantCopy( pVarVal, &pCData->data);
7133 return S_OK;
7135 return E_INVALIDARG; /* FIXME: correct? */
7138 /* ITypeInfo2::GetVarCustData
7140 * Gets the custom data
7142 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7143 ITypeInfo2 * iface,
7144 UINT index,
7145 REFGUID guid,
7146 VARIANT *pVarVal)
7148 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7149 TLBCustData *pCData=NULL;
7150 TLBVarDesc * pVDesc;
7151 UINT i;
7153 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7155 if(pVDesc)
7157 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7159 if( IsEqualIID(guid, &pCData->guid)) break;
7163 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7165 if(pCData)
7167 VariantInit( pVarVal);
7168 VariantCopy( pVarVal, &pCData->data);
7169 return S_OK;
7171 return E_INVALIDARG; /* FIXME: correct? */
7174 /* ITypeInfo2::GetImplCustData
7176 * Gets the custom data
7178 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7179 ITypeInfo2 * iface,
7180 UINT index,
7181 REFGUID guid,
7182 VARIANT *pVarVal)
7184 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7185 TLBCustData *pCData=NULL;
7186 TLBImplType * pRDesc;
7187 UINT i;
7189 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7191 if(pRDesc)
7193 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7195 if( IsEqualIID(guid, &pCData->guid)) break;
7199 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7201 if(pCData)
7203 VariantInit( pVarVal);
7204 VariantCopy( pVarVal, &pCData->data);
7205 return S_OK;
7207 return E_INVALIDARG; /* FIXME: correct? */
7210 /* ITypeInfo2::GetDocumentation2
7212 * Retrieves the documentation string, the complete Help file name and path,
7213 * the localization context to use, and the context ID for the library Help
7214 * topic in the Help file.
7217 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7218 ITypeInfo2 * iface,
7219 MEMBERID memid,
7220 LCID lcid,
7221 BSTR *pbstrHelpString,
7222 DWORD *pdwHelpStringContext,
7223 BSTR *pbstrHelpStringDll)
7225 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7226 const TLBFuncDesc *pFDesc;
7227 const TLBVarDesc *pVDesc;
7228 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7229 "HelpStringContext(%p) HelpStringDll(%p)\n",
7230 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7231 pbstrHelpStringDll );
7232 /* the help string should be obtained from the helpstringdll,
7233 * using the _DLLGetDocumentation function, based on the supplied
7234 * lcid. Nice to do sometime...
7236 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7237 if(pbstrHelpString)
7238 *pbstrHelpString=SysAllocString(This->Name);
7239 if(pdwHelpStringContext)
7240 *pdwHelpStringContext=This->dwHelpStringContext;
7241 if(pbstrHelpStringDll)
7242 *pbstrHelpStringDll=
7243 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7244 return S_OK;
7245 }else {/* for a member */
7246 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7247 if(pFDesc->funcdesc.memid==memid){
7248 if(pbstrHelpString)
7249 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7250 if(pdwHelpStringContext)
7251 *pdwHelpStringContext=pFDesc->HelpStringContext;
7252 if(pbstrHelpStringDll)
7253 *pbstrHelpStringDll=
7254 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7255 return S_OK;
7257 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7258 if(pVDesc->vardesc.memid==memid){
7259 if(pbstrHelpString)
7260 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7261 if(pdwHelpStringContext)
7262 *pdwHelpStringContext=pVDesc->HelpStringContext;
7263 if(pbstrHelpStringDll)
7264 *pbstrHelpStringDll=
7265 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7266 return S_OK;
7269 return TYPE_E_ELEMENTNOTFOUND;
7272 /* ITypeInfo2::GetAllCustData
7274 * Gets all custom data items for the Type info.
7277 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7278 ITypeInfo2 * iface,
7279 CUSTDATA *pCustData)
7281 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7282 TLBCustData *pCData;
7283 int i;
7285 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7287 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7288 if(pCustData->prgCustData ){
7289 pCustData->cCustData=This->ctCustData;
7290 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7291 pCustData->prgCustData[i].guid=pCData->guid;
7292 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7294 }else{
7295 ERR(" OUT OF MEMORY!\n");
7296 return E_OUTOFMEMORY;
7298 return S_OK;
7301 /* ITypeInfo2::GetAllFuncCustData
7303 * Gets all custom data items for the specified Function
7306 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7307 ITypeInfo2 * iface,
7308 UINT index,
7309 CUSTDATA *pCustData)
7311 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7312 TLBCustData *pCData;
7313 TLBFuncDesc * pFDesc;
7314 UINT i;
7315 TRACE("(%p) index %d\n", This, index);
7316 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7317 pFDesc=pFDesc->next)
7319 if(pFDesc){
7320 pCustData->prgCustData =
7321 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7322 if(pCustData->prgCustData ){
7323 pCustData->cCustData=pFDesc->ctCustData;
7324 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7325 pCData = pCData->next){
7326 pCustData->prgCustData[i].guid=pCData->guid;
7327 VariantCopy(& pCustData->prgCustData[i].varValue,
7328 & pCData->data);
7330 }else{
7331 ERR(" OUT OF MEMORY!\n");
7332 return E_OUTOFMEMORY;
7334 return S_OK;
7336 return TYPE_E_ELEMENTNOTFOUND;
7339 /* ITypeInfo2::GetAllParamCustData
7341 * Gets all custom data items for the Functions
7344 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7345 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7347 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7348 TLBCustData *pCData=NULL;
7349 TLBFuncDesc * pFDesc;
7350 UINT i;
7351 TRACE("(%p) index %d\n", This, indexFunc);
7352 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7353 pFDesc=pFDesc->next)
7355 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7356 pCustData->prgCustData =
7357 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7358 sizeof(CUSTDATAITEM));
7359 if(pCustData->prgCustData ){
7360 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7361 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7362 pCData; i++, pCData = pCData->next){
7363 pCustData->prgCustData[i].guid=pCData->guid;
7364 VariantCopy(& pCustData->prgCustData[i].varValue,
7365 & pCData->data);
7367 }else{
7368 ERR(" OUT OF MEMORY!\n");
7369 return E_OUTOFMEMORY;
7371 return S_OK;
7373 return TYPE_E_ELEMENTNOTFOUND;
7376 /* ITypeInfo2::GetAllVarCustData
7378 * Gets all custom data items for the specified Variable
7381 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7382 UINT index, CUSTDATA *pCustData)
7384 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7385 TLBCustData *pCData;
7386 TLBVarDesc * pVDesc;
7387 UINT i;
7388 TRACE("(%p) index %d\n", This, index);
7389 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7390 pVDesc=pVDesc->next)
7392 if(pVDesc){
7393 pCustData->prgCustData =
7394 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7395 if(pCustData->prgCustData ){
7396 pCustData->cCustData=pVDesc->ctCustData;
7397 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7398 pCData = pCData->next){
7399 pCustData->prgCustData[i].guid=pCData->guid;
7400 VariantCopy(& pCustData->prgCustData[i].varValue,
7401 & pCData->data);
7403 }else{
7404 ERR(" OUT OF MEMORY!\n");
7405 return E_OUTOFMEMORY;
7407 return S_OK;
7409 return TYPE_E_ELEMENTNOTFOUND;
7412 /* ITypeInfo2::GetAllImplCustData
7414 * Gets all custom data items for the specified implementation type
7417 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7418 ITypeInfo2 * iface,
7419 UINT index,
7420 CUSTDATA *pCustData)
7422 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7423 TLBCustData *pCData;
7424 TLBImplType * pRDesc;
7425 UINT i;
7426 TRACE("(%p) index %d\n", This, index);
7427 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7428 pRDesc=pRDesc->next)
7430 if(pRDesc){
7431 pCustData->prgCustData =
7432 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7433 if(pCustData->prgCustData ){
7434 pCustData->cCustData=pRDesc->ctCustData;
7435 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7436 pCData = pCData->next){
7437 pCustData->prgCustData[i].guid=pCData->guid;
7438 VariantCopy(& pCustData->prgCustData[i].varValue,
7439 & pCData->data);
7441 }else{
7442 ERR(" OUT OF MEMORY!\n");
7443 return E_OUTOFMEMORY;
7445 return S_OK;
7447 return TYPE_E_ELEMENTNOTFOUND;
7450 static const ITypeInfo2Vtbl tinfvt =
7453 ITypeInfo_fnQueryInterface,
7454 ITypeInfo_fnAddRef,
7455 ITypeInfo_fnRelease,
7457 ITypeInfo_fnGetTypeAttr,
7458 ITypeInfo_fnGetTypeComp,
7459 ITypeInfo_fnGetFuncDesc,
7460 ITypeInfo_fnGetVarDesc,
7461 ITypeInfo_fnGetNames,
7462 ITypeInfo_fnGetRefTypeOfImplType,
7463 ITypeInfo_fnGetImplTypeFlags,
7464 ITypeInfo_fnGetIDsOfNames,
7465 ITypeInfo_fnInvoke,
7466 ITypeInfo_fnGetDocumentation,
7467 ITypeInfo_fnGetDllEntry,
7468 ITypeInfo_fnGetRefTypeInfo,
7469 ITypeInfo_fnAddressOfMember,
7470 ITypeInfo_fnCreateInstance,
7471 ITypeInfo_fnGetMops,
7472 ITypeInfo_fnGetContainingTypeLib,
7473 ITypeInfo_fnReleaseTypeAttr,
7474 ITypeInfo_fnReleaseFuncDesc,
7475 ITypeInfo_fnReleaseVarDesc,
7477 ITypeInfo2_fnGetTypeKind,
7478 ITypeInfo2_fnGetTypeFlags,
7479 ITypeInfo2_fnGetFuncIndexOfMemId,
7480 ITypeInfo2_fnGetVarIndexOfMemId,
7481 ITypeInfo2_fnGetCustData,
7482 ITypeInfo2_fnGetFuncCustData,
7483 ITypeInfo2_fnGetParamCustData,
7484 ITypeInfo2_fnGetVarCustData,
7485 ITypeInfo2_fnGetImplTypeCustData,
7486 ITypeInfo2_fnGetDocumentation2,
7487 ITypeInfo2_fnGetAllCustData,
7488 ITypeInfo2_fnGetAllFuncCustData,
7489 ITypeInfo2_fnGetAllParamCustData,
7490 ITypeInfo2_fnGetAllVarCustData,
7491 ITypeInfo2_fnGetAllImplTypeCustData,
7494 /******************************************************************************
7495 * CreateDispTypeInfo [OLEAUT32.31]
7497 * Build type information for an object so it can be called through an
7498 * IDispatch interface.
7500 * RETURNS
7501 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7502 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7504 * NOTES
7505 * This call allows an objects methods to be accessed through IDispatch, by
7506 * building an ITypeInfo object that IDispatch can use to call through.
7508 HRESULT WINAPI CreateDispTypeInfo(
7509 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7510 LCID lcid, /* [I] Locale Id */
7511 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7513 ITypeInfoImpl *pTIClass, *pTIIface;
7514 ITypeLibImpl *pTypeLibImpl;
7515 unsigned int param, func;
7516 TLBFuncDesc **ppFuncDesc;
7517 TLBRefType *ref;
7519 TRACE("\n");
7520 pTypeLibImpl = TypeLibImpl_Constructor();
7521 if (!pTypeLibImpl) return E_FAIL;
7523 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7524 pTIIface->pTypeLib = pTypeLibImpl;
7525 pTIIface->index = 0;
7526 pTIIface->Name = NULL;
7527 pTIIface->dwHelpContext = -1;
7528 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7529 pTIIface->TypeAttr.lcid = lcid;
7530 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7531 pTIIface->TypeAttr.wMajorVerNum = 0;
7532 pTIIface->TypeAttr.wMinorVerNum = 0;
7533 pTIIface->TypeAttr.cbAlignment = 2;
7534 pTIIface->TypeAttr.cbSizeInstance = -1;
7535 pTIIface->TypeAttr.cbSizeVft = -1;
7536 pTIIface->TypeAttr.cFuncs = 0;
7537 pTIIface->TypeAttr.cImplTypes = 0;
7538 pTIIface->TypeAttr.cVars = 0;
7539 pTIIface->TypeAttr.wTypeFlags = 0;
7541 ppFuncDesc = &pTIIface->funclist;
7542 for(func = 0; func < pidata->cMembers; func++) {
7543 METHODDATA *md = pidata->pmethdata + func;
7544 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7545 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7546 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7547 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7548 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7549 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7550 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7551 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7552 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7553 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7554 (*ppFuncDesc)->funcdesc.cScodes = 0;
7555 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7556 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7557 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7558 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7559 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7560 md->cArgs * sizeof(ELEMDESC));
7561 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7562 md->cArgs * sizeof(TLBParDesc));
7563 for(param = 0; param < md->cArgs; param++) {
7564 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7565 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7567 (*ppFuncDesc)->helpcontext = 0;
7568 (*ppFuncDesc)->HelpStringContext = 0;
7569 (*ppFuncDesc)->HelpString = NULL;
7570 (*ppFuncDesc)->Entry = NULL;
7571 (*ppFuncDesc)->ctCustData = 0;
7572 (*ppFuncDesc)->pCustData = NULL;
7573 (*ppFuncDesc)->next = NULL;
7574 pTIIface->TypeAttr.cFuncs++;
7575 ppFuncDesc = &(*ppFuncDesc)->next;
7578 dump_TypeInfo(pTIIface);
7580 pTypeLibImpl->pTypeInfo = pTIIface;
7581 pTypeLibImpl->TypeInfoCount++;
7583 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7584 pTIClass->pTypeLib = pTypeLibImpl;
7585 pTIClass->index = 1;
7586 pTIClass->Name = NULL;
7587 pTIClass->dwHelpContext = -1;
7588 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7589 pTIClass->TypeAttr.lcid = lcid;
7590 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7591 pTIClass->TypeAttr.wMajorVerNum = 0;
7592 pTIClass->TypeAttr.wMinorVerNum = 0;
7593 pTIClass->TypeAttr.cbAlignment = 2;
7594 pTIClass->TypeAttr.cbSizeInstance = -1;
7595 pTIClass->TypeAttr.cbSizeVft = -1;
7596 pTIClass->TypeAttr.cFuncs = 0;
7597 pTIClass->TypeAttr.cImplTypes = 1;
7598 pTIClass->TypeAttr.cVars = 0;
7599 pTIClass->TypeAttr.wTypeFlags = 0;
7601 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7602 pTIClass->impltypelist->hRef = 0;
7604 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7605 ref->index = 0;
7606 ref->reference = 0;
7607 ref->pImpTLInfo = TLB_REF_INTERNAL;
7608 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7610 dump_TypeInfo(pTIClass);
7612 pTIIface->next = pTIClass;
7613 pTypeLibImpl->TypeInfoCount++;
7615 *pptinfo = (ITypeInfo*)pTIClass;
7617 ITypeInfo_AddRef(*pptinfo);
7618 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7620 return S_OK;
7624 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7626 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7628 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7631 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7633 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7635 return ITypeInfo_AddRef((ITypeInfo *)This);
7638 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7640 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7642 return ITypeInfo_Release((ITypeInfo *)This);
7645 static HRESULT WINAPI ITypeComp_fnBind(
7646 ITypeComp * iface,
7647 OLECHAR * szName,
7648 ULONG lHash,
7649 WORD wFlags,
7650 ITypeInfo ** ppTInfo,
7651 DESCKIND * pDescKind,
7652 BINDPTR * pBindPtr)
7654 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7655 const TLBFuncDesc *pFDesc;
7656 const TLBVarDesc *pVDesc;
7657 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7659 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7661 *pDescKind = DESCKIND_NONE;
7662 pBindPtr->lpfuncdesc = NULL;
7663 *ppTInfo = NULL;
7665 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7666 if (!strcmpiW(pFDesc->Name, szName)) {
7667 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7668 break;
7669 else
7670 /* name found, but wrong flags */
7671 hr = TYPE_E_TYPEMISMATCH;
7674 if (pFDesc)
7676 HRESULT hr = TLB_AllocAndInitFuncDesc(
7677 &pFDesc->funcdesc,
7678 &pBindPtr->lpfuncdesc,
7679 This->TypeAttr.typekind == TKIND_DISPATCH);
7680 if (FAILED(hr))
7681 return hr;
7682 *pDescKind = DESCKIND_FUNCDESC;
7683 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7684 ITypeInfo_AddRef(*ppTInfo);
7685 return S_OK;
7686 } else {
7687 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7688 if (!strcmpiW(pVDesc->Name, szName)) {
7689 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7690 if (FAILED(hr))
7691 return hr;
7692 *pDescKind = DESCKIND_VARDESC;
7693 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7694 ITypeInfo_AddRef(*ppTInfo);
7695 return S_OK;
7699 /* FIXME: search each inherited interface, not just the first */
7700 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7701 /* recursive search */
7702 ITypeInfo *pTInfo;
7703 ITypeComp *pTComp;
7704 HRESULT hr;
7705 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7706 if (SUCCEEDED(hr))
7708 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7709 ITypeInfo_Release(pTInfo);
7711 if (SUCCEEDED(hr))
7713 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7714 ITypeComp_Release(pTComp);
7715 return hr;
7717 WARN("Could not search inherited interface!\n");
7719 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7720 return hr;
7723 static HRESULT WINAPI ITypeComp_fnBindType(
7724 ITypeComp * iface,
7725 OLECHAR * szName,
7726 ULONG lHash,
7727 ITypeInfo ** ppTInfo,
7728 ITypeComp ** ppTComp)
7730 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7732 /* strange behaviour (does nothing) but like the
7733 * original */
7735 if (!ppTInfo || !ppTComp)
7736 return E_POINTER;
7738 *ppTInfo = NULL;
7739 *ppTComp = NULL;
7741 return S_OK;
7744 static const ITypeCompVtbl tcompvt =
7747 ITypeComp_fnQueryInterface,
7748 ITypeComp_fnAddRef,
7749 ITypeComp_fnRelease,
7751 ITypeComp_fnBind,
7752 ITypeComp_fnBindType