push cc8bc80451cc24f4d7cf75168b569f0ebfe19547
[wine/hacks.git] / dlls / oleaut32 / typelib.c
blob10f5e238af2bfec4cf4788c8f5eeb2abe3f3dacd
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
48 #include "config.h"
49 #include "wine/port.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
67 #include "lzexpand.h"
69 #include "wine/unicode.h"
70 #include "objbase.h"
71 #include "typelib.h"
72 #include "wine/debug.h"
73 #include "variant.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 typedef struct
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
89 typedef struct
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
95 * Name info array.
97 } NE_TYPEINFO;
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
102 /****************************************************************************
103 * FromLExxx
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
116 static DWORD FromLEDWord(DWORD p_iVal)
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
123 #else
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
126 #endif
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
132 * FromLExxx
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
139 WORD *Val = p_Val;
141 p_iSize /= sizeof(WORD);
143 while (p_iSize) {
144 *Val = FromLEWord(*Val);
145 Val++;
146 p_iSize--;
151 static void FromLEDWords(void *p_Val, int p_iSize)
153 DWORD *Val = p_Val;
155 p_iSize /= sizeof(DWORD);
157 while (p_iSize) {
158 *Val = FromLEDWord(*Val);
159 Val++;
160 p_iSize--;
163 #else
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
166 #endif
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
174 WCHAR buffer[60];
175 char key_name[16];
176 DWORD len, i;
177 INT best_maj = -1, best_min = -1;
178 HKEY hkey;
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 INT v_maj, v_min;
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
203 best_maj = v_maj;
205 if (*wMin == v_min)
207 best_min = v_min;
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
215 RegCloseKey( hkey );
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
223 *wMaj = best_maj;
224 *wMin = best_min;
225 return TRUE;
229 if (*wMaj == best_maj && best_min >= 0)
231 *wMin = best_min;
232 return TRUE;
234 return FALSE;
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
244 memcpy( buffer, TypelibW, sizeof(TypelibW) );
245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
247 return buffer;
250 /* get the path of an interface key, in the form "Interface\\<guid>" */
251 /* buffer must be at least 50 characters long */
252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
258 return buffer;
261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
262 /* buffer must be at least 16 characters long */
263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
266 static const WCHAR win16W[] = {'w','i','n','1','6',0};
267 static const WCHAR win32W[] = {'w','i','n','3','2',0};
268 static const WCHAR win64W[] = {'w','i','n','6','4',0};
270 sprintfW( buffer, LcidFormatW, lcid );
271 switch(syskind)
273 case SYS_WIN16: strcatW( buffer, win16W ); break;
274 case SYS_WIN32: strcatW( buffer, win32W ); break;
275 case SYS_WIN64: strcatW( buffer, win64W ); break;
276 default:
277 TRACE("Typelib is for unsupported syskind %i\n", syskind);
278 return NULL;
280 return buffer;
283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
286 /****************************************************************************
287 * QueryPathOfRegTypeLib [OLEAUT32.164]
289 * Gets the path to a registered type library.
291 * PARAMS
292 * guid [I] referenced guid
293 * wMaj [I] major version
294 * wMin [I] minor version
295 * lcid [I] locale id
296 * path [O] path of typelib
298 * RETURNS
299 * Success: S_OK.
300 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
301 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
302 * opened.
304 HRESULT WINAPI QueryPathOfRegTypeLib(
305 REFGUID guid,
306 WORD wMaj,
307 WORD wMin,
308 LCID lcid,
309 LPBSTR path )
311 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
312 LCID myLCID = lcid;
313 HKEY hkey;
314 WCHAR buffer[60];
315 WCHAR Path[MAX_PATH];
316 LONG res;
318 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
320 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
321 get_typelib_key( guid, wMaj, wMin, buffer );
323 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
324 if (res == ERROR_FILE_NOT_FOUND)
326 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
327 return TYPE_E_LIBNOTREGISTERED;
329 else if (res != ERROR_SUCCESS)
331 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
332 return TYPE_E_REGISTRYACCESS;
335 while (hr != S_OK)
337 LONG dwPathLen = sizeof(Path);
339 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
341 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
343 if (!lcid)
344 break;
345 else if (myLCID == lcid)
347 /* try with sub-langid */
348 myLCID = SUBLANGID(lcid);
350 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
352 /* try with system langid */
353 myLCID = 0;
355 else
357 break;
360 else
362 *path = SysAllocString( Path );
363 hr = S_OK;
366 RegCloseKey( hkey );
367 TRACE_(typelib)("-- 0x%08x\n", hr);
368 return hr;
371 /******************************************************************************
372 * CreateTypeLib [OLEAUT32.160] creates a typelib
374 * RETURNS
375 * Success: S_OK
376 * Failure: Status
378 HRESULT WINAPI CreateTypeLib(
379 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
381 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
382 return E_FAIL;
385 /******************************************************************************
386 * LoadTypeLib [OLEAUT32.161]
388 * Loads a type library
390 * PARAMS
391 * szFile [I] Name of file to load from.
392 * pptLib [O] Pointer that receives ITypeLib object on success.
394 * RETURNS
395 * Success: S_OK
396 * Failure: Status
398 * SEE
399 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
401 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
403 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
404 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
407 /******************************************************************************
408 * LoadTypeLibEx [OLEAUT32.183]
410 * Loads and optionally registers a type library
412 * RETURNS
413 * Success: S_OK
414 * Failure: Status
416 HRESULT WINAPI LoadTypeLibEx(
417 LPCOLESTR szFile, /* [in] Name of file to load from */
418 REGKIND regkind, /* [in] Specify kind of registration */
419 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
421 WCHAR szPath[MAX_PATH+1];
422 HRESULT res;
424 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
426 *pptLib = NULL;
428 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
430 if (SUCCEEDED(res))
431 switch(regkind)
433 case REGKIND_DEFAULT:
434 /* don't register typelibs supplied with full path. Experimentation confirms the following */
435 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
436 (szFile[0] && (szFile[1] == ':'))) break;
437 /* else fall-through */
439 case REGKIND_REGISTER:
440 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
442 IUnknown_Release(*pptLib);
443 *pptLib = 0;
445 break;
446 case REGKIND_NONE:
447 break;
450 TRACE(" returns %08x\n",res);
451 return res;
454 /******************************************************************************
455 * LoadRegTypeLib [OLEAUT32.162]
457 * Loads a registered type library.
459 * PARAMS
460 * rguid [I] GUID of the registered type library.
461 * wVerMajor [I] major version.
462 * wVerMinor [I] minor version.
463 * lcid [I] locale ID.
464 * ppTLib [O] pointer that receives an ITypeLib object on success.
466 * RETURNS
467 * Success: S_OK.
468 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
469 * LoadTypeLib.
471 HRESULT WINAPI LoadRegTypeLib(
472 REFGUID rguid,
473 WORD wVerMajor,
474 WORD wVerMinor,
475 LCID lcid,
476 ITypeLib **ppTLib)
478 BSTR bstr=NULL;
479 HRESULT res;
481 *ppTLib = NULL;
483 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
485 if(SUCCEEDED(res))
487 res= LoadTypeLib(bstr, ppTLib);
488 SysFreeString(bstr);
491 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
493 return res;
497 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
498 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
499 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
500 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
501 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
502 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
504 /******************************************************************************
505 * RegisterTypeLib [OLEAUT32.163]
506 * Adds information about a type library to the System Registry
507 * NOTES
508 * Docs: ITypeLib FAR * ptlib
509 * Docs: OLECHAR FAR* szFullPath
510 * Docs: OLECHAR FAR* szHelpDir
512 * RETURNS
513 * Success: S_OK
514 * Failure: Status
516 HRESULT WINAPI RegisterTypeLib(
517 ITypeLib * ptlib, /* [in] Pointer to the library*/
518 OLECHAR * szFullPath, /* [in] full Path of the library*/
519 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
520 may be NULL*/
522 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
523 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
524 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
525 HRESULT res;
526 TLIBATTR *attr;
527 WCHAR keyName[60];
528 WCHAR tmp[16];
529 HKEY key, subKey;
530 UINT types, tidx;
531 TYPEKIND kind;
532 DWORD disposition;
534 if (ptlib == NULL || szFullPath == NULL)
535 return E_INVALIDARG;
537 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
538 return E_FAIL;
540 #ifdef _WIN64
541 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
542 #else
543 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
544 #endif
546 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
548 res = S_OK;
549 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
550 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
552 LPOLESTR doc;
554 /* Set the human-readable name of the typelib */
555 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
557 if (RegSetValueExW(key, NULL, 0, REG_SZ,
558 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
559 res = E_FAIL;
561 SysFreeString(doc);
563 else
564 res = E_FAIL;
566 /* Make up the name of the typelib path subkey */
567 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
569 /* Create the typelib path subkey */
570 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
571 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
573 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
574 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
575 res = E_FAIL;
577 RegCloseKey(subKey);
579 else
580 res = E_FAIL;
582 /* Create the flags subkey */
583 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
584 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
586 /* FIXME: is %u correct? */
587 static const WCHAR formatW[] = {'%','u',0};
588 WCHAR buf[20];
589 sprintfW(buf, formatW, attr->wLibFlags);
590 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
591 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
592 res = E_FAIL;
594 RegCloseKey(subKey);
596 else
597 res = E_FAIL;
599 /* create the helpdir subkey */
600 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
601 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
603 BOOL freeHelpDir = FALSE;
604 OLECHAR* pIndexStr;
606 /* if we created a new key, and helpDir was null, set the helpdir
607 to the directory which contains the typelib. However,
608 if we just opened an existing key, we leave the helpdir alone */
609 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
610 szHelpDir = SysAllocString(szFullPath);
611 pIndexStr = strrchrW(szHelpDir, '\\');
612 if (pIndexStr) {
613 *pIndexStr = 0;
615 freeHelpDir = TRUE;
618 /* if we have an szHelpDir, set it! */
619 if (szHelpDir != NULL) {
620 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
621 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
622 res = E_FAIL;
626 /* tidy up */
627 if (freeHelpDir) SysFreeString(szHelpDir);
628 RegCloseKey(subKey);
630 } else {
631 res = E_FAIL;
634 RegCloseKey(key);
636 else
637 res = E_FAIL;
639 /* register OLE Automation-compatible interfaces for this typelib */
640 types = ITypeLib_GetTypeInfoCount(ptlib);
641 for (tidx=0; tidx<types; tidx++) {
642 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
643 LPOLESTR name = NULL;
644 ITypeInfo *tinfo = NULL;
646 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
648 switch (kind) {
649 case TKIND_INTERFACE:
650 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
651 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
652 break;
654 case TKIND_DISPATCH:
655 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
656 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
657 break;
659 default:
660 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
661 break;
664 if (tinfo) {
665 TYPEATTR *tattr = NULL;
666 ITypeInfo_GetTypeAttr(tinfo, &tattr);
668 if (tattr) {
669 TRACE_(typelib)("guid=%s, flags=%04x (",
670 debugstr_guid(&tattr->guid),
671 tattr->wTypeFlags);
673 if (TRACE_ON(typelib)) {
674 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
675 XX(FAPPOBJECT);
676 XX(FCANCREATE);
677 XX(FLICENSED);
678 XX(FPREDECLID);
679 XX(FHIDDEN);
680 XX(FCONTROL);
681 XX(FDUAL);
682 XX(FNONEXTENSIBLE);
683 XX(FOLEAUTOMATION);
684 XX(FRESTRICTED);
685 XX(FAGGREGATABLE);
686 XX(FREPLACEABLE);
687 XX(FDISPATCHABLE);
688 XX(FREVERSEBIND);
689 XX(FPROXY);
690 #undef XX
691 MESSAGE("\n");
694 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
696 /* register interface<->typelib coupling */
697 get_interface_key( &tattr->guid, keyName );
698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
699 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
701 if (name)
702 RegSetValueExW(key, NULL, 0, REG_SZ,
703 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
705 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
706 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
707 RegSetValueExW(subKey, NULL, 0, REG_SZ,
708 (const BYTE *)PSOA, sizeof PSOA);
709 RegCloseKey(subKey);
712 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
713 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
714 RegSetValueExW(subKey, NULL, 0, REG_SZ,
715 (const BYTE *)PSOA, sizeof PSOA);
716 RegCloseKey(subKey);
719 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
720 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
722 WCHAR buffer[40];
723 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
724 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
726 StringFromGUID2(&attr->guid, buffer, 40);
727 RegSetValueExW(subKey, NULL, 0, REG_SZ,
728 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
729 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
730 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
731 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
732 RegCloseKey(subKey);
735 RegCloseKey(key);
739 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
742 ITypeInfo_Release(tinfo);
745 SysFreeString(name);
749 ITypeLib_ReleaseTLibAttr(ptlib, attr);
751 return res;
755 /******************************************************************************
756 * UnRegisterTypeLib [OLEAUT32.186]
757 * Removes information about a type library from the System Registry
758 * NOTES
760 * RETURNS
761 * Success: S_OK
762 * Failure: Status
764 HRESULT WINAPI UnRegisterTypeLib(
765 REFGUID libid, /* [in] Guid of the library */
766 WORD wVerMajor, /* [in] major version */
767 WORD wVerMinor, /* [in] minor version */
768 LCID lcid, /* [in] locale id */
769 SYSKIND syskind)
771 BSTR tlibPath = NULL;
772 DWORD tmpLength;
773 WCHAR keyName[60];
774 WCHAR subKeyName[50];
775 int result = S_OK;
776 DWORD i = 0;
777 BOOL deleteOtherStuff;
778 HKEY key = NULL;
779 HKEY subKey = NULL;
780 TYPEATTR* typeAttr = NULL;
781 TYPEKIND kind;
782 ITypeInfo* typeInfo = NULL;
783 ITypeLib* typeLib = NULL;
784 int numTypes;
786 TRACE("(IID: %s)\n",debugstr_guid(libid));
788 /* Create the path to the key */
789 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
791 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
793 TRACE("Unsupported syskind %i\n", syskind);
794 result = E_INVALIDARG;
795 goto end;
798 /* get the path to the typelib on disk */
799 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
800 result = E_INVALIDARG;
801 goto end;
804 /* Try and open the key to the type library. */
805 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
806 result = E_INVALIDARG;
807 goto end;
810 /* Try and load the type library */
811 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
812 result = TYPE_E_INVALIDSTATE;
813 goto end;
816 /* remove any types registered with this typelib */
817 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
818 for (i=0; i<numTypes; i++) {
819 /* get the kind of type */
820 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
821 goto enddeleteloop;
824 /* skip non-interfaces, and get type info for the type */
825 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
826 goto enddeleteloop;
828 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
829 goto enddeleteloop;
831 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
832 goto enddeleteloop;
835 /* the path to the type */
836 get_interface_key( &typeAttr->guid, subKeyName );
838 /* Delete its bits */
839 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
840 goto enddeleteloop;
842 RegDeleteKeyW(subKey, ProxyStubClsidW);
843 RegDeleteKeyW(subKey, ProxyStubClsid32W);
844 RegDeleteKeyW(subKey, TypeLibW);
845 RegCloseKey(subKey);
846 subKey = NULL;
847 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
849 enddeleteloop:
850 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
851 typeAttr = NULL;
852 if (typeInfo) ITypeInfo_Release(typeInfo);
853 typeInfo = NULL;
856 /* Now, delete the type library path subkey */
857 get_lcid_subkey( lcid, syskind, subKeyName );
858 RegDeleteKeyW(key, subKeyName);
859 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
860 RegDeleteKeyW(key, subKeyName);
862 /* check if there is anything besides the FLAGS/HELPDIR keys.
863 If there is, we don't delete them */
864 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
865 deleteOtherStuff = TRUE;
866 i = 0;
867 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
868 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
870 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
871 if (!strcmpW(subKeyName, FLAGSW)) continue;
872 if (!strcmpW(subKeyName, HELPDIRW)) continue;
873 deleteOtherStuff = FALSE;
874 break;
877 /* only delete the other parts of the key if we're absolutely sure */
878 if (deleteOtherStuff) {
879 RegDeleteKeyW(key, FLAGSW);
880 RegDeleteKeyW(key, HELPDIRW);
881 RegCloseKey(key);
882 key = NULL;
884 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
885 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
886 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
889 end:
890 SysFreeString(tlibPath);
891 if (typeLib) ITypeLib_Release(typeLib);
892 if (subKey) RegCloseKey(subKey);
893 if (key) RegCloseKey(key);
894 return result;
897 /*======================= ITypeLib implementation =======================*/
899 typedef struct tagTLBCustData
901 GUID guid;
902 VARIANT data;
903 struct tagTLBCustData* next;
904 } TLBCustData;
906 /* data structure for import typelibs */
907 typedef struct tagTLBImpLib
909 int offset; /* offset in the file (MSFT)
910 offset in nametable (SLTG)
911 just used to identify library while reading
912 data from file */
913 GUID guid; /* libid */
914 BSTR name; /* name */
916 LCID lcid; /* lcid of imported typelib */
918 WORD wVersionMajor; /* major version number */
919 WORD wVersionMinor; /* minor version number */
921 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
922 NULL if not yet loaded */
923 struct tagTLBImpLib * next;
924 } TLBImpLib;
926 /* internal ITypeLib data */
927 typedef struct tagITypeLibImpl
929 const ITypeLib2Vtbl *lpVtbl;
930 const ITypeCompVtbl *lpVtblTypeComp;
931 LONG ref;
932 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
934 /* strings can be stored in tlb as multibyte strings BUT they are *always*
935 * exported to the application as a UNICODE string.
937 BSTR Name;
938 BSTR DocString;
939 BSTR HelpFile;
940 BSTR HelpStringDll;
941 unsigned long dwHelpContext;
942 int TypeInfoCount; /* nr of typeinfo's in librarry */
943 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
944 int ctCustData; /* number of items in cust data list */
945 TLBCustData * pCustData; /* linked list to cust data */
946 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
947 int ctTypeDesc; /* number of items in type desc array */
948 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
949 library. Only used while reading MSFT
950 typelibs */
951 struct list ref_list; /* list of ref types in this typelib */
952 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
955 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
956 struct tagITypeLibImpl *next, *prev;
957 WCHAR *path;
958 INT index;
959 } ITypeLibImpl;
961 static const ITypeLib2Vtbl tlbvt;
962 static const ITypeCompVtbl tlbtcvt;
964 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
966 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
969 /* ITypeLib methods */
970 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
971 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
973 /*======================= ITypeInfo implementation =======================*/
975 /* data for referenced types */
976 typedef struct tagTLBRefType
978 INT index; /* Type index for internal ref or for external ref
979 it the format is SLTG. -2 indicates to
980 use guid */
982 GUID guid; /* guid of the referenced type */
983 /* if index == TLB_REF_USE_GUID */
985 HREFTYPE reference; /* The href of this ref */
986 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
987 TLB_REF_INTERNAL for internal refs
988 TLB_REF_NOT_FOUND for broken refs */
990 struct list entry;
991 } TLBRefType;
993 #define TLB_REF_USE_GUID -2
995 #define TLB_REF_INTERNAL (void*)-2
996 #define TLB_REF_NOT_FOUND (void*)-1
998 /* internal Parameter data */
999 typedef struct tagTLBParDesc
1001 BSTR Name;
1002 int ctCustData;
1003 TLBCustData * pCustData; /* linked list to cust data */
1004 } TLBParDesc;
1006 /* internal Function data */
1007 typedef struct tagTLBFuncDesc
1009 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1010 BSTR Name; /* the name of this function */
1011 TLBParDesc *pParamDesc; /* array with param names and custom data */
1012 int helpcontext;
1013 int HelpStringContext;
1014 BSTR HelpString;
1015 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
1016 int ctCustData;
1017 TLBCustData * pCustData; /* linked list to cust data; */
1018 struct tagTLBFuncDesc * next;
1019 } TLBFuncDesc;
1021 /* internal Variable data */
1022 typedef struct tagTLBVarDesc
1024 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1025 BSTR Name; /* the name of this variable */
1026 int HelpContext;
1027 int HelpStringContext; /* FIXME: where? */
1028 BSTR HelpString;
1029 int ctCustData;
1030 TLBCustData * pCustData;/* linked list to cust data; */
1031 struct tagTLBVarDesc * next;
1032 } TLBVarDesc;
1034 /* internal implemented interface data */
1035 typedef struct tagTLBImplType
1037 HREFTYPE hRef; /* hRef of interface */
1038 int implflags; /* IMPLFLAG_*s */
1039 int ctCustData;
1040 TLBCustData * pCustData;/* linked list to custom data; */
1041 struct tagTLBImplType *next;
1042 } TLBImplType;
1044 /* internal TypeInfo data */
1045 typedef struct tagITypeInfoImpl
1047 const ITypeInfo2Vtbl *lpVtbl;
1048 const ITypeCompVtbl *lpVtblTypeComp;
1049 LONG ref;
1050 BOOL no_free_data; /* don't free data structures */
1051 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1052 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1053 int index; /* index in this typelib; */
1054 HREFTYPE hreftype; /* hreftype for app object binding */
1055 /* type libs seem to store the doc strings in ascii
1056 * so why should we do it in unicode?
1058 BSTR Name;
1059 BSTR DocString;
1060 BSTR DllName;
1061 unsigned long dwHelpContext;
1062 unsigned long dwHelpStringContext;
1064 /* functions */
1065 TLBFuncDesc * funclist; /* linked list with function descriptions */
1067 /* variables */
1068 TLBVarDesc * varlist; /* linked list with variable descriptions */
1070 /* Implemented Interfaces */
1071 TLBImplType * impltypelist;
1073 int ctCustData;
1074 TLBCustData * pCustData; /* linked list to cust data; */
1075 struct tagITypeInfoImpl * next;
1076 } ITypeInfoImpl;
1078 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1080 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1083 static const ITypeInfo2Vtbl tinfvt;
1084 static const ITypeCompVtbl tcompvt;
1086 static ITypeInfo2 * ITypeInfo_Constructor(void);
1088 typedef struct tagTLBContext
1090 unsigned int oStart; /* start of TLB in file */
1091 unsigned int pos; /* current pos */
1092 unsigned int length; /* total length */
1093 void *mapping; /* memory mapping */
1094 MSFT_SegDir * pTblDir;
1095 ITypeLibImpl* pLibInfo;
1096 } TLBContext;
1099 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1102 debug
1104 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1105 if (pTD->vt & VT_RESERVED)
1106 szVarType += strlen(strcpy(szVarType, "reserved | "));
1107 if (pTD->vt & VT_BYREF)
1108 szVarType += strlen(strcpy(szVarType, "ref to "));
1109 if (pTD->vt & VT_ARRAY)
1110 szVarType += strlen(strcpy(szVarType, "array of "));
1111 if (pTD->vt & VT_VECTOR)
1112 szVarType += strlen(strcpy(szVarType, "vector of "));
1113 switch(pTD->vt & VT_TYPEMASK) {
1114 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1115 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1116 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1117 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1118 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1119 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1120 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1121 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1122 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1123 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1124 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1125 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1126 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1127 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1128 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1129 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1130 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1131 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1132 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1133 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1134 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1135 pTD->u.hreftype); break;
1136 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1137 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1138 case VT_PTR: sprintf(szVarType, "ptr to ");
1139 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1140 break;
1141 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1142 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1143 break;
1144 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1145 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1146 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1147 break;
1149 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1153 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1154 char buf[200];
1155 USHORT flags = edesc->u.paramdesc.wParamFlags;
1156 dump_TypeDesc(&edesc->tdesc,buf);
1157 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1158 MESSAGE("\t\tu.paramdesc.wParamFlags");
1159 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1160 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1161 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1162 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1163 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1164 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1165 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1166 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1167 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1169 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1170 int i;
1171 MESSAGE("memid is %08x\n",funcdesc->memid);
1172 for (i=0;i<funcdesc->cParams;i++) {
1173 MESSAGE("Param %d:\n",i);
1174 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1176 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1177 switch (funcdesc->funckind) {
1178 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1179 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1180 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1181 case FUNC_STATIC: MESSAGE("static");break;
1182 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1183 default: MESSAGE("unknown");break;
1185 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1186 switch (funcdesc->invkind) {
1187 case INVOKE_FUNC: MESSAGE("func");break;
1188 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1189 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1190 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1192 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1193 switch (funcdesc->callconv) {
1194 case CC_CDECL: MESSAGE("cdecl");break;
1195 case CC_PASCAL: MESSAGE("pascal");break;
1196 case CC_STDCALL: MESSAGE("stdcall");break;
1197 case CC_SYSCALL: MESSAGE("syscall");break;
1198 default:break;
1200 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1201 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1202 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1204 MESSAGE("\telemdescFunc (return value type):\n");
1205 dump_ELEMDESC(&funcdesc->elemdescFunc);
1208 static const char * const typekind_desc[] =
1210 "TKIND_ENUM",
1211 "TKIND_RECORD",
1212 "TKIND_MODULE",
1213 "TKIND_INTERFACE",
1214 "TKIND_DISPATCH",
1215 "TKIND_COCLASS",
1216 "TKIND_ALIAS",
1217 "TKIND_UNION",
1218 "TKIND_MAX"
1221 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1223 int i;
1224 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1225 for (i=0;i<pfd->funcdesc.cParams;i++)
1226 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1229 dump_FUNCDESC(&(pfd->funcdesc));
1231 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1232 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1234 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1236 while (pfd)
1238 dump_TLBFuncDescOne(pfd);
1239 pfd = pfd->next;
1242 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1244 while (pvd)
1246 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1247 pvd = pvd->next;
1251 static void dump_TLBImpLib(const TLBImpLib *import)
1253 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1254 debugstr_w(import->name));
1255 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1256 import->wVersionMinor, import->lcid, import->offset);
1259 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1261 TLBRefType *ref;
1263 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1265 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1266 if(ref->index == -1)
1267 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1268 else
1269 TRACE_(typelib)("type no: %d\n", ref->index);
1271 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1273 TRACE_(typelib)("in lib\n");
1274 dump_TLBImpLib(ref->pImpTLInfo);
1279 static void dump_TLBImplType(const TLBImplType * impl)
1281 while (impl) {
1282 TRACE_(typelib)(
1283 "implementing/inheriting interface hRef = %x implflags %x\n",
1284 impl->hRef, impl->implflags);
1285 impl = impl->next;
1289 static void dump_Variant(const VARIANT * pvar)
1291 SYSTEMTIME st;
1293 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1295 if (pvar)
1297 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1298 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1300 TRACE(",%p", V_BYREF(pvar));
1302 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1304 TRACE(",%p", V_ARRAY(pvar));
1306 else switch (V_TYPE(pvar))
1308 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1309 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1310 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1311 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1312 case VT_INT:
1313 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1314 case VT_UINT:
1315 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1316 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1317 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1318 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1319 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1320 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1321 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1322 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1323 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1324 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1325 V_CY(pvar).s.Lo); break;
1326 case VT_DATE:
1327 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1328 TRACE(",<invalid>");
1329 else
1330 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1331 st.wHour, st.wMinute, st.wSecond);
1332 break;
1333 case VT_ERROR:
1334 case VT_VOID:
1335 case VT_USERDEFINED:
1336 case VT_EMPTY:
1337 case VT_NULL: break;
1338 default: TRACE(",?"); break;
1341 TRACE("}\n");
1344 static void dump_DispParms(const DISPPARAMS * pdp)
1346 unsigned int index;
1348 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1350 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1352 TRACE("named args:\n");
1353 for (index = 0; index < pdp->cNamedArgs; index++)
1354 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1357 if (pdp->cArgs && pdp->rgvarg)
1359 TRACE("args:\n");
1360 for (index = 0; index < pdp->cArgs; index++)
1361 dump_Variant( &pdp->rgvarg[index] );
1365 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1367 TRACE("%p ref=%u\n", pty, pty->ref);
1368 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1369 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1370 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1371 TRACE("fct:%u var:%u impl:%u\n",
1372 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1373 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1374 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1375 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1376 if (TRACE_ON(ole))
1377 dump_TLBFuncDesc(pty->funclist);
1378 dump_TLBVarDesc(pty->varlist);
1379 dump_TLBImplType(pty->impltypelist);
1382 static void dump_VARDESC(const VARDESC *v)
1384 MESSAGE("memid %d\n",v->memid);
1385 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1386 MESSAGE("oInst %d\n",v->u.oInst);
1387 dump_ELEMDESC(&(v->elemdescVar));
1388 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1389 MESSAGE("varkind %d\n",v->varkind);
1392 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1394 /* VT_LPWSTR is largest type that */
1395 /* may appear in type description*/
1396 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1397 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1398 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1399 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1400 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1401 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1402 {{0},30},{{0},31}
1405 static void TLB_abort(void)
1407 DebugBreak();
1410 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1411 static void * TLB_Alloc(unsigned size)
1413 void * ret;
1414 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1415 /* FIXME */
1416 ERR("cannot allocate memory\n");
1418 return ret;
1421 static void TLB_Free(void * ptr)
1423 HeapFree(GetProcessHeap(), 0, ptr);
1426 /* returns the size required for a deep copy of a typedesc into a
1427 * flat buffer */
1428 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1430 SIZE_T size = 0;
1432 if (alloc_initial_space)
1433 size += sizeof(TYPEDESC);
1435 switch (tdesc->vt)
1437 case VT_PTR:
1438 case VT_SAFEARRAY:
1439 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1440 break;
1441 case VT_CARRAY:
1442 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1443 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1444 break;
1446 return size;
1449 /* deep copy a typedesc into a flat buffer */
1450 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1452 if (!dest)
1454 dest = buffer;
1455 buffer = (char *)buffer + sizeof(TYPEDESC);
1458 *dest = *src;
1460 switch (src->vt)
1462 case VT_PTR:
1463 case VT_SAFEARRAY:
1464 dest->u.lptdesc = buffer;
1465 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1466 break;
1467 case VT_CARRAY:
1468 dest->u.lpadesc = buffer;
1469 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1470 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1471 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1472 break;
1474 return buffer;
1477 /* free custom data allocated by MSFT_CustData */
1478 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1480 TLBCustData *pCustDataNext;
1481 for (; pCustData; pCustData = pCustDataNext)
1483 VariantClear(&pCustData->data);
1485 pCustDataNext = pCustData->next;
1486 TLB_Free(pCustData);
1490 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1492 DWORD len;
1493 BSTR ret;
1495 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1496 ret = SysAllocStringLen(NULL, len - 1);
1497 if (!ret) return ret;
1498 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1499 return ret;
1502 /**********************************************************************
1504 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1506 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1508 return pcx->pos;
1511 static inline void MSFT_Seek(TLBContext *pcx, long where)
1513 if (where != DO_NOT_SEEK)
1515 where += pcx->oStart;
1516 if (where > pcx->length)
1518 /* FIXME */
1519 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1520 TLB_abort();
1522 pcx->pos = where;
1526 /* read function */
1527 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1529 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1530 pcx->pos, count, pcx->oStart, pcx->length, where);
1532 MSFT_Seek(pcx, where);
1533 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1534 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1535 pcx->pos += count;
1536 return count;
1539 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1540 long where )
1542 DWORD ret;
1544 ret = MSFT_Read(buffer, count, pcx, where);
1545 FromLEDWords(buffer, ret);
1547 return ret;
1550 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1551 long where )
1553 DWORD ret;
1555 ret = MSFT_Read(buffer, count, pcx, where);
1556 FromLEWords(buffer, ret);
1558 return ret;
1561 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1563 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1564 memset(pGuid,0, sizeof(GUID));
1565 return;
1567 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1568 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1569 pGuid->Data2 = FromLEWord(pGuid->Data2);
1570 pGuid->Data3 = FromLEWord(pGuid->Data3);
1571 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1574 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1576 MSFT_NameIntro niName;
1578 if (offset < 0)
1580 ERR_(typelib)("bad offset %d\n", offset);
1581 return -1;
1584 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1585 pcx->pTblDir->pNametab.offset+offset);
1587 return niName.hreftype;
1590 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1592 char * name;
1593 MSFT_NameIntro niName;
1594 int lengthInChars;
1595 BSTR bstrName = NULL;
1597 if (offset < 0)
1599 ERR_(typelib)("bad offset %d\n", offset);
1600 return NULL;
1602 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1603 pcx->pTblDir->pNametab.offset+offset);
1604 niName.namelen &= 0xFF; /* FIXME: correct ? */
1605 name=TLB_Alloc((niName.namelen & 0xff) +1);
1606 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1607 name[niName.namelen & 0xff]='\0';
1609 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1610 name, -1, NULL, 0);
1612 /* no invalid characters in string */
1613 if (lengthInChars)
1615 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1617 /* don't check for invalid character since this has been done previously */
1618 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1620 TLB_Free(name);
1622 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1623 return bstrName;
1626 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1628 char * string;
1629 INT16 length;
1630 int lengthInChars;
1631 BSTR bstr = NULL;
1633 if(offset<0) return NULL;
1634 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1635 if(length <= 0) return 0;
1636 string=TLB_Alloc(length +1);
1637 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1638 string[length]='\0';
1640 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1641 string, -1, NULL, 0);
1643 /* no invalid characters in string */
1644 if (lengthInChars)
1646 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1648 /* don't check for invalid character since this has been done previously */
1649 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1651 TLB_Free(string);
1653 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1654 return bstr;
1657 * read a value and fill a VARIANT structure
1659 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1661 int size;
1663 TRACE_(typelib)("\n");
1665 if(offset <0) { /* data are packed in here */
1666 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1667 V_I4(pVar) = offset & 0x3ffffff;
1668 return;
1670 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1671 pcx->pTblDir->pCustData.offset + offset );
1672 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1673 switch (V_VT(pVar)){
1674 case VT_EMPTY: /* FIXME: is this right? */
1675 case VT_NULL: /* FIXME: is this right? */
1676 case VT_I2 : /* this should not happen */
1677 case VT_I4 :
1678 case VT_R4 :
1679 case VT_ERROR :
1680 case VT_BOOL :
1681 case VT_I1 :
1682 case VT_UI1 :
1683 case VT_UI2 :
1684 case VT_UI4 :
1685 case VT_INT :
1686 case VT_UINT :
1687 case VT_VOID : /* FIXME: is this right? */
1688 case VT_HRESULT :
1689 size=4; break;
1690 case VT_R8 :
1691 case VT_CY :
1692 case VT_DATE :
1693 case VT_I8 :
1694 case VT_UI8 :
1695 case VT_DECIMAL : /* FIXME: is this right? */
1696 case VT_FILETIME :
1697 size=8;break;
1698 /* pointer types with known behaviour */
1699 case VT_BSTR :{
1700 char * ptr;
1701 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1702 if(size < 0) {
1703 char next;
1704 DWORD origPos = MSFT_Tell(pcx), nullPos;
1706 do {
1707 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1708 } while (next);
1709 nullPos = MSFT_Tell(pcx);
1710 size = nullPos - origPos;
1711 MSFT_Seek(pcx, origPos);
1713 ptr=TLB_Alloc(size);/* allocate temp buffer */
1714 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1715 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1716 /* FIXME: do we need a AtoW conversion here? */
1717 V_UNION(pVar, bstrVal[size])='\0';
1718 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1719 TLB_Free(ptr);
1721 size=-4; break;
1722 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1723 case VT_DISPATCH :
1724 case VT_VARIANT :
1725 case VT_UNKNOWN :
1726 case VT_PTR :
1727 case VT_SAFEARRAY :
1728 case VT_CARRAY :
1729 case VT_USERDEFINED :
1730 case VT_LPSTR :
1731 case VT_LPWSTR :
1732 case VT_BLOB :
1733 case VT_STREAM :
1734 case VT_STORAGE :
1735 case VT_STREAMED_OBJECT :
1736 case VT_STORED_OBJECT :
1737 case VT_BLOB_OBJECT :
1738 case VT_CF :
1739 case VT_CLSID :
1740 default:
1741 size=0;
1742 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1743 V_VT(pVar));
1746 if(size>0) /* (big|small) endian correct? */
1747 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1748 return;
1751 * create a linked list with custom data
1753 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1755 MSFT_CDGuid entry;
1756 TLBCustData* pNew;
1757 int count=0;
1759 TRACE_(typelib)("\n");
1761 while(offset >=0){
1762 count++;
1763 pNew=TLB_Alloc(sizeof(TLBCustData));
1764 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1765 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1766 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1767 /* add new custom data at head of the list */
1768 pNew->next=*ppCustData;
1769 *ppCustData=pNew;
1770 offset = entry.next;
1772 return count;
1775 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1776 ITypeInfoImpl *pTI)
1778 if(type <0)
1779 pTd->vt=type & VT_TYPEMASK;
1780 else
1781 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1783 if(pTd->vt == VT_USERDEFINED)
1784 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1786 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1789 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1791 /* resolve referenced type if any */
1792 while (lpTypeDesc)
1794 switch (lpTypeDesc->vt)
1796 case VT_PTR:
1797 lpTypeDesc = lpTypeDesc->u.lptdesc;
1798 break;
1800 case VT_CARRAY:
1801 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1802 break;
1804 case VT_USERDEFINED:
1805 MSFT_DoRefType(pcx, pTI->pTypeLib,
1806 lpTypeDesc->u.hreftype);
1808 lpTypeDesc = NULL;
1809 break;
1811 default:
1812 lpTypeDesc = NULL;
1817 static void
1818 MSFT_DoFuncs(TLBContext* pcx,
1819 ITypeInfoImpl* pTI,
1820 int cFuncs,
1821 int cVars,
1822 int offset,
1823 TLBFuncDesc** pptfd)
1826 * member information is stored in a data structure at offset
1827 * indicated by the memoffset field of the typeinfo structure
1828 * There are several distinctive parts.
1829 * The first part starts with a field that holds the total length
1830 * of this (first) part excluding this field. Then follow the records,
1831 * for each member there is one record.
1833 * The first entry is always the length of the record (including this
1834 * length word).
1835 * The rest of the record depends on the type of the member. If there is
1836 * a field indicating the member type (function, variable, interface, etc)
1837 * I have not found it yet. At this time we depend on the information
1838 * in the type info and the usual order how things are stored.
1840 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1841 * for each member;
1843 * Third is an equal sized array with file offsets to the name entry
1844 * of each member.
1846 * The fourth and last (?) part is an array with offsets to the records
1847 * in the first part of this file segment.
1850 int infolen, nameoffset, reclength, nrattributes, i;
1851 int recoffset = offset + sizeof(INT);
1853 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1854 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1855 TLBFuncDesc *ptfd_prev = NULL;
1857 TRACE_(typelib)("\n");
1859 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1861 for ( i = 0; i < cFuncs ; i++ )
1863 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1865 /* name, eventually add to a hash table */
1866 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1867 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1869 /* nameoffset is sometimes -1 on the second half of a propget/propput
1870 * pair of functions */
1871 if ((nameoffset == -1) && (i > 0))
1872 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1873 else
1874 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1876 /* read the function information record */
1877 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1879 reclength &= 0xffff;
1881 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1883 /* do the attributes */
1884 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1885 / sizeof(int);
1887 if ( nrattributes > 0 )
1889 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1891 if ( nrattributes > 1 )
1893 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1894 pFuncRec->OptAttr[1]) ;
1896 if ( nrattributes > 2 )
1898 if ( pFuncRec->FKCCIC & 0x2000 )
1900 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1901 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1902 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1904 else
1906 (*pptfd)->Entry = MSFT_ReadString(pcx,
1907 pFuncRec->OptAttr[2]);
1909 if( nrattributes > 5 )
1911 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1913 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1915 MSFT_CustData(pcx,
1916 pFuncRec->OptAttr[6],
1917 &(*pptfd)->pCustData);
1921 else
1923 (*pptfd)->Entry = (BSTR)-1;
1928 /* fill the FuncDesc Structure */
1929 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1930 offset + infolen + ( i + 1) * sizeof(INT));
1932 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1933 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1934 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1935 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1936 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1937 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1938 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1940 MSFT_GetTdesc(pcx,
1941 pFuncRec->DataType,
1942 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1943 pTI);
1944 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1946 /* do the parameters/arguments */
1947 if(pFuncRec->nrargs)
1949 int j = 0;
1950 MSFT_ParameterInfo paraminfo;
1952 (*pptfd)->funcdesc.lprgelemdescParam =
1953 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1955 (*pptfd)->pParamDesc =
1956 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1958 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1959 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1961 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1963 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1965 MSFT_GetTdesc(pcx,
1966 paraminfo.DataType,
1967 &elemdesc->tdesc,
1968 pTI);
1970 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1972 /* name */
1973 if (paraminfo.oName == -1)
1974 /* this occurs for [propput] or [propget] methods, so
1975 * we should just set the name of the parameter to the
1976 * name of the method. */
1977 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1978 else
1979 (*pptfd)->pParamDesc[j].Name =
1980 MSFT_ReadName( pcx, paraminfo.oName );
1981 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1983 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1985 /* default value */
1986 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1987 (pFuncRec->FKCCIC & 0x1000) )
1989 INT* pInt = (INT *)((char *)pFuncRec +
1990 reclength -
1991 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1993 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1995 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1996 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1998 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1999 pInt[j], pcx);
2001 else
2002 elemdesc->u.paramdesc.pparamdescex = NULL;
2003 /* custom info */
2004 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2006 MSFT_CustData(pcx,
2007 pFuncRec->OptAttr[7+j],
2008 &(*pptfd)->pParamDesc[j].pCustData);
2011 /* SEEK value = jump to offset,
2012 * from there jump to the end of record,
2013 * go back by (j-1) arguments
2015 MSFT_ReadLEDWords( &paraminfo ,
2016 sizeof(MSFT_ParameterInfo), pcx,
2017 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2018 * sizeof(MSFT_ParameterInfo)));
2022 /* scode is not used: archaic win16 stuff FIXME: right? */
2023 (*pptfd)->funcdesc.cScodes = 0 ;
2024 (*pptfd)->funcdesc.lprgscode = NULL ;
2026 ptfd_prev = *pptfd;
2027 pptfd = & ((*pptfd)->next);
2028 recoffset += reclength;
2030 HeapFree(GetProcessHeap(), 0, recbuf);
2033 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2034 int cVars, int offset, TLBVarDesc ** pptvd)
2036 int infolen, nameoffset, reclength;
2037 char recbuf[256];
2038 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2039 int i;
2040 int recoffset;
2042 TRACE_(typelib)("\n");
2044 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2045 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2046 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2047 recoffset += offset+sizeof(INT);
2048 for(i=0;i<cVars;i++){
2049 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2050 /* name, eventually add to a hash table */
2051 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2052 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2053 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2054 /* read the variable information record */
2055 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2056 reclength &=0xff;
2057 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2058 /* Optional data */
2059 if(reclength >(6*sizeof(INT)) )
2060 (*pptvd)->HelpContext=pVarRec->HelpContext;
2061 if(reclength >(7*sizeof(INT)) )
2062 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2063 if(reclength >(8*sizeof(INT)) )
2064 if(reclength >(9*sizeof(INT)) )
2065 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2066 /* fill the VarDesc Structure */
2067 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2068 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2069 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2070 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2071 MSFT_GetTdesc(pcx, pVarRec->DataType,
2072 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2073 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2074 if(pVarRec->VarKind == VAR_CONST ){
2075 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2076 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2077 pVarRec->OffsValue, pcx);
2078 } else
2079 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2080 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2081 pptvd=&((*pptvd)->next);
2082 recoffset += reclength;
2085 /* fill in data for a hreftype (offset). When the referenced type is contained
2086 * in the typelib, it's just an (file) offset in the type info base dir.
2087 * If comes from import, it's an offset+1 in the ImpInfo table
2088 * */
2089 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2090 int offset)
2092 TLBRefType *ref;
2094 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2096 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2098 if(ref->reference == offset) return;
2101 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2102 list_add_tail(&pTL->ref_list, &ref->entry);
2104 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2105 /* external typelib */
2106 MSFT_ImpInfo impinfo;
2107 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2109 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2111 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2112 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2113 while (pImpLib){ /* search the known offsets of all import libraries */
2114 if(pImpLib->offset==impinfo.oImpFile) break;
2115 pImpLib=pImpLib->next;
2117 if(pImpLib){
2118 ref->reference = offset;
2119 ref->pImpTLInfo = pImpLib;
2120 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2121 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2122 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2123 ref->index = TLB_REF_USE_GUID;
2124 } else
2125 ref->index = impinfo.oGuid;
2126 }else{
2127 ERR("Cannot find a reference\n");
2128 ref->reference = -1;
2129 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2131 }else{
2132 /* in this typelib */
2133 ref->index = MSFT_HREFTYPE_INDEX(offset);
2134 ref->reference = offset;
2135 ref->pImpTLInfo = TLB_REF_INTERNAL;
2139 /* process Implemented Interfaces of a com class */
2140 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2141 int offset)
2143 int i;
2144 MSFT_RefRecord refrec;
2145 TLBImplType **ppImpl = &pTI->impltypelist;
2147 TRACE_(typelib)("\n");
2149 for(i=0;i<count;i++){
2150 if(offset<0) break; /* paranoia */
2151 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2152 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2153 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2154 (*ppImpl)->hRef = refrec.reftype;
2155 (*ppImpl)->implflags=refrec.flags;
2156 (*ppImpl)->ctCustData=
2157 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2158 offset=refrec.onext;
2159 ppImpl=&((*ppImpl)->next);
2163 * process a typeinfo record
2165 static ITypeInfoImpl * MSFT_DoTypeInfo(
2166 TLBContext *pcx,
2167 int count,
2168 ITypeLibImpl * pLibInfo)
2170 MSFT_TypeInfoBase tiBase;
2171 ITypeInfoImpl *ptiRet;
2173 TRACE_(typelib)("count=%u\n", count);
2175 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2176 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2177 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2179 /* this is where we are coming from */
2180 ptiRet->pTypeLib = pLibInfo;
2181 ptiRet->index=count;
2182 /* fill in the typeattr fields */
2184 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2185 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2186 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2187 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2188 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2189 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2190 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2191 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2192 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2193 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2194 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2195 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2196 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2197 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2198 MSFT_GetTdesc(pcx, tiBase.datatype1,
2199 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2201 /* FIXME: */
2202 /* IDLDESC idldescType; *//* never saw this one != zero */
2204 /* name, eventually add to a hash table */
2205 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2206 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2207 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2208 /* help info */
2209 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2210 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2211 ptiRet->dwHelpContext=tiBase.helpcontext;
2213 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2214 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2216 /* note: InfoType's Help file and HelpStringDll come from the containing
2217 * library. Further HelpString and Docstring appear to be the same thing :(
2219 /* functions */
2220 if(ptiRet->TypeAttr.cFuncs >0 )
2221 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2222 ptiRet->TypeAttr.cVars,
2223 tiBase.memoffset, & ptiRet->funclist);
2224 /* variables */
2225 if(ptiRet->TypeAttr.cVars >0 )
2226 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2227 ptiRet->TypeAttr.cVars,
2228 tiBase.memoffset, & ptiRet->varlist);
2229 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2230 switch(ptiRet->TypeAttr.typekind)
2232 case TKIND_COCLASS:
2233 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2234 tiBase.datatype1);
2235 break;
2236 case TKIND_DISPATCH:
2237 /* This is not -1 when the interface is a non-base dual interface or
2238 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2239 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2240 not this interface.
2243 if (tiBase.datatype1 != -1)
2245 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2246 ptiRet->impltypelist->hRef = tiBase.datatype1;
2247 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2249 break;
2250 default:
2251 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2252 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2253 ptiRet->impltypelist->hRef = tiBase.datatype1;
2254 break;
2257 ptiRet->ctCustData=
2258 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2260 TRACE_(typelib)("%s guid: %s kind:%s\n",
2261 debugstr_w(ptiRet->Name),
2262 debugstr_guid(&ptiRet->TypeAttr.guid),
2263 typekind_desc[ptiRet->TypeAttr.typekind]);
2264 if (TRACE_ON(typelib))
2265 dump_TypeInfo(ptiRet);
2267 return ptiRet;
2270 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2271 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2272 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2273 * tradeoff here.
2275 static ITypeLibImpl *tlb_cache_first;
2276 static CRITICAL_SECTION cache_section;
2277 static CRITICAL_SECTION_DEBUG cache_section_debug =
2279 0, 0, &cache_section,
2280 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2281 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2283 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2286 typedef struct TLB_PEFile
2288 const IUnknownVtbl *lpvtbl;
2289 LONG refs;
2290 HMODULE dll;
2291 HRSRC typelib_resource;
2292 HGLOBAL typelib_global;
2293 LPVOID typelib_base;
2294 } TLB_PEFile;
2296 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2298 if (IsEqualIID(riid, &IID_IUnknown))
2300 *ppv = iface;
2301 IUnknown_AddRef(iface);
2302 return S_OK;
2304 *ppv = NULL;
2305 return E_NOINTERFACE;
2308 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2310 TLB_PEFile *This = (TLB_PEFile *)iface;
2311 return InterlockedIncrement(&This->refs);
2314 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2316 TLB_PEFile *This = (TLB_PEFile *)iface;
2317 ULONG refs = InterlockedDecrement(&This->refs);
2318 if (!refs)
2320 if (This->typelib_global)
2321 FreeResource(This->typelib_global);
2322 if (This->dll)
2323 FreeLibrary(This->dll);
2324 HeapFree(GetProcessHeap(), 0, This);
2326 return refs;
2329 static const IUnknownVtbl TLB_PEFile_Vtable =
2331 TLB_PEFile_QueryInterface,
2332 TLB_PEFile_AddRef,
2333 TLB_PEFile_Release
2336 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2338 TLB_PEFile *This;
2340 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2341 if (!This)
2342 return E_OUTOFMEMORY;
2344 This->lpvtbl = &TLB_PEFile_Vtable;
2345 This->refs = 1;
2346 This->dll = NULL;
2347 This->typelib_resource = NULL;
2348 This->typelib_global = NULL;
2349 This->typelib_base = NULL;
2351 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2352 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2354 if (This->dll)
2356 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2357 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2358 if (This->typelib_resource)
2360 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2361 if (This->typelib_global)
2363 This->typelib_base = LockResource(This->typelib_global);
2365 if (This->typelib_base)
2367 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2368 *ppBase = This->typelib_base;
2369 *ppFile = (IUnknown *)&This->lpvtbl;
2370 return S_OK;
2376 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2377 return TYPE_E_CANTLOADLIBRARY;
2380 typedef struct TLB_NEFile
2382 const IUnknownVtbl *lpvtbl;
2383 LONG refs;
2384 LPVOID typelib_base;
2385 } TLB_NEFile;
2387 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2389 if (IsEqualIID(riid, &IID_IUnknown))
2391 *ppv = iface;
2392 IUnknown_AddRef(iface);
2393 return S_OK;
2395 *ppv = NULL;
2396 return E_NOINTERFACE;
2399 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2401 TLB_NEFile *This = (TLB_NEFile *)iface;
2402 return InterlockedIncrement(&This->refs);
2405 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2407 TLB_NEFile *This = (TLB_NEFile *)iface;
2408 ULONG refs = InterlockedDecrement(&This->refs);
2409 if (!refs)
2411 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2412 HeapFree(GetProcessHeap(), 0, This);
2414 return refs;
2417 static const IUnknownVtbl TLB_NEFile_Vtable =
2419 TLB_NEFile_QueryInterface,
2420 TLB_NEFile_AddRef,
2421 TLB_NEFile_Release
2424 /***********************************************************************
2425 * read_xx_header [internal]
2427 static int read_xx_header( HFILE lzfd )
2429 IMAGE_DOS_HEADER mzh;
2430 char magic[3];
2432 LZSeek( lzfd, 0, SEEK_SET );
2433 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2434 return 0;
2435 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2436 return 0;
2438 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2439 if ( 2 != LZRead( lzfd, magic, 2 ) )
2440 return 0;
2442 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2444 if ( magic[0] == 'N' && magic[1] == 'E' )
2445 return IMAGE_OS2_SIGNATURE;
2446 if ( magic[0] == 'P' && magic[1] == 'E' )
2447 return IMAGE_NT_SIGNATURE;
2449 magic[2] = '\0';
2450 WARN("Can't handle %s files.\n", magic );
2451 return 0;
2455 /***********************************************************************
2456 * find_ne_resource [internal]
2458 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2459 DWORD *resLen, DWORD *resOff )
2461 IMAGE_OS2_HEADER nehd;
2462 NE_TYPEINFO *typeInfo;
2463 NE_NAMEINFO *nameInfo;
2464 DWORD nehdoffset;
2465 LPBYTE resTab;
2466 DWORD resTabSize;
2467 int count;
2469 /* Read in NE header */
2470 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2471 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2473 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2474 if ( !resTabSize )
2476 TRACE("No resources in NE dll\n" );
2477 return FALSE;
2480 /* Read in resource table */
2481 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2482 if ( !resTab ) return FALSE;
2484 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2485 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2487 HeapFree( GetProcessHeap(), 0, resTab );
2488 return FALSE;
2491 /* Find resource */
2492 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2494 if (HIWORD(typeid) != 0) /* named type */
2496 BYTE len = strlen( typeid );
2497 while (typeInfo->type_id)
2499 if (!(typeInfo->type_id & 0x8000))
2501 BYTE *p = resTab + typeInfo->type_id;
2502 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2504 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2505 typeInfo->count * sizeof(NE_NAMEINFO));
2508 else /* numeric type id */
2510 WORD id = LOWORD(typeid) | 0x8000;
2511 while (typeInfo->type_id)
2513 if (typeInfo->type_id == id) goto found_type;
2514 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2515 typeInfo->count * sizeof(NE_NAMEINFO));
2518 TRACE("No typeid entry found for %p\n", typeid );
2519 HeapFree( GetProcessHeap(), 0, resTab );
2520 return FALSE;
2522 found_type:
2523 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2525 if (HIWORD(resid) != 0) /* named resource */
2527 BYTE len = strlen( resid );
2528 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2530 BYTE *p = resTab + nameInfo->id;
2531 if (nameInfo->id & 0x8000) continue;
2532 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2535 else /* numeric resource id */
2537 WORD id = LOWORD(resid) | 0x8000;
2538 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2539 if (nameInfo->id == id) goto found_name;
2541 TRACE("No resid entry found for %p\n", typeid );
2542 HeapFree( GetProcessHeap(), 0, resTab );
2543 return FALSE;
2545 found_name:
2546 /* Return resource data */
2547 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2548 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2550 HeapFree( GetProcessHeap(), 0, resTab );
2551 return TRUE;
2554 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2556 HFILE lzfd = -1;
2557 OFSTRUCT ofs;
2558 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2559 TLB_NEFile *This = NULL;
2561 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2562 if (!This) return E_OUTOFMEMORY;
2564 This->lpvtbl = &TLB_NEFile_Vtable;
2565 This->refs = 1;
2566 This->typelib_base = NULL;
2568 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2569 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2571 DWORD reslen, offset;
2572 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2574 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2575 if( !This->typelib_base )
2576 hr = E_OUTOFMEMORY;
2577 else
2579 LZSeek( lzfd, offset, SEEK_SET );
2580 reslen = LZRead( lzfd, This->typelib_base, reslen );
2581 LZClose( lzfd );
2582 *ppBase = This->typelib_base;
2583 *pdwTLBLength = reslen;
2584 *ppFile = (IUnknown *)&This->lpvtbl;
2585 return S_OK;
2590 if( lzfd >= 0) LZClose( lzfd );
2591 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2592 return hr;
2595 typedef struct TLB_Mapping
2597 const IUnknownVtbl *lpvtbl;
2598 LONG refs;
2599 HANDLE file;
2600 HANDLE mapping;
2601 LPVOID typelib_base;
2602 } TLB_Mapping;
2604 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2606 if (IsEqualIID(riid, &IID_IUnknown))
2608 *ppv = iface;
2609 IUnknown_AddRef(iface);
2610 return S_OK;
2612 *ppv = NULL;
2613 return E_NOINTERFACE;
2616 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2618 TLB_Mapping *This = (TLB_Mapping *)iface;
2619 return InterlockedIncrement(&This->refs);
2622 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2624 TLB_Mapping *This = (TLB_Mapping *)iface;
2625 ULONG refs = InterlockedDecrement(&This->refs);
2626 if (!refs)
2628 if (This->typelib_base)
2629 UnmapViewOfFile(This->typelib_base);
2630 if (This->mapping)
2631 CloseHandle(This->mapping);
2632 if (This->file != INVALID_HANDLE_VALUE)
2633 CloseHandle(This->file);
2634 HeapFree(GetProcessHeap(), 0, This);
2636 return refs;
2639 static const IUnknownVtbl TLB_Mapping_Vtable =
2641 TLB_Mapping_QueryInterface,
2642 TLB_Mapping_AddRef,
2643 TLB_Mapping_Release
2646 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2648 TLB_Mapping *This;
2650 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2651 if (!This)
2652 return E_OUTOFMEMORY;
2654 This->lpvtbl = &TLB_Mapping_Vtable;
2655 This->refs = 1;
2656 This->file = INVALID_HANDLE_VALUE;
2657 This->mapping = NULL;
2658 This->typelib_base = NULL;
2660 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2661 if (INVALID_HANDLE_VALUE != This->file)
2663 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2664 if (This->mapping)
2666 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2667 if(This->typelib_base)
2669 /* retrieve file size */
2670 *pdwTLBLength = GetFileSize(This->file, NULL);
2671 *ppBase = This->typelib_base;
2672 *ppFile = (IUnknown *)&This->lpvtbl;
2673 return S_OK;
2678 IUnknown_Release((IUnknown *)&This->lpvtbl);
2679 return TYPE_E_CANTLOADLIBRARY;
2682 /****************************************************************************
2683 * TLB_ReadTypeLib
2685 * find the type of the typelib file and map the typelib resource into
2686 * the memory
2688 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2689 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2690 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2692 ITypeLibImpl *entry;
2693 HRESULT ret;
2694 INT index = 1;
2695 LPWSTR index_str, file = (LPWSTR)pszFileName;
2696 LPVOID pBase = NULL;
2697 DWORD dwTLBLength = 0;
2698 IUnknown *pFile = NULL;
2700 *ppTypeLib = NULL;
2702 index_str = strrchrW(pszFileName, '\\');
2703 if(index_str && *++index_str != '\0')
2705 LPWSTR end_ptr;
2706 long idx = strtolW(index_str, &end_ptr, 10);
2707 if(*end_ptr == '\0')
2709 int str_len = index_str - pszFileName - 1;
2710 index = idx;
2711 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2712 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2713 file[str_len] = 0;
2717 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2719 if(strchrW(file, '\\'))
2721 lstrcpyW(pszPath, file);
2723 else
2725 int len = GetSystemDirectoryW(pszPath, cchPath);
2726 pszPath[len] = '\\';
2727 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2731 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2733 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2735 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2736 EnterCriticalSection(&cache_section);
2737 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2739 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2741 TRACE("cache hit\n");
2742 *ppTypeLib = (ITypeLib2*)entry;
2743 ITypeLib_AddRef(*ppTypeLib);
2744 LeaveCriticalSection(&cache_section);
2745 return S_OK;
2748 LeaveCriticalSection(&cache_section);
2750 /* now actually load and parse the typelib */
2752 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2753 if (ret == TYPE_E_CANTLOADLIBRARY)
2754 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2755 if (ret == TYPE_E_CANTLOADLIBRARY)
2756 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2757 if (SUCCEEDED(ret))
2759 if (dwTLBLength >= 4)
2761 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2762 if (dwSignature == MSFT_SIGNATURE)
2763 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2764 else if (dwSignature == SLTG_SIGNATURE)
2765 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2766 else
2768 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2769 ret = TYPE_E_CANTLOADLIBRARY;
2772 else
2773 ret = TYPE_E_CANTLOADLIBRARY;
2774 IUnknown_Release(pFile);
2777 if(*ppTypeLib) {
2778 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2780 TRACE("adding to cache\n");
2781 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2782 lstrcpyW(impl->path, pszPath);
2783 /* We should really canonicalise the path here. */
2784 impl->index = index;
2786 /* FIXME: check if it has added already in the meantime */
2787 EnterCriticalSection(&cache_section);
2788 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2789 impl->prev = NULL;
2790 tlb_cache_first = impl;
2791 LeaveCriticalSection(&cache_section);
2792 ret = S_OK;
2793 } else
2794 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2796 return ret;
2799 /*================== ITypeLib(2) Methods ===================================*/
2801 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2803 ITypeLibImpl* pTypeLibImpl;
2805 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2806 if (!pTypeLibImpl) return NULL;
2808 pTypeLibImpl->lpVtbl = &tlbvt;
2809 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2810 pTypeLibImpl->ref = 1;
2812 list_init(&pTypeLibImpl->ref_list);
2813 pTypeLibImpl->dispatch_href = -1;
2815 return pTypeLibImpl;
2818 /****************************************************************************
2819 * ITypeLib2_Constructor_MSFT
2821 * loading an MSFT typelib from an in-memory image
2823 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2825 TLBContext cx;
2826 long lPSegDir;
2827 MSFT_Header tlbHeader;
2828 MSFT_SegDir tlbSegDir;
2829 ITypeLibImpl * pTypeLibImpl;
2831 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2833 pTypeLibImpl = TypeLibImpl_Constructor();
2834 if (!pTypeLibImpl) return NULL;
2836 /* get pointer to beginning of typelib data */
2837 cx.pos = 0;
2838 cx.oStart=0;
2839 cx.mapping = pLib;
2840 cx.pLibInfo = pTypeLibImpl;
2841 cx.length = dwTLBLength;
2843 /* read header */
2844 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2845 TRACE_(typelib)("header:\n");
2846 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2847 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2848 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2849 return NULL;
2851 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2853 /* there is a small amount of information here until the next important
2854 * part:
2855 * the segment directory . Try to calculate the amount of data */
2856 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2858 /* now read the segment directory */
2859 TRACE("read segment directory (at %ld)\n",lPSegDir);
2860 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2861 cx.pTblDir = &tlbSegDir;
2863 /* just check two entries */
2864 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2866 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2867 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2868 return NULL;
2871 /* now fill our internal data */
2872 /* TLIBATTR fields */
2873 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2875 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2876 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2877 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2878 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2879 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2881 /* name, eventually add to a hash table */
2882 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2884 /* help info */
2885 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2886 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2888 if( tlbHeader.varflags & HELPDLLFLAG)
2890 int offset;
2891 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2892 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2895 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2897 /* custom data */
2898 if(tlbHeader.CustomDataOffset >= 0)
2900 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2903 /* fill in type descriptions */
2904 if(tlbSegDir.pTypdescTab.length > 0)
2906 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2907 INT16 td[4];
2908 pTypeLibImpl->ctTypeDesc = cTD;
2909 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2910 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2911 for(i=0; i<cTD; )
2913 /* FIXME: add several sanity checks here */
2914 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2915 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2917 /* FIXME: check safearray */
2918 if(td[3] < 0)
2919 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2920 else
2921 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2923 else if(td[0] == VT_CARRAY)
2925 /* array descr table here */
2926 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2928 else if(td[0] == VT_USERDEFINED)
2930 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2932 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2935 /* second time around to fill the array subscript info */
2936 for(i=0;i<cTD;i++)
2938 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2939 if(tlbSegDir.pArrayDescriptions.offset>0)
2941 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2942 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2944 if(td[1]<0)
2945 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2946 else
2947 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2949 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2951 for(j = 0; j<td[2]; j++)
2953 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2954 sizeof(INT), &cx, DO_NOT_SEEK);
2955 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2956 sizeof(INT), &cx, DO_NOT_SEEK);
2959 else
2961 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2962 ERR("didn't find array description data\n");
2967 /* imported type libs */
2968 if(tlbSegDir.pImpFiles.offset>0)
2970 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2971 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2972 UINT16 size;
2974 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2976 char *name;
2978 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2979 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2980 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2982 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2983 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2984 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2985 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2987 size >>= 2;
2988 name = TLB_Alloc(size+1);
2989 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2990 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2992 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2993 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2995 ppImpLib = &(*ppImpLib)->next;
2999 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3000 if(pTypeLibImpl->dispatch_href != -1)
3001 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3003 /* type info's */
3004 if(tlbHeader.nrtypeinfos >= 0 )
3006 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3007 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3008 int i;
3010 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3012 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3014 ppTI = &((*ppTI)->next);
3015 (pTypeLibImpl->TypeInfoCount)++;
3019 TRACE("(%p)\n", pTypeLibImpl);
3020 return (ITypeLib2*) pTypeLibImpl;
3024 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3026 char b[3];
3027 int i;
3028 short s;
3030 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3031 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3032 return FALSE;
3035 guid->Data4[0] = s >> 8;
3036 guid->Data4[1] = s & 0xff;
3038 b[2] = '\0';
3039 for(i = 0; i < 6; i++) {
3040 memcpy(b, str + 24 + 2 * i, 2);
3041 guid->Data4[i + 2] = strtol(b, NULL, 16);
3043 return TRUE;
3046 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3048 WORD bytelen;
3049 DWORD len;
3051 *pBstr = NULL;
3052 bytelen = *(const WORD*)ptr;
3053 if(bytelen == 0xffff) return 2;
3054 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3055 *pBstr = SysAllocStringLen(NULL, len - 1);
3056 if (*pBstr)
3057 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3058 return bytelen + 2;
3061 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3063 WORD bytelen;
3065 *str = NULL;
3066 bytelen = *(const WORD*)ptr;
3067 if(bytelen == 0xffff) return 2;
3068 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3069 memcpy(*str, ptr + 2, bytelen);
3070 (*str)[bytelen] = '\0';
3071 return bytelen + 2;
3074 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3076 char *ptr = pLibBlk;
3077 WORD w;
3079 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3080 FIXME("libblk magic = %04x\n", w);
3081 return 0;
3084 ptr += 6;
3085 if((w = *(WORD*)ptr) != 0xffff) {
3086 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3087 ptr += w;
3089 ptr += 2;
3091 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3093 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3095 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3096 ptr += 4;
3098 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3099 ptr += 2;
3101 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3102 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3103 else
3104 pTypeLibImpl->LibAttr.lcid = 0;
3105 ptr += 2;
3107 ptr += 4; /* skip res12 */
3109 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3110 ptr += 2;
3112 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3113 ptr += 2;
3115 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3116 ptr += 2;
3118 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3119 ptr += sizeof(GUID);
3121 return ptr - (char*)pLibBlk;
3124 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3125 typedef struct
3127 unsigned int num;
3128 HREFTYPE refs[1];
3129 } sltg_ref_lookup_t;
3131 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3132 HREFTYPE *typelib_ref)
3134 if(typeinfo_ref < table->num)
3136 *typelib_ref = table->refs[typeinfo_ref];
3137 return S_OK;
3140 ERR_(typelib)("Unable to find reference\n");
3141 *typelib_ref = -1;
3142 return E_FAIL;
3145 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3147 BOOL done = FALSE;
3149 while(!done) {
3150 if((*pType & 0xe00) == 0xe00) {
3151 pTD->vt = VT_PTR;
3152 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3153 sizeof(TYPEDESC));
3154 pTD = pTD->u.lptdesc;
3156 switch(*pType & 0x3f) {
3157 case VT_PTR:
3158 pTD->vt = VT_PTR;
3159 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3160 sizeof(TYPEDESC));
3161 pTD = pTD->u.lptdesc;
3162 break;
3164 case VT_USERDEFINED:
3165 pTD->vt = VT_USERDEFINED;
3166 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3167 done = TRUE;
3168 break;
3170 case VT_CARRAY:
3172 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3173 array */
3175 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3177 pTD->vt = VT_CARRAY;
3178 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3179 sizeof(ARRAYDESC) +
3180 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3181 pTD->u.lpadesc->cDims = pSA->cDims;
3182 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3183 pSA->cDims * sizeof(SAFEARRAYBOUND));
3185 pTD = &pTD->u.lpadesc->tdescElem;
3186 break;
3189 case VT_SAFEARRAY:
3191 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3192 useful? */
3194 pType++;
3195 pTD->vt = VT_SAFEARRAY;
3196 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3197 sizeof(TYPEDESC));
3198 pTD = pTD->u.lptdesc;
3199 break;
3201 default:
3202 pTD->vt = *pType & 0x3f;
3203 done = TRUE;
3204 break;
3206 pType++;
3208 return pType;
3211 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3212 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3214 /* Handle [in/out] first */
3215 if((*pType & 0xc000) == 0xc000)
3216 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3217 else if(*pType & 0x8000)
3218 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3219 else if(*pType & 0x4000)
3220 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3221 else
3222 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3224 if(*pType & 0x2000)
3225 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3227 if(*pType & 0x80)
3228 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3230 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3234 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3235 char *pNameTable)
3237 unsigned int ref;
3238 char *name;
3239 TLBRefType *ref_type;
3240 sltg_ref_lookup_t *table;
3241 HREFTYPE typelib_ref;
3243 if(pRef->magic != SLTG_REF_MAGIC) {
3244 FIXME("Ref magic = %x\n", pRef->magic);
3245 return NULL;
3247 name = ( (char*)pRef->names + pRef->number);
3249 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3250 table->num = pRef->number >> 3;
3252 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3254 /* We don't want the first href to be 0 */
3255 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3257 for(ref = 0; ref < pRef->number >> 3; ref++) {
3258 char *refname;
3259 unsigned int lib_offs, type_num;
3261 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3263 name += SLTG_ReadStringA(name, &refname);
3264 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3265 FIXME_(typelib)("Can't sscanf ref\n");
3266 if(lib_offs != 0xffff) {
3267 TLBImpLib **import = &pTL->pImpLibs;
3269 while(*import) {
3270 if((*import)->offset == lib_offs)
3271 break;
3272 import = &(*import)->next;
3274 if(!*import) {
3275 char fname[MAX_PATH+1];
3276 int len;
3278 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3279 sizeof(**import));
3280 (*import)->offset = lib_offs;
3281 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3282 &(*import)->guid);
3283 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3284 &(*import)->wVersionMajor,
3285 &(*import)->wVersionMinor,
3286 &(*import)->lcid, fname) != 4) {
3287 FIXME_(typelib)("can't sscanf ref %s\n",
3288 pNameTable + lib_offs + 40);
3290 len = strlen(fname);
3291 if(fname[len-1] != '#')
3292 FIXME("fname = %s\n", fname);
3293 fname[len-1] = '\0';
3294 (*import)->name = TLB_MultiByteToBSTR(fname);
3296 ref_type->pImpTLInfo = *import;
3298 /* Store a reference to IDispatch */
3299 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3300 pTL->dispatch_href = typelib_ref;
3302 } else { /* internal ref */
3303 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3305 ref_type->reference = typelib_ref;
3306 ref_type->index = type_num;
3308 HeapFree(GetProcessHeap(), 0, refname);
3309 list_add_tail(&pTL->ref_list, &ref_type->entry);
3311 table->refs[ref] = typelib_ref;
3312 typelib_ref += 4;
3314 if((BYTE)*name != SLTG_REF_MAGIC)
3315 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3316 dump_TLBRefType(pTL);
3317 return table;
3320 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3321 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3323 SLTG_ImplInfo *info;
3324 TLBImplType **ppImplType = &pTI->impltypelist;
3325 /* I don't really get this structure, usually it's 0x16 bytes
3326 long, but iuser.tlb contains some that are 0x18 bytes long.
3327 That's ok because we can use the next ptr to jump to the next
3328 one. But how do we know the length of the last one? The WORD
3329 at offs 0x8 might be the clue. For now I'm just assuming that
3330 the last one is the regular 0x16 bytes. */
3332 info = (SLTG_ImplInfo*)pBlk;
3333 while(1) {
3334 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3335 sizeof(**ppImplType));
3336 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3337 (*ppImplType)->implflags = info->impltypeflags;
3338 pTI->TypeAttr.cImplTypes++;
3339 ppImplType = &(*ppImplType)->next;
3341 if(info->next == 0xffff)
3342 break;
3343 if(OneOnly)
3344 FIXME_(typelib)("Interface inheriting more than one interface\n");
3345 info = (SLTG_ImplInfo*)(pBlk + info->next);
3347 info++; /* see comment at top of function */
3348 return (char*)info;
3351 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3352 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3354 TLBVarDesc **ppVarDesc = &pTI->varlist;
3355 BSTR bstrPrevName = NULL;
3356 SLTG_Variable *pItem;
3357 unsigned short i;
3358 WORD *pType;
3360 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3361 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3363 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3364 sizeof(**ppVarDesc));
3365 (*ppVarDesc)->vardesc.memid = pItem->memid;
3367 if (pItem->magic != SLTG_VAR_MAGIC &&
3368 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3369 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3370 return;
3373 if (pItem->name == 0xfffe)
3374 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3375 else
3376 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3378 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3379 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3380 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3382 if(pItem->flags & 0x02)
3383 pType = &pItem->type;
3384 else
3385 pType = (WORD*)(pBlk + pItem->type);
3387 if (pItem->flags & ~0xda)
3388 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3390 SLTG_DoElem(pType, pBlk,
3391 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3393 if (TRACE_ON(typelib)) {
3394 char buf[300];
3395 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3396 TRACE_(typelib)("elemdescVar: %s\n", buf);
3399 if (pItem->flags & 0x40) {
3400 TRACE_(typelib)("VAR_DISPATCH\n");
3401 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3403 else if (pItem->flags & 0x10) {
3404 TRACE_(typelib)("VAR_CONST\n");
3405 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3406 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3407 sizeof(VARIANT));
3408 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3409 if (pItem->flags & 0x08)
3410 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3411 else {
3412 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3414 case VT_LPSTR:
3415 case VT_LPWSTR:
3416 case VT_BSTR:
3418 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3419 BSTR str;
3420 TRACE_(typelib)("len = %u\n", len);
3421 if (len == 0xffff) {
3422 str = NULL;
3423 } else {
3424 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3425 str = SysAllocStringLen(NULL, alloc_len);
3426 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3428 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3429 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3430 break;
3432 case VT_I2:
3433 case VT_UI2:
3434 case VT_I4:
3435 case VT_UI4:
3436 case VT_INT:
3437 case VT_UINT:
3438 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3439 *(INT*)(pBlk + pItem->byte_offs);
3440 break;
3441 default:
3442 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3446 else {
3447 TRACE_(typelib)("VAR_PERINSTANCE\n");
3448 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3449 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3452 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3453 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3455 if (pItem->flags & 0x80)
3456 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3458 bstrPrevName = (*ppVarDesc)->Name;
3459 ppVarDesc = &((*ppVarDesc)->next);
3461 pTI->TypeAttr.cVars = cVars;
3464 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3465 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3467 SLTG_Function *pFunc;
3468 unsigned short i;
3469 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3471 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3472 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3474 int param;
3475 WORD *pType, *pArg;
3477 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3478 sizeof(**ppFuncDesc));
3480 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3481 case SLTG_FUNCTION_MAGIC:
3482 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3483 break;
3484 case SLTG_DISPATCH_FUNCTION_MAGIC:
3485 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3486 break;
3487 case SLTG_STATIC_FUNCTION_MAGIC:
3488 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3489 break;
3490 default:
3491 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3492 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3493 *ppFuncDesc = NULL;
3494 return;
3496 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3498 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3499 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3500 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3501 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3502 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3503 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3505 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3506 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3508 if(pFunc->retnextopt & 0x80)
3509 pType = &pFunc->rettype;
3510 else
3511 pType = (WORD*)(pBlk + pFunc->rettype);
3513 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3515 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3516 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3517 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3518 (*ppFuncDesc)->pParamDesc =
3519 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3520 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3522 pArg = (WORD*)(pBlk + pFunc->arg_off);
3524 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3525 char *paramName = pNameTable + *pArg;
3526 BOOL HaveOffs;
3527 /* If arg type follows then paramName points to the 2nd
3528 letter of the name, else the next WORD is an offset to
3529 the arg type and paramName points to the first letter.
3530 So let's take one char off paramName and see if we're
3531 pointing at an alpha-numeric char. However if *pArg is
3532 0xffff or 0xfffe then the param has no name, the former
3533 meaning that the next WORD is the type, the latter
3534 meaning that the next WORD is an offset to the type. */
3536 HaveOffs = FALSE;
3537 if(*pArg == 0xffff)
3538 paramName = NULL;
3539 else if(*pArg == 0xfffe) {
3540 paramName = NULL;
3541 HaveOffs = TRUE;
3543 else if(paramName[-1] && !isalnum(paramName[-1]))
3544 HaveOffs = TRUE;
3546 pArg++;
3548 if(HaveOffs) { /* the next word is an offset to type */
3549 pType = (WORD*)(pBlk + *pArg);
3550 SLTG_DoElem(pType, pBlk,
3551 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3552 pArg++;
3553 } else {
3554 if(paramName)
3555 paramName--;
3556 pArg = SLTG_DoElem(pArg, pBlk,
3557 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3560 /* Are we an optional param ? */
3561 if((*ppFuncDesc)->funcdesc.cParams - param <=
3562 (*ppFuncDesc)->funcdesc.cParamsOpt)
3563 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3565 if(paramName) {
3566 (*ppFuncDesc)->pParamDesc[param].Name =
3567 TLB_MultiByteToBSTR(paramName);
3568 } else {
3569 (*ppFuncDesc)->pParamDesc[param].Name =
3570 SysAllocString((*ppFuncDesc)->Name);
3574 ppFuncDesc = &((*ppFuncDesc)->next);
3575 if(pFunc->next == 0xffff) break;
3577 pTI->TypeAttr.cFuncs = cFuncs;
3580 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3581 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3582 SLTG_TypeInfoTail *pTITail)
3584 char *pFirstItem;
3585 sltg_ref_lookup_t *ref_lookup = NULL;
3587 if(pTIHeader->href_table != 0xffffffff) {
3588 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3589 pNameTable);
3592 pFirstItem = pBlk;
3594 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3595 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3597 HeapFree(GetProcessHeap(), 0, ref_lookup);
3601 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3602 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3603 const SLTG_TypeInfoTail *pTITail)
3605 char *pFirstItem;
3606 sltg_ref_lookup_t *ref_lookup = NULL;
3608 if(pTIHeader->href_table != 0xffffffff) {
3609 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3610 pNameTable);
3613 pFirstItem = pBlk;
3615 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3616 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3619 if (pTITail->funcs_off != 0xffff)
3620 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3622 HeapFree(GetProcessHeap(), 0, ref_lookup);
3624 if (TRACE_ON(typelib))
3625 dump_TLBFuncDesc(pTI->funclist);
3628 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3629 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3630 const SLTG_TypeInfoTail *pTITail)
3632 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3635 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3636 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3637 const SLTG_TypeInfoTail *pTITail)
3639 WORD *pType;
3640 sltg_ref_lookup_t *ref_lookup = NULL;
3642 if (pTITail->simple_alias) {
3643 /* if simple alias, no more processing required */
3644 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3645 return;
3648 if(pTIHeader->href_table != 0xffffffff) {
3649 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3650 pNameTable);
3653 /* otherwise it is an offset to a type */
3654 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3656 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3658 HeapFree(GetProcessHeap(), 0, ref_lookup);
3661 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3662 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3663 const SLTG_TypeInfoTail *pTITail)
3665 sltg_ref_lookup_t *ref_lookup = NULL;
3666 if (pTIHeader->href_table != 0xffffffff)
3667 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3668 pNameTable);
3670 if (pTITail->vars_off != 0xffff)
3671 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3673 if (pTITail->funcs_off != 0xffff)
3674 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3676 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3677 * of dispinterface functions including the IDispatch ones, so
3678 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3679 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3681 HeapFree(GetProcessHeap(), 0, ref_lookup);
3682 if (TRACE_ON(typelib))
3683 dump_TLBFuncDesc(pTI->funclist);
3686 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3687 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3688 const SLTG_TypeInfoTail *pTITail)
3690 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3693 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3694 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3695 const SLTG_TypeInfoTail *pTITail)
3697 sltg_ref_lookup_t *ref_lookup = NULL;
3698 if (pTIHeader->href_table != 0xffffffff)
3699 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3700 pNameTable);
3702 if (pTITail->vars_off != 0xffff)
3703 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3705 if (pTITail->funcs_off != 0xffff)
3706 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3707 HeapFree(GetProcessHeap(), 0, ref_lookup);
3708 if (TRACE_ON(typelib))
3709 dump_TypeInfo(pTI);
3712 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3713 managable copy of it into this */
3714 typedef struct {
3715 WORD small_no;
3716 char *index_name;
3717 char *other_name;
3718 WORD res1a;
3719 WORD name_offs;
3720 WORD more_bytes;
3721 char *extra;
3722 WORD res20;
3723 DWORD helpcontext;
3724 WORD res26;
3725 GUID uuid;
3726 } SLTG_InternalOtherTypeInfo;
3728 /****************************************************************************
3729 * ITypeLib2_Constructor_SLTG
3731 * loading a SLTG typelib from an in-memory image
3733 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3735 ITypeLibImpl *pTypeLibImpl;
3736 SLTG_Header *pHeader;
3737 SLTG_BlkEntry *pBlkEntry;
3738 SLTG_Magic *pMagic;
3739 SLTG_Index *pIndex;
3740 SLTG_Pad9 *pPad9;
3741 LPVOID pBlk, pFirstBlk;
3742 SLTG_LibBlk *pLibBlk;
3743 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3744 char *pAfterOTIBlks = NULL;
3745 char *pNameTable, *ptr;
3746 int i;
3747 DWORD len, order;
3748 ITypeInfoImpl **ppTypeInfoImpl;
3750 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3753 pTypeLibImpl = TypeLibImpl_Constructor();
3754 if (!pTypeLibImpl) return NULL;
3756 pHeader = pLib;
3758 TRACE_(typelib)("header:\n");
3759 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3760 pHeader->nrOfFileBlks );
3761 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3762 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3763 pHeader->SLTG_magic);
3764 return NULL;
3767 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3768 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3770 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3771 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3773 /* Next we have a magic block */
3774 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3776 /* Let's see if we're still in sync */
3777 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3778 sizeof(SLTG_COMPOBJ_MAGIC))) {
3779 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3780 return NULL;
3782 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3783 sizeof(SLTG_DIR_MAGIC))) {
3784 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3785 return NULL;
3788 pIndex = (SLTG_Index*)(pMagic+1);
3790 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3792 pFirstBlk = pPad9 + 1;
3794 /* We'll set up a ptr to the main library block, which is the last one. */
3796 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3797 pBlkEntry[order].next != 0;
3798 order = pBlkEntry[order].next - 1, i++) {
3799 pBlk = (char*)pBlk + pBlkEntry[order].len;
3801 pLibBlk = pBlk;
3803 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3805 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3806 interspersed */
3808 len += 0x40;
3810 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3812 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3813 sizeof(*pOtherTypeInfoBlks) *
3814 pTypeLibImpl->TypeInfoCount);
3817 ptr = (char*)pLibBlk + len;
3819 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3820 WORD w, extra;
3821 len = 0;
3823 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3825 w = *(WORD*)(ptr + 2);
3826 if(w != 0xffff) {
3827 len += w;
3828 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3829 w+1);
3830 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3831 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3833 w = *(WORD*)(ptr + 4 + len);
3834 if(w != 0xffff) {
3835 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3836 len += w;
3837 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3838 w+1);
3839 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3840 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3842 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3843 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3844 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3845 if(extra) {
3846 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3847 extra);
3848 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3849 len += extra;
3851 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3852 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3853 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3854 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3855 len += sizeof(SLTG_OtherTypeInfo);
3856 ptr += len;
3859 pAfterOTIBlks = ptr;
3861 /* Skip this WORD and get the next DWORD */
3862 len = *(DWORD*)(pAfterOTIBlks + 2);
3864 /* Now add this to pLibBLk look at what we're pointing at and
3865 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3866 dust and we should be pointing at the beginning of the name
3867 table */
3869 pNameTable = (char*)pLibBlk + len;
3871 switch(*(WORD*)pNameTable) {
3872 case 0xffff:
3873 break;
3874 case 0x0200:
3875 pNameTable += 0x20;
3876 break;
3877 default:
3878 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3879 break;
3882 pNameTable += 0x216;
3884 pNameTable += 2;
3886 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3888 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3891 /* Hopefully we now have enough ptrs set up to actually read in
3892 some TypeInfos. It's not clear which order to do them in, so
3893 I'll just follow the links along the BlkEntry chain and read
3894 them in the order in which they are in the file */
3896 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3898 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3899 pBlkEntry[order].next != 0;
3900 order = pBlkEntry[order].next - 1, i++) {
3902 SLTG_TypeInfoHeader *pTIHeader;
3903 SLTG_TypeInfoTail *pTITail;
3904 SLTG_MemberHeader *pMemHeader;
3906 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3907 pOtherTypeInfoBlks[i].index_name)) {
3908 FIXME_(typelib)("Index strings don't match\n");
3909 return NULL;
3912 pTIHeader = pBlk;
3913 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3914 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3915 return NULL;
3917 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3918 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3919 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3921 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3922 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3923 (*ppTypeInfoImpl)->index = i;
3924 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3925 pOtherTypeInfoBlks[i].name_offs +
3926 pNameTable);
3927 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3928 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3929 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3930 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3931 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3932 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3933 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3935 if((pTIHeader->typeflags1 & 7) != 2)
3936 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3937 if(pTIHeader->typeflags3 != 2)
3938 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3940 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3941 debugstr_w((*ppTypeInfoImpl)->Name),
3942 typekind_desc[pTIHeader->typekind],
3943 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3944 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3946 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3948 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3950 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3951 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3952 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3954 switch(pTIHeader->typekind) {
3955 case TKIND_ENUM:
3956 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3957 pTIHeader, pTITail);
3958 break;
3960 case TKIND_RECORD:
3961 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3962 pTIHeader, pTITail);
3963 break;
3965 case TKIND_INTERFACE:
3966 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3967 pTIHeader, pTITail);
3968 break;
3970 case TKIND_COCLASS:
3971 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3972 pTIHeader, pTITail);
3973 break;
3975 case TKIND_ALIAS:
3976 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3977 pTIHeader, pTITail);
3978 break;
3980 case TKIND_DISPATCH:
3981 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3982 pTIHeader, pTITail);
3983 break;
3985 case TKIND_MODULE:
3986 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3987 pTIHeader, pTITail);
3988 break;
3990 default:
3991 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3992 break;
3996 /* could get cFuncs, cVars and cImplTypes from here
3997 but we've already set those */
3998 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3999 X(06);
4000 X(16);
4001 X(18);
4002 X(1a);
4003 X(1e);
4004 X(24);
4005 X(26);
4006 X(2a);
4007 X(2c);
4008 X(2e);
4009 X(30);
4010 X(32);
4011 X(34);
4012 #undef X
4013 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4014 pBlk = (char*)pBlk + pBlkEntry[order].len;
4017 if(i != pTypeLibImpl->TypeInfoCount) {
4018 FIXME("Somehow processed %d TypeInfos\n", i);
4019 return NULL;
4022 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4023 return (ITypeLib2*)pTypeLibImpl;
4026 /* ITypeLib::QueryInterface
4028 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4029 ITypeLib2 * iface,
4030 REFIID riid,
4031 VOID **ppvObject)
4033 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4035 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4037 *ppvObject=NULL;
4038 if(IsEqualIID(riid, &IID_IUnknown) ||
4039 IsEqualIID(riid,&IID_ITypeLib)||
4040 IsEqualIID(riid,&IID_ITypeLib2))
4042 *ppvObject = This;
4045 if(*ppvObject)
4047 ITypeLib2_AddRef(iface);
4048 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4049 return S_OK;
4051 TRACE("-- Interface: E_NOINTERFACE\n");
4052 return E_NOINTERFACE;
4055 /* ITypeLib::AddRef
4057 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4059 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4060 ULONG ref = InterlockedIncrement(&This->ref);
4062 TRACE("(%p)->ref was %u\n",This, ref - 1);
4064 return ref;
4067 /* ITypeLib::Release
4069 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4071 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4072 ULONG ref = InterlockedDecrement(&This->ref);
4074 TRACE("(%p)->(%u)\n",This, ref);
4076 if (!ref)
4078 TLBImpLib *pImpLib, *pImpLibNext;
4079 TLBCustData *pCustData, *pCustDataNext;
4080 TLBRefType *ref_type;
4081 void *cursor2;
4082 int i;
4084 /* remove cache entry */
4085 if(This->path)
4087 TRACE("removing from cache list\n");
4088 EnterCriticalSection(&cache_section);
4089 if (This->next) This->next->prev = This->prev;
4090 if (This->prev) This->prev->next = This->next;
4091 else tlb_cache_first = This->next;
4092 LeaveCriticalSection(&cache_section);
4093 HeapFree(GetProcessHeap(), 0, This->path);
4095 TRACE(" destroying ITypeLib(%p)\n",This);
4097 SysFreeString(This->Name);
4098 This->Name = NULL;
4100 SysFreeString(This->DocString);
4101 This->DocString = NULL;
4103 SysFreeString(This->HelpFile);
4104 This->HelpFile = NULL;
4106 SysFreeString(This->HelpStringDll);
4107 This->HelpStringDll = NULL;
4109 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4111 VariantClear(&pCustData->data);
4113 pCustDataNext = pCustData->next;
4114 TLB_Free(pCustData);
4117 for (i = 0; i < This->ctTypeDesc; i++)
4118 if (This->pTypeDesc[i].vt == VT_CARRAY)
4119 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4121 TLB_Free(This->pTypeDesc);
4123 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4125 if (pImpLib->pImpTypeLib)
4126 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4127 SysFreeString(pImpLib->name);
4129 pImpLibNext = pImpLib->next;
4130 TLB_Free(pImpLib);
4133 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4135 list_remove(&ref_type->entry);
4136 TLB_Free(ref_type);
4139 if (This->pTypeInfo) /* can be NULL */
4140 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4141 HeapFree(GetProcessHeap(),0,This);
4142 return 0;
4145 return ref;
4148 /* ITypeLib::GetTypeInfoCount
4150 * Returns the number of type descriptions in the type library
4152 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4154 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4155 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4156 return This->TypeInfoCount;
4159 /* ITypeLib::GetTypeInfo
4161 * retrieves the specified type description in the library.
4163 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4164 ITypeLib2 *iface,
4165 UINT index,
4166 ITypeInfo **ppTInfo)
4168 UINT i;
4170 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4171 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4173 TRACE("(%p)->(index=%d)\n", This, index);
4175 if (!ppTInfo) return E_INVALIDARG;
4177 /* search element n in list */
4178 for(i=0; i < index; i++)
4180 pTypeInfo = pTypeInfo->next;
4181 if (!pTypeInfo)
4183 TRACE("-- element not found\n");
4184 return TYPE_E_ELEMENTNOTFOUND;
4188 *ppTInfo = (ITypeInfo *) pTypeInfo;
4190 ITypeInfo_AddRef(*ppTInfo);
4191 TRACE("-- found (%p)\n",*ppTInfo);
4192 return S_OK;
4196 /* ITypeLibs::GetTypeInfoType
4198 * Retrieves the type of a type description.
4200 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4201 ITypeLib2 *iface,
4202 UINT index,
4203 TYPEKIND *pTKind)
4205 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4206 UINT i;
4207 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4209 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4210 return TYPE_E_ELEMENTNOTFOUND;
4212 TRACE("(%p) index %d\n", This, index);
4214 if(!pTKind) return E_INVALIDARG;
4216 /* search element n in list */
4217 for(i=0; i < index; i++)
4219 if(!pTInfo)
4221 TRACE("-- element not found\n");
4222 return TYPE_E_ELEMENTNOTFOUND;
4224 pTInfo = pTInfo->next;
4227 *pTKind = pTInfo->TypeAttr.typekind;
4228 TRACE("-- found Type (%d)\n", *pTKind);
4229 return S_OK;
4232 /* ITypeLib::GetTypeInfoOfGuid
4234 * Retrieves the type description that corresponds to the specified GUID.
4237 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4238 ITypeLib2 *iface,
4239 REFGUID guid,
4240 ITypeInfo **ppTInfo)
4242 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4243 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4245 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4247 if (!pTypeInfo)
4249 WARN("-- element not found\n");
4250 return TYPE_E_ELEMENTNOTFOUND;
4253 /* search linked list for guid */
4254 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4256 pTypeInfo = pTypeInfo->next;
4258 if (!pTypeInfo)
4260 /* end of list reached */
4261 WARN("-- element not found\n");
4262 return TYPE_E_ELEMENTNOTFOUND;
4266 TRACE("-- found (%p, %s)\n",
4267 pTypeInfo,
4268 debugstr_w(pTypeInfo->Name));
4270 *ppTInfo = (ITypeInfo*)pTypeInfo;
4271 ITypeInfo_AddRef(*ppTInfo);
4272 return S_OK;
4275 /* ITypeLib::GetLibAttr
4277 * Retrieves the structure that contains the library's attributes.
4280 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4281 ITypeLib2 *iface,
4282 LPTLIBATTR *ppTLibAttr)
4284 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4285 TRACE("(%p)\n",This);
4286 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4287 **ppTLibAttr = This->LibAttr;
4288 return S_OK;
4291 /* ITypeLib::GetTypeComp
4293 * Enables a client compiler to bind to a library's types, variables,
4294 * constants, and global functions.
4297 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4298 ITypeLib2 *iface,
4299 ITypeComp **ppTComp)
4301 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4303 TRACE("(%p)->(%p)\n",This,ppTComp);
4304 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4305 ITypeComp_AddRef(*ppTComp);
4307 return S_OK;
4310 /* ITypeLib::GetDocumentation
4312 * Retrieves the library's documentation string, the complete Help file name
4313 * and path, and the context identifier for the library Help topic in the Help
4314 * file.
4316 * On a successful return all non-null BSTR pointers will have been set,
4317 * possibly to NULL.
4319 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4320 ITypeLib2 *iface,
4321 INT index,
4322 BSTR *pBstrName,
4323 BSTR *pBstrDocString,
4324 DWORD *pdwHelpContext,
4325 BSTR *pBstrHelpFile)
4327 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4329 HRESULT result = E_INVALIDARG;
4331 ITypeInfo *pTInfo;
4334 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4335 This, index,
4336 pBstrName, pBstrDocString,
4337 pdwHelpContext, pBstrHelpFile);
4339 if(index<0)
4341 /* documentation for the typelib */
4342 if(pBstrName)
4344 if (This->Name)
4346 if(!(*pBstrName = SysAllocString(This->Name)))
4347 goto memerr1;
4349 else
4350 *pBstrName = NULL;
4352 if(pBstrDocString)
4354 if (This->DocString)
4356 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4357 goto memerr2;
4359 else if (This->Name)
4361 if(!(*pBstrDocString = SysAllocString(This->Name)))
4362 goto memerr2;
4364 else
4365 *pBstrDocString = NULL;
4367 if(pdwHelpContext)
4369 *pdwHelpContext = This->dwHelpContext;
4371 if(pBstrHelpFile)
4373 if (This->HelpFile)
4375 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4376 goto memerr3;
4378 else
4379 *pBstrHelpFile = NULL;
4382 result = S_OK;
4384 else
4386 /* for a typeinfo */
4387 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4389 if(SUCCEEDED(result))
4391 result = ITypeInfo_GetDocumentation(pTInfo,
4392 MEMBERID_NIL,
4393 pBstrName,
4394 pBstrDocString,
4395 pdwHelpContext, pBstrHelpFile);
4397 ITypeInfo_Release(pTInfo);
4400 return result;
4401 memerr3:
4402 if (pBstrDocString) SysFreeString (*pBstrDocString);
4403 memerr2:
4404 if (pBstrName) SysFreeString (*pBstrName);
4405 memerr1:
4406 return STG_E_INSUFFICIENTMEMORY;
4409 /* ITypeLib::IsName
4411 * Indicates whether a passed-in string contains the name of a type or member
4412 * described in the library.
4415 static HRESULT WINAPI ITypeLib2_fnIsName(
4416 ITypeLib2 *iface,
4417 LPOLESTR szNameBuf,
4418 ULONG lHashVal,
4419 BOOL *pfName)
4421 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4422 ITypeInfoImpl *pTInfo;
4423 TLBFuncDesc *pFInfo;
4424 TLBVarDesc *pVInfo;
4425 int i;
4426 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4428 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4429 pfName);
4431 *pfName=TRUE;
4432 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4433 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4434 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4435 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4436 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4437 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4438 goto ITypeLib2_fnIsName_exit;
4440 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4441 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4444 *pfName=FALSE;
4446 ITypeLib2_fnIsName_exit:
4447 TRACE("(%p)slow! search for %s: %s found!\n", This,
4448 debugstr_w(szNameBuf), *pfName?"NOT":"");
4450 return S_OK;
4453 /* ITypeLib::FindName
4455 * Finds occurrences of a type description in a type library. This may be used
4456 * to quickly verify that a name exists in a type library.
4459 static HRESULT WINAPI ITypeLib2_fnFindName(
4460 ITypeLib2 *iface,
4461 LPOLESTR szNameBuf,
4462 ULONG lHashVal,
4463 ITypeInfo **ppTInfo,
4464 MEMBERID *rgMemId,
4465 UINT16 *pcFound)
4467 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4468 ITypeInfoImpl *pTInfo;
4469 TLBFuncDesc *pFInfo;
4470 TLBVarDesc *pVInfo;
4471 int i,j = 0;
4472 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4474 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4475 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4476 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4477 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4478 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4479 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4480 goto ITypeLib2_fnFindName_exit;
4483 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4484 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4485 continue;
4486 ITypeLib2_fnFindName_exit:
4487 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4488 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4489 j++;
4491 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4492 This, *pcFound, debugstr_w(szNameBuf), j);
4494 *pcFound=j;
4496 return S_OK;
4499 /* ITypeLib::ReleaseTLibAttr
4501 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4504 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4505 ITypeLib2 *iface,
4506 TLIBATTR *pTLibAttr)
4508 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4509 TRACE("freeing (%p)\n",This);
4510 HeapFree(GetProcessHeap(),0,pTLibAttr);
4514 /* ITypeLib2::GetCustData
4516 * gets the custom data
4518 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4519 ITypeLib2 * iface,
4520 REFGUID guid,
4521 VARIANT *pVarVal)
4523 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4524 TLBCustData *pCData;
4526 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4528 if( IsEqualIID(guid, &pCData->guid)) break;
4531 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4533 if(pCData)
4535 VariantInit( pVarVal);
4536 VariantCopy( pVarVal, &pCData->data);
4537 return S_OK;
4539 return E_INVALIDARG; /* FIXME: correct? */
4542 /* ITypeLib2::GetLibStatistics
4544 * Returns statistics about a type library that are required for efficient
4545 * sizing of hash tables.
4548 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4549 ITypeLib2 * iface,
4550 ULONG *pcUniqueNames,
4551 ULONG *pcchUniqueNames)
4553 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4555 FIXME("(%p): stub!\n", This);
4557 if(pcUniqueNames) *pcUniqueNames=1;
4558 if(pcchUniqueNames) *pcchUniqueNames=1;
4559 return S_OK;
4562 /* ITypeLib2::GetDocumentation2
4564 * Retrieves the library's documentation string, the complete Help file name
4565 * and path, the localization context to use, and the context ID for the
4566 * library Help topic in the Help file.
4569 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4570 ITypeLib2 * iface,
4571 INT index,
4572 LCID lcid,
4573 BSTR *pbstrHelpString,
4574 DWORD *pdwHelpStringContext,
4575 BSTR *pbstrHelpStringDll)
4577 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4578 HRESULT result;
4579 ITypeInfo *pTInfo;
4581 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4583 /* the help string should be obtained from the helpstringdll,
4584 * using the _DLLGetDocumentation function, based on the supplied
4585 * lcid. Nice to do sometime...
4587 if(index<0)
4589 /* documentation for the typelib */
4590 if(pbstrHelpString)
4591 *pbstrHelpString=SysAllocString(This->DocString);
4592 if(pdwHelpStringContext)
4593 *pdwHelpStringContext=This->dwHelpContext;
4594 if(pbstrHelpStringDll)
4595 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4597 result = S_OK;
4599 else
4601 /* for a typeinfo */
4602 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4604 if(SUCCEEDED(result))
4606 ITypeInfo2 * pTInfo2;
4607 result = ITypeInfo_QueryInterface(pTInfo,
4608 &IID_ITypeInfo2,
4609 (LPVOID*) &pTInfo2);
4611 if(SUCCEEDED(result))
4613 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4614 MEMBERID_NIL,
4615 lcid,
4616 pbstrHelpString,
4617 pdwHelpStringContext,
4618 pbstrHelpStringDll);
4620 ITypeInfo2_Release(pTInfo2);
4623 ITypeInfo_Release(pTInfo);
4626 return result;
4629 /* ITypeLib2::GetAllCustData
4631 * Gets all custom data items for the library.
4634 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4635 ITypeLib2 * iface,
4636 CUSTDATA *pCustData)
4638 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4639 TLBCustData *pCData;
4640 int i;
4641 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4642 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4643 if(pCustData->prgCustData ){
4644 pCustData->cCustData=This->ctCustData;
4645 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4646 pCustData->prgCustData[i].guid=pCData->guid;
4647 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4649 }else{
4650 ERR(" OUT OF MEMORY!\n");
4651 return E_OUTOFMEMORY;
4653 return S_OK;
4656 static const ITypeLib2Vtbl tlbvt = {
4657 ITypeLib2_fnQueryInterface,
4658 ITypeLib2_fnAddRef,
4659 ITypeLib2_fnRelease,
4660 ITypeLib2_fnGetTypeInfoCount,
4661 ITypeLib2_fnGetTypeInfo,
4662 ITypeLib2_fnGetTypeInfoType,
4663 ITypeLib2_fnGetTypeInfoOfGuid,
4664 ITypeLib2_fnGetLibAttr,
4665 ITypeLib2_fnGetTypeComp,
4666 ITypeLib2_fnGetDocumentation,
4667 ITypeLib2_fnIsName,
4668 ITypeLib2_fnFindName,
4669 ITypeLib2_fnReleaseTLibAttr,
4671 ITypeLib2_fnGetCustData,
4672 ITypeLib2_fnGetLibStatistics,
4673 ITypeLib2_fnGetDocumentation2,
4674 ITypeLib2_fnGetAllCustData
4678 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4680 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4682 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4685 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4687 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4689 return ITypeLib2_AddRef((ITypeLib2 *)This);
4692 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4694 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4696 return ITypeLib2_Release((ITypeLib2 *)This);
4699 static HRESULT WINAPI ITypeLibComp_fnBind(
4700 ITypeComp * iface,
4701 OLECHAR * szName,
4702 ULONG lHash,
4703 WORD wFlags,
4704 ITypeInfo ** ppTInfo,
4705 DESCKIND * pDescKind,
4706 BINDPTR * pBindPtr)
4708 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4709 ITypeInfoImpl *pTypeInfo;
4711 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4713 *pDescKind = DESCKIND_NONE;
4714 pBindPtr->lptcomp = NULL;
4715 *ppTInfo = NULL;
4717 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4719 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4721 /* FIXME: check wFlags here? */
4722 /* FIXME: we should use a hash table to look this info up using lHash
4723 * instead of an O(n) search */
4724 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4725 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4727 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4729 *pDescKind = DESCKIND_TYPECOMP;
4730 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4731 ITypeComp_AddRef(pBindPtr->lptcomp);
4732 TRACE("module or enum: %s\n", debugstr_w(szName));
4733 return S_OK;
4737 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4738 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4740 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4741 HRESULT hr;
4743 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4744 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4746 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4747 return S_OK;
4751 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4752 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4754 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4755 HRESULT hr;
4756 ITypeInfo *subtypeinfo;
4757 BINDPTR subbindptr;
4758 DESCKIND subdesckind;
4760 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4761 &subtypeinfo, &subdesckind, &subbindptr);
4762 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4764 TYPEDESC tdesc_appobject =
4767 (TYPEDESC *)pTypeInfo->hreftype
4769 VT_USERDEFINED
4771 const VARDESC vardesc_appobject =
4773 -2, /* memid */
4774 NULL, /* lpstrSchema */
4776 0 /* oInst */
4779 /* ELEMDESC */
4781 /* TYPEDESC */
4783 &tdesc_appobject
4785 VT_PTR
4788 0, /* wVarFlags */
4789 VAR_STATIC /* varkind */
4792 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4794 /* cleanup things filled in by Bind call so we can put our
4795 * application object data in there instead */
4796 switch (subdesckind)
4798 case DESCKIND_FUNCDESC:
4799 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4800 break;
4801 case DESCKIND_VARDESC:
4802 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4803 break;
4804 default:
4805 break;
4807 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4809 if (pTypeInfo->hreftype == -1)
4810 FIXME("no hreftype for interface %p\n", pTypeInfo);
4812 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4813 if (FAILED(hr))
4814 return hr;
4816 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4817 *ppTInfo = (ITypeInfo *)pTypeInfo;
4818 ITypeInfo_AddRef(*ppTInfo);
4819 return S_OK;
4824 TRACE("name not found %s\n", debugstr_w(szName));
4825 return S_OK;
4828 static HRESULT WINAPI ITypeLibComp_fnBindType(
4829 ITypeComp * iface,
4830 OLECHAR * szName,
4831 ULONG lHash,
4832 ITypeInfo ** ppTInfo,
4833 ITypeComp ** ppTComp)
4835 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4836 return E_NOTIMPL;
4839 static const ITypeCompVtbl tlbtcvt =
4842 ITypeLibComp_fnQueryInterface,
4843 ITypeLibComp_fnAddRef,
4844 ITypeLibComp_fnRelease,
4846 ITypeLibComp_fnBind,
4847 ITypeLibComp_fnBindType
4850 /*================== ITypeInfo(2) Methods ===================================*/
4851 static ITypeInfo2 * ITypeInfo_Constructor(void)
4853 ITypeInfoImpl * pTypeInfoImpl;
4855 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4856 if (pTypeInfoImpl)
4858 pTypeInfoImpl->lpVtbl = &tinfvt;
4859 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4860 pTypeInfoImpl->ref=1;
4861 pTypeInfoImpl->hreftype = -1;
4862 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4863 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4865 TRACE("(%p)\n", pTypeInfoImpl);
4866 return (ITypeInfo2*) pTypeInfoImpl;
4869 /* ITypeInfo::QueryInterface
4871 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4872 ITypeInfo2 *iface,
4873 REFIID riid,
4874 VOID **ppvObject)
4876 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4878 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4880 *ppvObject=NULL;
4881 if(IsEqualIID(riid, &IID_IUnknown) ||
4882 IsEqualIID(riid,&IID_ITypeInfo)||
4883 IsEqualIID(riid,&IID_ITypeInfo2))
4884 *ppvObject = This;
4886 if(*ppvObject){
4887 ITypeInfo_AddRef(iface);
4888 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4889 return S_OK;
4891 TRACE("-- Interface: E_NOINTERFACE\n");
4892 return E_NOINTERFACE;
4895 /* ITypeInfo::AddRef
4897 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4899 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4900 ULONG ref = InterlockedIncrement(&This->ref);
4902 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4904 TRACE("(%p)->ref is %u\n",This, ref);
4905 return ref;
4908 /* ITypeInfo::Release
4910 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4912 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4913 ULONG ref = InterlockedDecrement(&This->ref);
4915 TRACE("(%p)->(%u)\n",This, ref);
4917 if (ref) {
4918 /* We don't release ITypeLib when ref=0 because
4919 it means that function is called by ITypeLib2_Release */
4920 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4921 } else {
4922 TLBFuncDesc *pFInfo, *pFInfoNext;
4923 TLBVarDesc *pVInfo, *pVInfoNext;
4924 TLBImplType *pImpl, *pImplNext;
4926 TRACE("destroying ITypeInfo(%p)\n",This);
4928 if (This->no_free_data)
4929 goto finish_free;
4931 SysFreeString(This->Name);
4932 This->Name = NULL;
4934 SysFreeString(This->DocString);
4935 This->DocString = NULL;
4937 SysFreeString(This->DllName);
4938 This->DllName = NULL;
4940 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4942 INT i;
4943 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4945 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4946 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4948 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4949 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4951 SysFreeString(pFInfo->pParamDesc[i].Name);
4953 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4954 TLB_Free(pFInfo->pParamDesc);
4955 TLB_FreeCustData(pFInfo->pCustData);
4956 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4957 SysFreeString(pFInfo->Entry);
4958 SysFreeString(pFInfo->HelpString);
4959 SysFreeString(pFInfo->Name);
4961 pFInfoNext = pFInfo->next;
4962 TLB_Free(pFInfo);
4964 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4966 if (pVInfo->vardesc.varkind == VAR_CONST)
4968 VariantClear(pVInfo->vardesc.u.lpvarValue);
4969 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4971 TLB_FreeCustData(pVInfo->pCustData);
4972 SysFreeString(pVInfo->Name);
4973 pVInfoNext = pVInfo->next;
4974 TLB_Free(pVInfo);
4976 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4978 TLB_FreeCustData(pImpl->pCustData);
4979 pImplNext = pImpl->next;
4980 TLB_Free(pImpl);
4982 TLB_FreeCustData(This->pCustData);
4984 finish_free:
4985 if (This->next)
4987 ITypeInfo_Release((ITypeInfo*)This->next);
4990 HeapFree(GetProcessHeap(),0,This);
4991 return 0;
4993 return ref;
4996 /* ITypeInfo::GetTypeAttr
4998 * Retrieves a TYPEATTR structure that contains the attributes of the type
4999 * description.
5002 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5003 LPTYPEATTR *ppTypeAttr)
5005 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5006 SIZE_T size;
5008 TRACE("(%p)\n",This);
5010 size = sizeof(**ppTypeAttr);
5011 if (This->TypeAttr.typekind == TKIND_ALIAS)
5012 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5014 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5015 if (!*ppTypeAttr)
5016 return E_OUTOFMEMORY;
5018 **ppTypeAttr = This->TypeAttr;
5020 if (This->TypeAttr.typekind == TKIND_ALIAS)
5021 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5022 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5024 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5025 /* This should include all the inherited funcs */
5026 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5027 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5028 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5030 return S_OK;
5033 /* ITypeInfo::GetTypeComp
5035 * Retrieves the ITypeComp interface for the type description, which enables a
5036 * client compiler to bind to the type description's members.
5039 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5040 ITypeComp * *ppTComp)
5042 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5044 TRACE("(%p)->(%p)\n", This, ppTComp);
5046 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5047 ITypeComp_AddRef(*ppTComp);
5048 return S_OK;
5051 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5053 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5054 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5055 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5056 return size;
5059 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5061 *dest = *src;
5062 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5063 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5065 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5066 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5067 *buffer += sizeof(PARAMDESCEX);
5068 *pparamdescex_dest = *pparamdescex_src;
5069 VariantInit(&pparamdescex_dest->varDefaultValue);
5070 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5071 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5073 else
5074 dest->u.paramdesc.pparamdescex = NULL;
5075 return S_OK;
5078 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5080 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5081 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5084 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5086 FUNCDESC *dest;
5087 char *buffer;
5088 SIZE_T size = sizeof(*src);
5089 SHORT i;
5090 HRESULT hr;
5092 size += sizeof(*src->lprgscode) * src->cScodes;
5093 size += TLB_SizeElemDesc(&src->elemdescFunc);
5094 for (i = 0; i < src->cParams; i++)
5096 size += sizeof(ELEMDESC);
5097 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5100 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5101 if (!dest) return E_OUTOFMEMORY;
5103 *dest = *src;
5104 if (dispinterface) /* overwrite funckind */
5105 dest->funckind = FUNC_DISPATCH;
5106 buffer = (char *)(dest + 1);
5108 dest->lprgscode = (SCODE *)buffer;
5109 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5110 buffer += sizeof(*src->lprgscode) * src->cScodes;
5112 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5113 if (FAILED(hr))
5115 SysFreeString((BSTR)dest);
5116 return hr;
5119 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5120 buffer += sizeof(ELEMDESC) * src->cParams;
5121 for (i = 0; i < src->cParams; i++)
5123 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5124 if (FAILED(hr))
5125 break;
5127 if (FAILED(hr))
5129 /* undo the above actions */
5130 for (i = i - 1; i >= 0; i--)
5131 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5132 TLB_FreeElemDesc(&dest->elemdescFunc);
5133 SysFreeString((BSTR)dest);
5134 return hr;
5137 /* special treatment for dispinterfaces: this makes functions appear
5138 * to return their [retval] value when it is really returning an
5139 * HRESULT */
5140 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5142 if (dest->cParams &&
5143 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5145 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5146 if (elemdesc->tdesc.vt != VT_PTR)
5148 ERR("elemdesc should have started with VT_PTR instead of:\n");
5149 if (ERR_ON(ole))
5150 dump_ELEMDESC(elemdesc);
5151 return E_UNEXPECTED;
5154 /* copy last parameter to the return value. we are using a flat
5155 * buffer so there is no danger of leaking memory in
5156 * elemdescFunc */
5157 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5159 /* remove the last parameter */
5160 dest->cParams--;
5162 else
5163 /* otherwise this function is made to appear to have no return
5164 * value */
5165 dest->elemdescFunc.tdesc.vt = VT_VOID;
5169 *dest_ptr = dest;
5170 return S_OK;
5173 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5175 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5176 const TLBFuncDesc *pFDesc;
5177 UINT i;
5179 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5182 if (pFDesc)
5184 *ppFuncDesc = &pFDesc->funcdesc;
5185 return S_OK;
5188 return TYPE_E_ELEMENTNOTFOUND;
5191 /* internal function to make the inherited interfaces' methods appear
5192 * part of the interface */
5193 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5194 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5196 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5197 HRESULT hr;
5198 UINT implemented_funcs = 0;
5200 if (funcs)
5201 *funcs = 0;
5202 else
5203 *hrefoffset = DISPATCH_HREF_OFFSET;
5205 if(This->impltypelist)
5207 ITypeInfo *pSubTypeInfo;
5208 UINT sub_funcs;
5210 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5211 if (FAILED(hr))
5212 return hr;
5214 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5215 index,
5216 ppFuncDesc,
5217 &sub_funcs, hrefoffset);
5218 implemented_funcs += sub_funcs;
5219 ITypeInfo_Release(pSubTypeInfo);
5220 if (SUCCEEDED(hr))
5221 return hr;
5222 *hrefoffset += DISPATCH_HREF_OFFSET;
5225 if (funcs)
5226 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5227 else
5228 *hrefoffset = 0;
5230 if (index < implemented_funcs)
5231 return E_INVALIDARG;
5232 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5233 ppFuncDesc);
5236 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5238 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5239 while (TRUE)
5241 switch (pTypeDesc->vt)
5243 case VT_USERDEFINED:
5244 pTypeDesc->u.hreftype += hrefoffset;
5245 return;
5246 case VT_PTR:
5247 case VT_SAFEARRAY:
5248 pTypeDesc = pTypeDesc->u.lptdesc;
5249 break;
5250 case VT_CARRAY:
5251 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5252 break;
5253 default:
5254 return;
5259 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5261 SHORT i;
5262 for (i = 0; i < pFuncDesc->cParams; i++)
5263 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5264 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5267 /* ITypeInfo::GetFuncDesc
5269 * Retrieves the FUNCDESC structure that contains information about a
5270 * specified function.
5273 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5274 LPFUNCDESC *ppFuncDesc)
5276 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5277 const FUNCDESC *internal_funcdesc;
5278 HRESULT hr;
5279 UINT hrefoffset = 0;
5281 TRACE("(%p) index %d\n", This, index);
5283 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5284 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5285 &internal_funcdesc, NULL,
5286 &hrefoffset);
5287 else
5288 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5289 &internal_funcdesc);
5290 if (FAILED(hr))
5292 WARN("description for function %d not found\n", index);
5293 return hr;
5296 hr = TLB_AllocAndInitFuncDesc(
5297 internal_funcdesc,
5298 ppFuncDesc,
5299 This->TypeAttr.typekind == TKIND_DISPATCH);
5301 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5302 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5304 TRACE("-- 0x%08x\n", hr);
5305 return hr;
5308 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5310 VARDESC *dest;
5311 char *buffer;
5312 SIZE_T size = sizeof(*src);
5313 HRESULT hr;
5315 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5316 if (src->varkind == VAR_CONST)
5317 size += sizeof(VARIANT);
5318 size += TLB_SizeElemDesc(&src->elemdescVar);
5320 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5321 if (!dest) return E_OUTOFMEMORY;
5323 *dest = *src;
5324 buffer = (char *)(dest + 1);
5325 if (src->lpstrSchema)
5327 int len;
5328 dest->lpstrSchema = (LPOLESTR)buffer;
5329 len = strlenW(src->lpstrSchema);
5330 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5331 buffer += (len + 1) * sizeof(WCHAR);
5334 if (src->varkind == VAR_CONST)
5336 HRESULT hr;
5338 dest->u.lpvarValue = (VARIANT *)buffer;
5339 *dest->u.lpvarValue = *src->u.lpvarValue;
5340 buffer += sizeof(VARIANT);
5341 VariantInit(dest->u.lpvarValue);
5342 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5343 if (FAILED(hr))
5345 SysFreeString((BSTR)dest_ptr);
5346 return hr;
5349 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5350 if (FAILED(hr))
5352 if (src->varkind == VAR_CONST)
5353 VariantClear(dest->u.lpvarValue);
5354 SysFreeString((BSTR)dest);
5355 return hr;
5357 *dest_ptr = dest;
5358 return S_OK;
5361 /* ITypeInfo::GetVarDesc
5363 * Retrieves a VARDESC structure that describes the specified variable.
5366 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5367 LPVARDESC *ppVarDesc)
5369 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5370 UINT i;
5371 const TLBVarDesc *pVDesc;
5373 TRACE("(%p) index %d\n", This, index);
5375 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5378 if (pVDesc)
5379 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5381 return E_INVALIDARG;
5384 /* ITypeInfo_GetNames
5386 * Retrieves the variable with the specified member ID (or the name of the
5387 * property or method and its parameters) that correspond to the specified
5388 * function ID.
5390 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5391 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5393 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5394 const TLBFuncDesc *pFDesc;
5395 const TLBVarDesc *pVDesc;
5396 int i;
5397 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5398 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5399 if(pFDesc)
5401 /* function found, now return function and parameter names */
5402 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5404 if(!i)
5405 *rgBstrNames=SysAllocString(pFDesc->Name);
5406 else
5407 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5409 *pcNames=i;
5411 else
5413 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5414 if(pVDesc)
5416 *rgBstrNames=SysAllocString(pVDesc->Name);
5417 *pcNames=1;
5419 else
5421 if(This->impltypelist &&
5422 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5423 /* recursive search */
5424 ITypeInfo *pTInfo;
5425 HRESULT result;
5426 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5427 &pTInfo);
5428 if(SUCCEEDED(result))
5430 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5431 ITypeInfo_Release(pTInfo);
5432 return result;
5434 WARN("Could not search inherited interface!\n");
5436 else
5438 WARN("no names found\n");
5440 *pcNames=0;
5441 return TYPE_E_ELEMENTNOTFOUND;
5444 return S_OK;
5448 /* ITypeInfo::GetRefTypeOfImplType
5450 * If a type description describes a COM class, it retrieves the type
5451 * description of the implemented interface types. For an interface,
5452 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5453 * if any exist.
5456 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5457 ITypeInfo2 *iface,
5458 UINT index,
5459 HREFTYPE *pRefType)
5461 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5462 UINT i;
5463 HRESULT hr = S_OK;
5464 const TLBImplType *pImpl = This->impltypelist;
5466 TRACE("(%p) index %d\n", This, index);
5467 if (TRACE_ON(ole)) dump_TypeInfo(This);
5469 if(index==(UINT)-1)
5471 /* only valid on dual interfaces;
5472 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5474 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5476 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5477 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5479 *pRefType = -1;
5481 else
5483 hr = TYPE_E_ELEMENTNOTFOUND;
5486 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5488 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5489 *pRefType = This->pTypeLib->dispatch_href;
5491 else
5493 /* get element n from linked list */
5494 for(i=0; pImpl && i<index; i++)
5496 pImpl = pImpl->next;
5499 if (pImpl)
5500 *pRefType = pImpl->hRef;
5501 else
5502 hr = TYPE_E_ELEMENTNOTFOUND;
5505 if(TRACE_ON(ole))
5507 if(SUCCEEDED(hr))
5508 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5509 else
5510 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5513 return hr;
5516 /* ITypeInfo::GetImplTypeFlags
5518 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5519 * or base interface in a type description.
5521 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5522 UINT index, INT *pImplTypeFlags)
5524 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5525 UINT i;
5526 TLBImplType *pImpl;
5528 TRACE("(%p) index %d\n", This, index);
5529 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5530 i++, pImpl=pImpl->next)
5532 if(i==index && pImpl){
5533 *pImplTypeFlags=pImpl->implflags;
5534 return S_OK;
5536 *pImplTypeFlags=0;
5537 return TYPE_E_ELEMENTNOTFOUND;
5540 /* GetIDsOfNames
5541 * Maps between member names and member IDs, and parameter names and
5542 * parameter IDs.
5544 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5545 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5547 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5548 const TLBFuncDesc *pFDesc;
5549 const TLBVarDesc *pVDesc;
5550 HRESULT ret=S_OK;
5551 UINT i;
5553 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5554 cNames);
5556 /* init out parameters in case of failure */
5557 for (i = 0; i < cNames; i++)
5558 pMemId[i] = MEMBERID_NIL;
5560 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5561 int j;
5562 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5563 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5564 for(i=1; i < cNames; i++){
5565 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5566 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5567 break;
5568 if( j<pFDesc->funcdesc.cParams)
5569 pMemId[i]=j;
5570 else
5571 ret=DISP_E_UNKNOWNNAME;
5573 TRACE("-- 0x%08x\n", ret);
5574 return ret;
5577 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5578 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5579 if(cNames) *pMemId=pVDesc->vardesc.memid;
5580 return ret;
5583 /* not found, see if it can be found in an inherited interface */
5584 if(This->impltypelist) {
5585 /* recursive search */
5586 ITypeInfo *pTInfo;
5587 ret=ITypeInfo_GetRefTypeInfo(iface,
5588 This->impltypelist->hRef, &pTInfo);
5589 if(SUCCEEDED(ret)){
5590 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5591 ITypeInfo_Release(pTInfo);
5592 return ret;
5594 WARN("Could not search inherited interface!\n");
5595 } else
5596 WARN("no names found\n");
5597 return DISP_E_UNKNOWNNAME;
5600 /* ITypeInfo::Invoke
5602 * Invokes a method, or accesses a property of an object, that implements the
5603 * interface described by the type description.
5605 DWORD
5606 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5607 DWORD res;
5609 if (TRACE_ON(ole)) {
5610 int i;
5611 TRACE("Calling %p(",func);
5612 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5613 TRACE(")\n");
5616 switch (callconv) {
5617 case CC_STDCALL:
5619 switch (nrargs) {
5620 case 0:
5621 res = func();
5622 break;
5623 case 1:
5624 res = func(args[0]);
5625 break;
5626 case 2:
5627 res = func(args[0],args[1]);
5628 break;
5629 case 3:
5630 res = func(args[0],args[1],args[2]);
5631 break;
5632 case 4:
5633 res = func(args[0],args[1],args[2],args[3]);
5634 break;
5635 case 5:
5636 res = func(args[0],args[1],args[2],args[3],args[4]);
5637 break;
5638 case 6:
5639 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5640 break;
5641 case 7:
5642 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5643 break;
5644 case 8:
5645 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5646 break;
5647 case 9:
5648 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5649 break;
5650 case 10:
5651 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5652 break;
5653 case 11:
5654 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5655 break;
5656 case 12:
5657 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
5658 break;
5659 case 13:
5660 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
5661 break;
5662 case 14:
5663 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
5664 break;
5665 case 15:
5666 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
5667 break;
5668 case 16:
5669 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
5670 break;
5671 case 17:
5672 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
5673 break;
5674 case 18:
5675 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5676 break;
5677 case 19:
5678 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
5679 break;
5680 case 20:
5681 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
5682 break;
5683 case 21:
5684 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
5685 break;
5686 case 22:
5687 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
5688 break;
5689 case 23:
5690 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
5691 break;
5692 case 24:
5693 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23]);
5694 break;
5695 case 25:
5696 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24]);
5697 break;
5698 case 26:
5699 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25]);
5700 break;
5701 case 27:
5702 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26]);
5703 break;
5704 case 28:
5705 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27]);
5706 break;
5707 case 29:
5708 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28]);
5709 break;
5710 case 30:
5711 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
5712 break;
5713 default:
5714 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5715 res = -1;
5716 break;
5718 break;
5719 default:
5720 FIXME("unsupported calling convention %d\n",callconv);
5721 res = -1;
5722 break;
5724 TRACE("returns %08x\n",res);
5725 return res;
5728 /* The size of the argument on the stack in DWORD units (in all x86 call
5729 * convetions the arguments on the stack are DWORD-aligned)
5731 static int _dispargsize(VARTYPE vt)
5733 switch (vt) {
5734 case VT_I8:
5735 case VT_UI8:
5736 return 8/sizeof(DWORD);
5737 case VT_R8:
5738 return sizeof(double)/sizeof(DWORD);
5739 case VT_DECIMAL:
5740 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5741 case VT_CY:
5742 return sizeof(CY)/sizeof(DWORD);
5743 case VT_DATE:
5744 return sizeof(DATE)/sizeof(DWORD);
5745 case VT_VARIANT:
5746 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5747 case VT_RECORD:
5748 FIXME("VT_RECORD not implemented\n");
5749 return 1;
5750 default:
5751 return 1;
5755 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5757 HRESULT hr = S_OK;
5758 ITypeInfo *tinfo2 = NULL;
5759 TYPEATTR *tattr = NULL;
5761 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5762 if (hr)
5764 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5765 "hr = 0x%08x\n",
5766 tdesc->u.hreftype, hr);
5767 return hr;
5769 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5770 if (hr)
5772 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5773 ITypeInfo_Release(tinfo2);
5774 return hr;
5777 switch (tattr->typekind)
5779 case TKIND_ENUM:
5780 *vt |= VT_I4;
5781 break;
5783 case TKIND_ALIAS:
5784 tdesc = &tattr->tdescAlias;
5785 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5786 break;
5788 case TKIND_INTERFACE:
5789 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5790 *vt |= VT_DISPATCH;
5791 else
5792 *vt |= VT_UNKNOWN;
5793 break;
5795 case TKIND_DISPATCH:
5796 *vt |= VT_DISPATCH;
5797 break;
5799 case TKIND_COCLASS:
5800 *vt |= VT_DISPATCH;
5801 break;
5803 case TKIND_RECORD:
5804 FIXME("TKIND_RECORD unhandled.\n");
5805 hr = E_NOTIMPL;
5806 break;
5808 case TKIND_UNION:
5809 FIXME("TKIND_UNION unhandled.\n");
5810 hr = E_NOTIMPL;
5811 break;
5813 default:
5814 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5815 hr = E_NOTIMPL;
5816 break;
5818 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5819 ITypeInfo_Release(tinfo2);
5820 return hr;
5823 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5825 HRESULT hr = S_OK;
5827 /* enforce only one level of pointer indirection */
5828 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5830 tdesc = tdesc->u.lptdesc;
5832 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5833 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5834 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5835 if ((tdesc->vt == VT_USERDEFINED) ||
5836 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5838 VARTYPE vt_userdefined = 0;
5839 const TYPEDESC *tdesc_userdefined = tdesc;
5840 if (tdesc->vt == VT_PTR)
5842 vt_userdefined = VT_BYREF;
5843 tdesc_userdefined = tdesc->u.lptdesc;
5845 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5846 if ((hr == S_OK) &&
5847 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5848 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5850 *vt |= vt_userdefined;
5851 return S_OK;
5854 *vt = VT_BYREF;
5857 switch (tdesc->vt)
5859 case VT_HRESULT:
5860 *vt |= VT_ERROR;
5861 break;
5862 case VT_USERDEFINED:
5863 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5864 break;
5865 case VT_VOID:
5866 case VT_CARRAY:
5867 case VT_PTR:
5868 case VT_LPSTR:
5869 case VT_LPWSTR:
5870 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5871 hr = DISP_E_BADVARTYPE;
5872 break;
5873 case VT_SAFEARRAY:
5874 *vt |= VT_ARRAY;
5875 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5876 break;
5877 default:
5878 *vt |= tdesc->vt;
5879 break;
5881 return hr;
5884 /***********************************************************************
5885 * DispCallFunc (OLEAUT32.@)
5887 * Invokes a function of the specified calling convention, passing the
5888 * specified arguments and returns the result.
5890 * PARAMS
5891 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5892 * oVft [I] The offset in the vtable. See notes.
5893 * cc [I] Calling convention of the function to call.
5894 * vtReturn [I] The return type of the function.
5895 * cActuals [I] Number of parameters.
5896 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5897 * prgpvarg [I] The arguments to pass.
5898 * pvargResult [O] The return value of the function. Can be NULL.
5900 * RETURNS
5901 * Success: S_OK.
5902 * Failure: HRESULT code.
5904 * NOTES
5905 * The HRESULT return value of this function is not affected by the return
5906 * value of the user supplied function, which is returned in pvargResult.
5908 * If pvInstance is NULL then a non-object function is to be called and oVft
5909 * is the address of the function to call.
5911 * The cc parameter can be one of the following values:
5912 *|CC_FASTCALL
5913 *|CC_CDECL
5914 *|CC_PASCAL
5915 *|CC_STDCALL
5916 *|CC_FPFASTCALL
5917 *|CC_SYSCALL
5918 *|CC_MPWCDECL
5919 *|CC_MPWPASCAL
5922 HRESULT WINAPI
5923 DispCallFunc(
5924 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5925 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5927 int argsize, argspos;
5928 UINT i;
5929 DWORD *args;
5930 HRESULT hres;
5932 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5933 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5934 pvargResult, V_VT(pvargResult));
5936 argsize = 0;
5937 if (pvInstance)
5938 argsize++; /* for This pointer */
5940 for (i=0;i<cActuals;i++)
5942 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5943 dump_Variant(prgpvarg[i]);
5944 argsize += _dispargsize(prgvt[i]);
5946 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5948 argspos = 0;
5949 if (pvInstance)
5951 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5952 argspos++;
5955 for (i=0;i<cActuals;i++)
5957 VARIANT *arg = prgpvarg[i];
5958 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5959 if (prgvt[i] == VT_VARIANT)
5960 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5961 else
5962 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5963 argspos += _dispargsize(prgvt[i]);
5966 if (pvInstance)
5968 FARPROC *vtable = *(FARPROC**)pvInstance;
5969 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5971 else
5972 /* if we aren't invoking an object then the function pointer is stored
5973 * in oVft */
5974 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5976 if (pvargResult && (vtReturn != VT_EMPTY))
5978 TRACE("Method returned 0x%08x\n",hres);
5979 V_VT(pvargResult) = vtReturn;
5980 V_UI4(pvargResult) = hres;
5983 HeapFree(GetProcessHeap(),0,args);
5984 return S_OK;
5987 #define INVBUF_ELEMENT_SIZE \
5988 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5989 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5990 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5991 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5992 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5993 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5994 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5995 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5997 static HRESULT WINAPI ITypeInfo_fnInvoke(
5998 ITypeInfo2 *iface,
5999 VOID *pIUnk,
6000 MEMBERID memid,
6001 UINT16 wFlags,
6002 DISPPARAMS *pDispParams,
6003 VARIANT *pVarResult,
6004 EXCEPINFO *pExcepInfo,
6005 UINT *pArgErr)
6007 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6008 int i;
6009 unsigned int var_index;
6010 TYPEKIND type_kind;
6011 HRESULT hres;
6012 const TLBFuncDesc *pFuncInfo;
6014 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6015 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6018 if (!pDispParams)
6020 ERR("NULL pDispParams not allowed\n");
6021 return E_INVALIDARG;
6024 dump_DispParms(pDispParams);
6026 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6028 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6029 pDispParams->cNamedArgs, pDispParams->cArgs);
6030 return E_INVALIDARG;
6033 /* we do this instead of using GetFuncDesc since it will return a fake
6034 * FUNCDESC for dispinterfaces and we want the real function description */
6035 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6036 if ((memid == pFuncInfo->funcdesc.memid) &&
6037 (wFlags & pFuncInfo->funcdesc.invkind))
6038 break;
6040 if (pFuncInfo) {
6041 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6043 if (TRACE_ON(ole))
6045 TRACE("invoking:\n");
6046 dump_TLBFuncDescOne(pFuncInfo);
6049 switch (func_desc->funckind) {
6050 case FUNC_PUREVIRTUAL:
6051 case FUNC_VIRTUAL: {
6052 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6053 VARIANT varresult;
6054 VARIANT retval; /* pointer for storing byref retvals in */
6055 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6056 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6057 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6058 UINT cNamedArgs = pDispParams->cNamedArgs;
6059 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6061 hres = S_OK;
6063 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6065 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6067 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6068 hres = DISP_E_PARAMNOTFOUND;
6069 goto func_fail;
6071 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6072 cNamedArgs--;
6073 rgdispidNamedArgs++;
6076 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6078 ERR("functions with the vararg attribute do not support named arguments\n");
6079 hres = DISP_E_NONAMEDARGS;
6080 goto func_fail;
6083 for (i = 0; i < func_desc->cParams; i++)
6085 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6086 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6087 if (FAILED(hres))
6088 goto func_fail;
6091 TRACE("changing args\n");
6092 for (i = 0; i < func_desc->cParams; i++)
6094 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6095 VARIANTARG *src_arg;
6097 if (cNamedArgs)
6099 USHORT j;
6100 src_arg = NULL;
6101 for (j = 0; j < cNamedArgs; j++)
6102 if (rgdispidNamedArgs[j] == i)
6104 src_arg = &pDispParams->rgvarg[j];
6105 break;
6108 else
6109 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
6111 if (wParamFlags & PARAMFLAG_FRETVAL)
6113 /* under most conditions the caller is not allowed to
6114 * pass in a dispparam arg in the index of what would be
6115 * the retval parameter. however, there is an exception
6116 * where the extra parameter is used in an extra
6117 * IDispatch::Invoke below */
6118 if ((i < pDispParams->cArgs) &&
6119 ((func_desc->cParams != 1) || !pVarResult ||
6120 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6122 hres = DISP_E_BADPARAMCOUNT;
6123 break;
6126 /* note: this check is placed so that if the caller passes
6127 * in a VARIANTARG for the retval we just ignore it, like
6128 * native does */
6129 if (i == func_desc->cParams - 1)
6131 VARIANTARG *arg;
6132 arg = prgpvarg[i] = &rgvarg[i];
6133 memset(arg, 0, sizeof(*arg));
6134 V_VT(arg) = rgvt[i];
6135 memset(&retval, 0, sizeof(retval));
6136 V_BYREF(arg) = &retval;
6138 else
6140 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6141 hres = E_UNEXPECTED;
6142 break;
6145 else if (src_arg)
6147 dump_Variant(src_arg);
6149 if (rgvt[i] == VT_VARIANT)
6150 hres = VariantCopy(&rgvarg[i], src_arg);
6151 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6153 if (rgvt[i] == V_VT(src_arg))
6154 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6155 else
6157 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6158 hres = VariantCopy(&missing_arg[i], src_arg);
6159 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6161 V_VT(&rgvarg[i]) = rgvt[i];
6163 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6165 SAFEARRAY *a;
6166 SAFEARRAYBOUND bound;
6167 VARIANT *v;
6168 LONG j;
6169 bound.lLbound = 0;
6170 bound.cElements = pDispParams->cArgs-i;
6171 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6173 ERR("SafeArrayCreate failed\n");
6174 break;
6176 hres = SafeArrayAccessData(a, (LPVOID)&v);
6177 if (hres != S_OK)
6179 ERR("SafeArrayAccessData failed with %x\n", hres);
6180 break;
6182 for (j = 0; j < bound.cElements; j++)
6183 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6184 hres = SafeArrayUnaccessData(a);
6185 if (hres != S_OK)
6187 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6188 break;
6190 V_ARRAY(&rgvarg[i]) = a;
6191 V_VT(&rgvarg[i]) = rgvt[i];
6193 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6195 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6196 V_VT(&missing_arg[i]) = V_VT(src_arg);
6197 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6198 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6199 V_VT(&rgvarg[i]) = rgvt[i];
6201 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6203 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6204 V_VT(&rgvarg[i]) = rgvt[i];
6206 else
6208 /* FIXME: this doesn't work for VT_BYREF arguments if
6209 * they are not the same type as in the paramdesc */
6210 V_VT(&rgvarg[i]) = V_VT(src_arg);
6211 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6212 V_VT(&rgvarg[i]) = rgvt[i];
6215 if (FAILED(hres))
6217 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6218 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6219 debugstr_VT(src_arg), debugstr_VF(src_arg));
6220 break;
6222 prgpvarg[i] = &rgvarg[i];
6224 else if (wParamFlags & PARAMFLAG_FOPT)
6226 VARIANTARG *arg;
6227 arg = prgpvarg[i] = &rgvarg[i];
6228 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6230 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6231 if (FAILED(hres))
6232 break;
6234 else
6236 VARIANTARG *missing_arg;
6237 /* if the function wants a pointer to a variant then
6238 * set that up, otherwise just pass the VT_ERROR in
6239 * the argument by value */
6240 if (rgvt[i] & VT_BYREF)
6242 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6243 V_VT(arg) = VT_VARIANT | VT_BYREF;
6244 V_VARIANTREF(arg) = missing_arg;
6246 else
6247 missing_arg = arg;
6248 V_VT(missing_arg) = VT_ERROR;
6249 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6252 else
6254 hres = DISP_E_BADPARAMCOUNT;
6255 break;
6258 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6260 /* VT_VOID is a special case for return types, so it is not
6261 * handled in the general function */
6262 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6263 V_VT(&varresult) = VT_EMPTY;
6264 else
6266 V_VT(&varresult) = 0;
6267 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6268 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6271 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6272 V_VT(&varresult), func_desc->cParams, rgvt,
6273 prgpvarg, &varresult);
6275 for (i = 0; i < func_desc->cParams; i++)
6277 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6278 if (wParamFlags & PARAMFLAG_FRETVAL)
6280 if (TRACE_ON(ole))
6282 TRACE("[retval] value: ");
6283 dump_Variant(prgpvarg[i]);
6286 if (pVarResult)
6288 VariantInit(pVarResult);
6289 /* deref return value */
6290 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6293 /* free data stored in varresult. Note that
6294 * VariantClear doesn't do what we want because we are
6295 * working with byref types. */
6296 /* FIXME: clear safearrays, bstrs, records and
6297 * variants here too */
6298 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6299 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6301 if(*V_UNKNOWNREF(prgpvarg[i]))
6302 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6304 break;
6306 else if (i < pDispParams->cArgs)
6308 if (wParamFlags & PARAMFLAG_FOUT)
6310 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6312 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6313 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6315 if (FAILED(hres))
6317 ERR("failed to convert param %d to vt %d\n", i,
6318 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6319 break;
6322 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6323 func_desc->cParamsOpt < 0 &&
6324 i == func_desc->cParams-1)
6326 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6327 LONG j, ubound;
6328 VARIANT *v;
6329 hres = SafeArrayGetUBound(a, 1, &ubound);
6330 if (hres != S_OK)
6332 ERR("SafeArrayGetUBound failed with %x\n", hres);
6333 break;
6335 hres = SafeArrayAccessData(a, (LPVOID)&v);
6336 if (hres != S_OK)
6338 ERR("SafeArrayAccessData failed with %x\n", hres);
6339 break;
6341 for (j = 0; j <= ubound; j++)
6342 VariantClear(&v[j]);
6343 hres = SafeArrayUnaccessData(a);
6344 if (hres != S_OK)
6346 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6347 break;
6350 VariantClear(&rgvarg[i]);
6352 else if (wParamFlags & PARAMFLAG_FOPT)
6354 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6355 VariantClear(&rgvarg[i]);
6359 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6361 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6362 hres = DISP_E_EXCEPTION;
6363 if (pExcepInfo)
6365 IErrorInfo *pErrorInfo;
6366 pExcepInfo->scode = V_ERROR(&varresult);
6367 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6369 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6370 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6371 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6372 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6374 IErrorInfo_Release(pErrorInfo);
6378 if (V_VT(&varresult) != VT_ERROR)
6380 TRACE("varresult value: ");
6381 dump_Variant(&varresult);
6383 if (pVarResult)
6385 VariantClear(pVarResult);
6386 *pVarResult = varresult;
6388 else
6389 VariantClear(&varresult);
6392 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6393 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6394 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6395 (pDispParams->cArgs != 0))
6397 if (V_VT(pVarResult) == VT_DISPATCH)
6399 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6400 /* Note: not VariantClear; we still need the dispatch
6401 * pointer to be valid */
6402 VariantInit(pVarResult);
6403 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6404 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6405 pDispParams, pVarResult, pExcepInfo, pArgErr);
6406 IDispatch_Release(pDispatch);
6408 else
6410 VariantClear(pVarResult);
6411 hres = DISP_E_NOTACOLLECTION;
6415 func_fail:
6416 HeapFree(GetProcessHeap(), 0, buffer);
6417 break;
6419 case FUNC_DISPATCH: {
6420 IDispatch *disp;
6422 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6423 if (SUCCEEDED(hres)) {
6424 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6425 hres = IDispatch_Invoke(
6426 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6427 pVarResult,pExcepInfo,pArgErr
6429 if (FAILED(hres))
6430 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6431 IDispatch_Release(disp);
6432 } else
6433 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6434 break;
6436 default:
6437 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6438 hres = E_FAIL;
6439 break;
6442 TRACE("-- 0x%08x\n", hres);
6443 return hres;
6445 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6446 VARDESC *var_desc;
6448 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6449 if(FAILED(hres)) return hres;
6451 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6452 dump_VARDESC(var_desc);
6453 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6454 return E_NOTIMPL;
6457 /* not found, look for it in inherited interfaces */
6458 ITypeInfo2_GetTypeKind(iface, &type_kind);
6459 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6460 if(This->impltypelist) {
6461 /* recursive search */
6462 ITypeInfo *pTInfo;
6463 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6464 if(SUCCEEDED(hres)){
6465 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6466 ITypeInfo_Release(pTInfo);
6467 return hres;
6469 WARN("Could not search inherited interface!\n");
6472 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6473 return DISP_E_MEMBERNOTFOUND;
6476 /* ITypeInfo::GetDocumentation
6478 * Retrieves the documentation string, the complete Help file name and path,
6479 * and the context ID for the Help topic for a specified type description.
6481 * (Can be tested by the Visual Basic Editor in Word for instance.)
6483 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6484 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6485 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6487 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6488 const TLBFuncDesc *pFDesc;
6489 const TLBVarDesc *pVDesc;
6490 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6491 " HelpContext(%p) HelpFile(%p)\n",
6492 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6493 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6494 if(pBstrName)
6495 *pBstrName=SysAllocString(This->Name);
6496 if(pBstrDocString)
6497 *pBstrDocString=SysAllocString(This->DocString);
6498 if(pdwHelpContext)
6499 *pdwHelpContext=This->dwHelpContext;
6500 if(pBstrHelpFile)
6501 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6502 return S_OK;
6503 }else {/* for a member */
6504 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6505 if(pFDesc->funcdesc.memid==memid){
6506 if(pBstrName)
6507 *pBstrName = SysAllocString(pFDesc->Name);
6508 if(pBstrDocString)
6509 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6510 if(pdwHelpContext)
6511 *pdwHelpContext=pFDesc->helpcontext;
6512 return S_OK;
6514 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6515 if(pVDesc->vardesc.memid==memid){
6516 if(pBstrName)
6517 *pBstrName = SysAllocString(pVDesc->Name);
6518 if(pBstrDocString)
6519 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6520 if(pdwHelpContext)
6521 *pdwHelpContext=pVDesc->HelpContext;
6522 return S_OK;
6526 if(This->impltypelist &&
6527 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6528 /* recursive search */
6529 ITypeInfo *pTInfo;
6530 HRESULT result;
6531 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6532 &pTInfo);
6533 if(SUCCEEDED(result)) {
6534 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6535 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6536 ITypeInfo_Release(pTInfo);
6537 return result;
6539 WARN("Could not search inherited interface!\n");
6542 WARN("member %d not found\n", memid);
6543 return TYPE_E_ELEMENTNOTFOUND;
6546 /* ITypeInfo::GetDllEntry
6548 * Retrieves a description or specification of an entry point for a function
6549 * in a DLL.
6551 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6552 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6553 WORD *pwOrdinal)
6555 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6556 const TLBFuncDesc *pFDesc;
6558 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6560 if (pBstrDllName) *pBstrDllName = NULL;
6561 if (pBstrName) *pBstrName = NULL;
6562 if (pwOrdinal) *pwOrdinal = 0;
6564 if (This->TypeAttr.typekind != TKIND_MODULE)
6565 return TYPE_E_BADMODULEKIND;
6567 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6568 if(pFDesc->funcdesc.memid==memid){
6569 dump_TypeInfo(This);
6570 if (TRACE_ON(ole))
6571 dump_TLBFuncDescOne(pFDesc);
6573 if (pBstrDllName)
6574 *pBstrDllName = SysAllocString(This->DllName);
6576 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6577 if (pBstrName)
6578 *pBstrName = SysAllocString(pFDesc->Entry);
6579 if (pwOrdinal)
6580 *pwOrdinal = -1;
6581 return S_OK;
6583 if (pBstrName)
6584 *pBstrName = NULL;
6585 if (pwOrdinal)
6586 *pwOrdinal = (DWORD)pFDesc->Entry;
6587 return S_OK;
6589 return TYPE_E_ELEMENTNOTFOUND;
6592 /* internal function to make the inherited interfaces' methods appear
6593 * part of the interface */
6594 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6595 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6597 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6598 HRESULT hr;
6600 TRACE("%p, 0x%x\n", iface, *hRefType);
6602 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6604 ITypeInfo *pSubTypeInfo;
6606 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6607 if (FAILED(hr))
6608 return hr;
6610 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6611 hRefType, ppTInfo);
6612 ITypeInfo_Release(pSubTypeInfo);
6613 if (SUCCEEDED(hr))
6614 return hr;
6616 *hRefType -= DISPATCH_HREF_OFFSET;
6618 if (!(*hRefType & DISPATCH_HREF_MASK))
6619 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6620 else
6621 return E_FAIL;
6624 /* ITypeInfo::GetRefTypeInfo
6626 * If a type description references other type descriptions, it retrieves
6627 * the referenced type descriptions.
6629 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6630 ITypeInfo2 *iface,
6631 HREFTYPE hRefType,
6632 ITypeInfo **ppTInfo)
6634 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6635 HRESULT result = E_FAIL;
6637 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6639 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6640 ITypeInfo_AddRef(*ppTInfo);
6641 result = S_OK;
6643 else if (hRefType == -1 &&
6644 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6645 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6647 /* when we meet a DUAL dispinterface, we must create the interface
6648 * version of it.
6650 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6653 /* the interface version contains the same information as the dispinterface
6654 * copy the contents of the structs.
6656 *pTypeInfoImpl = *This;
6657 pTypeInfoImpl->ref = 0;
6659 /* change the type to interface */
6660 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6662 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6664 /* we use data structures from This, so we need to keep a reference
6665 * to it to stop it being destroyed and signal to the new instance to
6666 * not free its data structures when it is destroyed */
6667 pTypeInfoImpl->no_free_data = TRUE;
6668 pTypeInfoImpl->next = This;
6669 ITypeInfo_AddRef((ITypeInfo*) This);
6671 ITypeInfo_AddRef(*ppTInfo);
6673 result = S_OK;
6675 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6676 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6677 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6679 HREFTYPE href_dispatch = hRefType;
6680 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6681 } else {
6682 TLBRefType *ref_type;
6683 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6685 if(ref_type->reference == hRefType)
6686 break;
6688 if(&ref_type->entry == &This->pTypeLib->ref_list)
6690 FIXME("Can't find pRefType for ref %x\n", hRefType);
6691 goto end;
6693 if(hRefType != -1) {
6694 ITypeLib *pTLib = NULL;
6696 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6697 UINT Index;
6698 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6699 } else {
6700 if(ref_type->pImpTLInfo->pImpTypeLib) {
6701 TRACE("typeinfo in imported typelib that is already loaded\n");
6702 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6703 ITypeLib2_AddRef(pTLib);
6704 result = S_OK;
6705 } else {
6706 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6707 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6708 ref_type->pImpTLInfo->wVersionMajor,
6709 ref_type->pImpTLInfo->wVersionMinor,
6710 ref_type->pImpTLInfo->lcid,
6711 &pTLib);
6713 if(FAILED(result)) {
6714 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6715 result=LoadTypeLib(libnam, &pTLib);
6716 SysFreeString(libnam);
6718 if(SUCCEEDED(result)) {
6719 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6720 ITypeLib2_AddRef(pTLib);
6724 if(SUCCEEDED(result)) {
6725 if(ref_type->index == TLB_REF_USE_GUID)
6726 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6727 &ref_type->guid,
6728 ppTInfo);
6729 else
6730 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6731 ppTInfo);
6733 if (pTLib != NULL)
6734 ITypeLib2_Release(pTLib);
6738 end:
6739 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6740 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6741 return result;
6744 /* ITypeInfo::AddressOfMember
6746 * Retrieves the addresses of static functions or variables, such as those
6747 * defined in a DLL.
6749 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6750 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6752 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6753 HRESULT hr;
6754 BSTR dll, entry;
6755 WORD ordinal;
6756 HMODULE module;
6758 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6760 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6761 if (FAILED(hr))
6762 return hr;
6764 module = LoadLibraryW(dll);
6765 if (!module)
6767 ERR("couldn't load %s\n", debugstr_w(dll));
6768 SysFreeString(dll);
6769 SysFreeString(entry);
6770 return STG_E_FILENOTFOUND;
6772 /* FIXME: store library somewhere where we can free it */
6774 if (entry)
6776 LPSTR entryA;
6777 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6778 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6779 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6781 *ppv = GetProcAddress(module, entryA);
6782 if (!*ppv)
6783 ERR("function not found %s\n", debugstr_a(entryA));
6785 HeapFree(GetProcessHeap(), 0, entryA);
6787 else
6789 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6790 if (!*ppv)
6791 ERR("function not found %d\n", ordinal);
6794 SysFreeString(dll);
6795 SysFreeString(entry);
6797 if (!*ppv)
6798 return TYPE_E_DLLFUNCTIONNOTFOUND;
6800 return S_OK;
6803 /* ITypeInfo::CreateInstance
6805 * Creates a new instance of a type that describes a component object class
6806 * (coclass).
6808 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6809 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6811 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6812 HRESULT hr;
6813 TYPEATTR *pTA;
6815 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6817 *ppvObj = NULL;
6819 if(pOuterUnk)
6821 WARN("Not able to aggregate\n");
6822 return CLASS_E_NOAGGREGATION;
6825 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6826 if(FAILED(hr)) return hr;
6828 if(pTA->typekind != TKIND_COCLASS)
6830 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6831 hr = E_INVALIDARG;
6832 goto end;
6835 hr = S_FALSE;
6836 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6838 IUnknown *pUnk;
6839 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6840 TRACE("GetActiveObject rets %08x\n", hr);
6841 if(hr == S_OK)
6843 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6844 IUnknown_Release(pUnk);
6848 if(hr != S_OK)
6849 hr = CoCreateInstance(&pTA->guid, NULL,
6850 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6851 riid, ppvObj);
6853 end:
6854 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6855 return hr;
6858 /* ITypeInfo::GetMops
6860 * Retrieves marshalling information.
6862 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6863 BSTR *pBstrMops)
6865 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6866 FIXME("(%p) stub!\n", This);
6867 return S_OK;
6870 /* ITypeInfo::GetContainingTypeLib
6872 * Retrieves the containing type library and the index of the type description
6873 * within that type library.
6875 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6876 ITypeLib * *ppTLib, UINT *pIndex)
6878 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6880 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6881 if (pIndex) {
6882 *pIndex=This->index;
6883 TRACE("returning pIndex=%d\n", *pIndex);
6886 if (ppTLib) {
6887 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6888 ITypeLib2_AddRef(*ppTLib);
6889 TRACE("returning ppTLib=%p\n", *ppTLib);
6892 return S_OK;
6895 /* ITypeInfo::ReleaseTypeAttr
6897 * Releases a TYPEATTR previously returned by GetTypeAttr.
6900 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6901 TYPEATTR* pTypeAttr)
6903 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6904 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6905 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6908 /* ITypeInfo::ReleaseFuncDesc
6910 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6912 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6913 ITypeInfo2 *iface,
6914 FUNCDESC *pFuncDesc)
6916 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6917 SHORT i;
6919 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6921 for (i = 0; i < pFuncDesc->cParams; i++)
6922 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6923 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6925 SysFreeString((BSTR)pFuncDesc);
6928 /* ITypeInfo::ReleaseVarDesc
6930 * Releases a VARDESC previously returned by GetVarDesc.
6932 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6933 VARDESC *pVarDesc)
6935 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6936 TRACE("(%p)->(%p)\n", This, pVarDesc);
6938 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6939 if (pVarDesc->varkind == VAR_CONST)
6940 VariantClear(pVarDesc->u.lpvarValue);
6941 SysFreeString((BSTR)pVarDesc);
6944 /* ITypeInfo2::GetTypeKind
6946 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6949 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6950 TYPEKIND *pTypeKind)
6952 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6953 *pTypeKind=This->TypeAttr.typekind;
6954 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6955 return S_OK;
6958 /* ITypeInfo2::GetTypeFlags
6960 * Returns the type flags without any allocations. This returns a DWORD type
6961 * flag, which expands the type flags without growing the TYPEATTR (type
6962 * attribute).
6965 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6967 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6968 *pTypeFlags=This->TypeAttr.wTypeFlags;
6969 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6970 return S_OK;
6973 /* ITypeInfo2::GetFuncIndexOfMemId
6974 * Binds to a specific member based on a known DISPID, where the member name
6975 * is not known (for example, when binding to a default member).
6978 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6979 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6981 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6982 const TLBFuncDesc *pFuncInfo;
6983 int i;
6984 HRESULT result;
6986 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6987 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6988 break;
6989 if(pFuncInfo) {
6990 *pFuncIndex = i;
6991 result = S_OK;
6992 } else
6993 result = TYPE_E_ELEMENTNOTFOUND;
6995 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6996 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6997 return result;
7000 /* TypeInfo2::GetVarIndexOfMemId
7002 * Binds to a specific member based on a known DISPID, where the member name
7003 * is not known (for example, when binding to a default member).
7006 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7007 MEMBERID memid, UINT *pVarIndex)
7009 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7010 TLBVarDesc *pVarInfo;
7011 int i;
7012 HRESULT result;
7013 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7014 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7016 if(pVarInfo) {
7017 *pVarIndex = i;
7018 result = S_OK;
7019 } else
7020 result = TYPE_E_ELEMENTNOTFOUND;
7022 TRACE("(%p) memid 0x%08x -> %s\n", This,
7023 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7024 return result;
7027 /* ITypeInfo2::GetCustData
7029 * Gets the custom data
7031 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7032 ITypeInfo2 * iface,
7033 REFGUID guid,
7034 VARIANT *pVarVal)
7036 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7037 TLBCustData *pCData;
7039 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7040 if( IsEqualIID(guid, &pCData->guid)) break;
7042 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7044 if(pCData)
7046 VariantInit( pVarVal);
7047 VariantCopy( pVarVal, &pCData->data);
7048 return S_OK;
7050 return E_INVALIDARG; /* FIXME: correct? */
7053 /* ITypeInfo2::GetFuncCustData
7055 * Gets the custom data
7057 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7058 ITypeInfo2 * iface,
7059 UINT index,
7060 REFGUID guid,
7061 VARIANT *pVarVal)
7063 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7064 TLBCustData *pCData=NULL;
7065 TLBFuncDesc * pFDesc;
7066 UINT i;
7067 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7068 pFDesc=pFDesc->next);
7070 if(pFDesc)
7071 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7072 if( IsEqualIID(guid, &pCData->guid)) break;
7074 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7076 if(pCData){
7077 VariantInit( pVarVal);
7078 VariantCopy( pVarVal, &pCData->data);
7079 return S_OK;
7081 return E_INVALIDARG; /* FIXME: correct? */
7084 /* ITypeInfo2::GetParamCustData
7086 * Gets the custom data
7088 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7089 ITypeInfo2 * iface,
7090 UINT indexFunc,
7091 UINT indexParam,
7092 REFGUID guid,
7093 VARIANT *pVarVal)
7095 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7096 TLBCustData *pCData=NULL;
7097 TLBFuncDesc * pFDesc;
7098 UINT i;
7100 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7102 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7103 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7104 pCData = pCData->next)
7105 if( IsEqualIID(guid, &pCData->guid)) break;
7107 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7109 if(pCData)
7111 VariantInit( pVarVal);
7112 VariantCopy( pVarVal, &pCData->data);
7113 return S_OK;
7115 return E_INVALIDARG; /* FIXME: correct? */
7118 /* ITypeInfo2::GetVarCustData
7120 * Gets the custom data
7122 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7123 ITypeInfo2 * iface,
7124 UINT index,
7125 REFGUID guid,
7126 VARIANT *pVarVal)
7128 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7129 TLBCustData *pCData=NULL;
7130 TLBVarDesc * pVDesc;
7131 UINT i;
7133 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7135 if(pVDesc)
7137 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7139 if( IsEqualIID(guid, &pCData->guid)) break;
7143 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7145 if(pCData)
7147 VariantInit( pVarVal);
7148 VariantCopy( pVarVal, &pCData->data);
7149 return S_OK;
7151 return E_INVALIDARG; /* FIXME: correct? */
7154 /* ITypeInfo2::GetImplCustData
7156 * Gets the custom data
7158 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7159 ITypeInfo2 * iface,
7160 UINT index,
7161 REFGUID guid,
7162 VARIANT *pVarVal)
7164 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7165 TLBCustData *pCData=NULL;
7166 TLBImplType * pRDesc;
7167 UINT i;
7169 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7171 if(pRDesc)
7173 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7175 if( IsEqualIID(guid, &pCData->guid)) break;
7179 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7181 if(pCData)
7183 VariantInit( pVarVal);
7184 VariantCopy( pVarVal, &pCData->data);
7185 return S_OK;
7187 return E_INVALIDARG; /* FIXME: correct? */
7190 /* ITypeInfo2::GetDocumentation2
7192 * Retrieves the documentation string, the complete Help file name and path,
7193 * the localization context to use, and the context ID for the library Help
7194 * topic in the Help file.
7197 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7198 ITypeInfo2 * iface,
7199 MEMBERID memid,
7200 LCID lcid,
7201 BSTR *pbstrHelpString,
7202 DWORD *pdwHelpStringContext,
7203 BSTR *pbstrHelpStringDll)
7205 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7206 const TLBFuncDesc *pFDesc;
7207 const TLBVarDesc *pVDesc;
7208 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7209 "HelpStringContext(%p) HelpStringDll(%p)\n",
7210 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7211 pbstrHelpStringDll );
7212 /* the help string should be obtained from the helpstringdll,
7213 * using the _DLLGetDocumentation function, based on the supplied
7214 * lcid. Nice to do sometime...
7216 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7217 if(pbstrHelpString)
7218 *pbstrHelpString=SysAllocString(This->Name);
7219 if(pdwHelpStringContext)
7220 *pdwHelpStringContext=This->dwHelpStringContext;
7221 if(pbstrHelpStringDll)
7222 *pbstrHelpStringDll=
7223 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7224 return S_OK;
7225 }else {/* for a member */
7226 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7227 if(pFDesc->funcdesc.memid==memid){
7228 if(pbstrHelpString)
7229 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7230 if(pdwHelpStringContext)
7231 *pdwHelpStringContext=pFDesc->HelpStringContext;
7232 if(pbstrHelpStringDll)
7233 *pbstrHelpStringDll=
7234 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7235 return S_OK;
7237 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7238 if(pVDesc->vardesc.memid==memid){
7239 if(pbstrHelpString)
7240 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7241 if(pdwHelpStringContext)
7242 *pdwHelpStringContext=pVDesc->HelpStringContext;
7243 if(pbstrHelpStringDll)
7244 *pbstrHelpStringDll=
7245 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7246 return S_OK;
7249 return TYPE_E_ELEMENTNOTFOUND;
7252 /* ITypeInfo2::GetAllCustData
7254 * Gets all custom data items for the Type info.
7257 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7258 ITypeInfo2 * iface,
7259 CUSTDATA *pCustData)
7261 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7262 TLBCustData *pCData;
7263 int i;
7265 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7267 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7268 if(pCustData->prgCustData ){
7269 pCustData->cCustData=This->ctCustData;
7270 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7271 pCustData->prgCustData[i].guid=pCData->guid;
7272 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7274 }else{
7275 ERR(" OUT OF MEMORY!\n");
7276 return E_OUTOFMEMORY;
7278 return S_OK;
7281 /* ITypeInfo2::GetAllFuncCustData
7283 * Gets all custom data items for the specified Function
7286 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7287 ITypeInfo2 * iface,
7288 UINT index,
7289 CUSTDATA *pCustData)
7291 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7292 TLBCustData *pCData;
7293 TLBFuncDesc * pFDesc;
7294 UINT i;
7295 TRACE("(%p) index %d\n", This, index);
7296 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7297 pFDesc=pFDesc->next)
7299 if(pFDesc){
7300 pCustData->prgCustData =
7301 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7302 if(pCustData->prgCustData ){
7303 pCustData->cCustData=pFDesc->ctCustData;
7304 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7305 pCData = pCData->next){
7306 pCustData->prgCustData[i].guid=pCData->guid;
7307 VariantCopy(& pCustData->prgCustData[i].varValue,
7308 & pCData->data);
7310 }else{
7311 ERR(" OUT OF MEMORY!\n");
7312 return E_OUTOFMEMORY;
7314 return S_OK;
7316 return TYPE_E_ELEMENTNOTFOUND;
7319 /* ITypeInfo2::GetAllParamCustData
7321 * Gets all custom data items for the Functions
7324 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7325 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7327 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7328 TLBCustData *pCData=NULL;
7329 TLBFuncDesc * pFDesc;
7330 UINT i;
7331 TRACE("(%p) index %d\n", This, indexFunc);
7332 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7333 pFDesc=pFDesc->next)
7335 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7336 pCustData->prgCustData =
7337 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7338 sizeof(CUSTDATAITEM));
7339 if(pCustData->prgCustData ){
7340 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7341 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7342 pCData; i++, pCData = pCData->next){
7343 pCustData->prgCustData[i].guid=pCData->guid;
7344 VariantCopy(& pCustData->prgCustData[i].varValue,
7345 & pCData->data);
7347 }else{
7348 ERR(" OUT OF MEMORY!\n");
7349 return E_OUTOFMEMORY;
7351 return S_OK;
7353 return TYPE_E_ELEMENTNOTFOUND;
7356 /* ITypeInfo2::GetAllVarCustData
7358 * Gets all custom data items for the specified Variable
7361 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7362 UINT index, CUSTDATA *pCustData)
7364 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7365 TLBCustData *pCData;
7366 TLBVarDesc * pVDesc;
7367 UINT i;
7368 TRACE("(%p) index %d\n", This, index);
7369 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7370 pVDesc=pVDesc->next)
7372 if(pVDesc){
7373 pCustData->prgCustData =
7374 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7375 if(pCustData->prgCustData ){
7376 pCustData->cCustData=pVDesc->ctCustData;
7377 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7378 pCData = pCData->next){
7379 pCustData->prgCustData[i].guid=pCData->guid;
7380 VariantCopy(& pCustData->prgCustData[i].varValue,
7381 & pCData->data);
7383 }else{
7384 ERR(" OUT OF MEMORY!\n");
7385 return E_OUTOFMEMORY;
7387 return S_OK;
7389 return TYPE_E_ELEMENTNOTFOUND;
7392 /* ITypeInfo2::GetAllImplCustData
7394 * Gets all custom data items for the specified implementation type
7397 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7398 ITypeInfo2 * iface,
7399 UINT index,
7400 CUSTDATA *pCustData)
7402 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7403 TLBCustData *pCData;
7404 TLBImplType * pRDesc;
7405 UINT i;
7406 TRACE("(%p) index %d\n", This, index);
7407 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7408 pRDesc=pRDesc->next)
7410 if(pRDesc){
7411 pCustData->prgCustData =
7412 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7413 if(pCustData->prgCustData ){
7414 pCustData->cCustData=pRDesc->ctCustData;
7415 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7416 pCData = pCData->next){
7417 pCustData->prgCustData[i].guid=pCData->guid;
7418 VariantCopy(& pCustData->prgCustData[i].varValue,
7419 & pCData->data);
7421 }else{
7422 ERR(" OUT OF MEMORY!\n");
7423 return E_OUTOFMEMORY;
7425 return S_OK;
7427 return TYPE_E_ELEMENTNOTFOUND;
7430 static const ITypeInfo2Vtbl tinfvt =
7433 ITypeInfo_fnQueryInterface,
7434 ITypeInfo_fnAddRef,
7435 ITypeInfo_fnRelease,
7437 ITypeInfo_fnGetTypeAttr,
7438 ITypeInfo_fnGetTypeComp,
7439 ITypeInfo_fnGetFuncDesc,
7440 ITypeInfo_fnGetVarDesc,
7441 ITypeInfo_fnGetNames,
7442 ITypeInfo_fnGetRefTypeOfImplType,
7443 ITypeInfo_fnGetImplTypeFlags,
7444 ITypeInfo_fnGetIDsOfNames,
7445 ITypeInfo_fnInvoke,
7446 ITypeInfo_fnGetDocumentation,
7447 ITypeInfo_fnGetDllEntry,
7448 ITypeInfo_fnGetRefTypeInfo,
7449 ITypeInfo_fnAddressOfMember,
7450 ITypeInfo_fnCreateInstance,
7451 ITypeInfo_fnGetMops,
7452 ITypeInfo_fnGetContainingTypeLib,
7453 ITypeInfo_fnReleaseTypeAttr,
7454 ITypeInfo_fnReleaseFuncDesc,
7455 ITypeInfo_fnReleaseVarDesc,
7457 ITypeInfo2_fnGetTypeKind,
7458 ITypeInfo2_fnGetTypeFlags,
7459 ITypeInfo2_fnGetFuncIndexOfMemId,
7460 ITypeInfo2_fnGetVarIndexOfMemId,
7461 ITypeInfo2_fnGetCustData,
7462 ITypeInfo2_fnGetFuncCustData,
7463 ITypeInfo2_fnGetParamCustData,
7464 ITypeInfo2_fnGetVarCustData,
7465 ITypeInfo2_fnGetImplTypeCustData,
7466 ITypeInfo2_fnGetDocumentation2,
7467 ITypeInfo2_fnGetAllCustData,
7468 ITypeInfo2_fnGetAllFuncCustData,
7469 ITypeInfo2_fnGetAllParamCustData,
7470 ITypeInfo2_fnGetAllVarCustData,
7471 ITypeInfo2_fnGetAllImplTypeCustData,
7474 /******************************************************************************
7475 * CreateDispTypeInfo [OLEAUT32.31]
7477 * Build type information for an object so it can be called through an
7478 * IDispatch interface.
7480 * RETURNS
7481 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7482 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7484 * NOTES
7485 * This call allows an objects methods to be accessed through IDispatch, by
7486 * building an ITypeInfo object that IDispatch can use to call through.
7488 HRESULT WINAPI CreateDispTypeInfo(
7489 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7490 LCID lcid, /* [I] Locale Id */
7491 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7493 ITypeInfoImpl *pTIClass, *pTIIface;
7494 ITypeLibImpl *pTypeLibImpl;
7495 unsigned int param, func;
7496 TLBFuncDesc **ppFuncDesc;
7497 TLBRefType *ref;
7499 TRACE("\n");
7500 pTypeLibImpl = TypeLibImpl_Constructor();
7501 if (!pTypeLibImpl) return E_FAIL;
7503 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7504 pTIIface->pTypeLib = pTypeLibImpl;
7505 pTIIface->index = 0;
7506 pTIIface->Name = NULL;
7507 pTIIface->dwHelpContext = -1;
7508 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7509 pTIIface->TypeAttr.lcid = lcid;
7510 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7511 pTIIface->TypeAttr.wMajorVerNum = 0;
7512 pTIIface->TypeAttr.wMinorVerNum = 0;
7513 pTIIface->TypeAttr.cbAlignment = 2;
7514 pTIIface->TypeAttr.cbSizeInstance = -1;
7515 pTIIface->TypeAttr.cbSizeVft = -1;
7516 pTIIface->TypeAttr.cFuncs = 0;
7517 pTIIface->TypeAttr.cImplTypes = 0;
7518 pTIIface->TypeAttr.cVars = 0;
7519 pTIIface->TypeAttr.wTypeFlags = 0;
7521 ppFuncDesc = &pTIIface->funclist;
7522 for(func = 0; func < pidata->cMembers; func++) {
7523 METHODDATA *md = pidata->pmethdata + func;
7524 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7525 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7526 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7527 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7528 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7529 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7530 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7531 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7532 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7533 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7534 (*ppFuncDesc)->funcdesc.cScodes = 0;
7535 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7536 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7537 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7538 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7539 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7540 md->cArgs * sizeof(ELEMDESC));
7541 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7542 md->cArgs * sizeof(TLBParDesc));
7543 for(param = 0; param < md->cArgs; param++) {
7544 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7545 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7547 (*ppFuncDesc)->helpcontext = 0;
7548 (*ppFuncDesc)->HelpStringContext = 0;
7549 (*ppFuncDesc)->HelpString = NULL;
7550 (*ppFuncDesc)->Entry = NULL;
7551 (*ppFuncDesc)->ctCustData = 0;
7552 (*ppFuncDesc)->pCustData = NULL;
7553 (*ppFuncDesc)->next = NULL;
7554 pTIIface->TypeAttr.cFuncs++;
7555 ppFuncDesc = &(*ppFuncDesc)->next;
7558 dump_TypeInfo(pTIIface);
7560 pTypeLibImpl->pTypeInfo = pTIIface;
7561 pTypeLibImpl->TypeInfoCount++;
7563 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7564 pTIClass->pTypeLib = pTypeLibImpl;
7565 pTIClass->index = 1;
7566 pTIClass->Name = NULL;
7567 pTIClass->dwHelpContext = -1;
7568 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7569 pTIClass->TypeAttr.lcid = lcid;
7570 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7571 pTIClass->TypeAttr.wMajorVerNum = 0;
7572 pTIClass->TypeAttr.wMinorVerNum = 0;
7573 pTIClass->TypeAttr.cbAlignment = 2;
7574 pTIClass->TypeAttr.cbSizeInstance = -1;
7575 pTIClass->TypeAttr.cbSizeVft = -1;
7576 pTIClass->TypeAttr.cFuncs = 0;
7577 pTIClass->TypeAttr.cImplTypes = 1;
7578 pTIClass->TypeAttr.cVars = 0;
7579 pTIClass->TypeAttr.wTypeFlags = 0;
7581 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7582 pTIClass->impltypelist->hRef = 0;
7584 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7585 ref->index = 0;
7586 ref->reference = 0;
7587 ref->pImpTLInfo = TLB_REF_INTERNAL;
7588 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7590 dump_TypeInfo(pTIClass);
7592 pTIIface->next = pTIClass;
7593 pTypeLibImpl->TypeInfoCount++;
7595 *pptinfo = (ITypeInfo*)pTIClass;
7597 ITypeInfo_AddRef(*pptinfo);
7598 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7600 return S_OK;
7604 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7606 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7608 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7611 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7613 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7615 return ITypeInfo_AddRef((ITypeInfo *)This);
7618 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7620 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7622 return ITypeInfo_Release((ITypeInfo *)This);
7625 static HRESULT WINAPI ITypeComp_fnBind(
7626 ITypeComp * iface,
7627 OLECHAR * szName,
7628 ULONG lHash,
7629 WORD wFlags,
7630 ITypeInfo ** ppTInfo,
7631 DESCKIND * pDescKind,
7632 BINDPTR * pBindPtr)
7634 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7635 const TLBFuncDesc *pFDesc;
7636 const TLBVarDesc *pVDesc;
7637 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7639 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7641 *pDescKind = DESCKIND_NONE;
7642 pBindPtr->lpfuncdesc = NULL;
7643 *ppTInfo = NULL;
7645 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7646 if (!strcmpiW(pFDesc->Name, szName)) {
7647 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7648 break;
7649 else
7650 /* name found, but wrong flags */
7651 hr = TYPE_E_TYPEMISMATCH;
7654 if (pFDesc)
7656 HRESULT hr = TLB_AllocAndInitFuncDesc(
7657 &pFDesc->funcdesc,
7658 &pBindPtr->lpfuncdesc,
7659 This->TypeAttr.typekind == TKIND_DISPATCH);
7660 if (FAILED(hr))
7661 return hr;
7662 *pDescKind = DESCKIND_FUNCDESC;
7663 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7664 ITypeInfo_AddRef(*ppTInfo);
7665 return S_OK;
7666 } else {
7667 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7668 if (!strcmpiW(pVDesc->Name, szName)) {
7669 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7670 if (FAILED(hr))
7671 return hr;
7672 *pDescKind = DESCKIND_VARDESC;
7673 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7674 ITypeInfo_AddRef(*ppTInfo);
7675 return S_OK;
7679 /* FIXME: search each inherited interface, not just the first */
7680 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7681 /* recursive search */
7682 ITypeInfo *pTInfo;
7683 ITypeComp *pTComp;
7684 HRESULT hr;
7685 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7686 if (SUCCEEDED(hr))
7688 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7689 ITypeInfo_Release(pTInfo);
7691 if (SUCCEEDED(hr))
7693 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7694 ITypeComp_Release(pTComp);
7695 return hr;
7697 WARN("Could not search inherited interface!\n");
7699 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7700 return hr;
7703 static HRESULT WINAPI ITypeComp_fnBindType(
7704 ITypeComp * iface,
7705 OLECHAR * szName,
7706 ULONG lHash,
7707 ITypeInfo ** ppTInfo,
7708 ITypeComp ** ppTComp)
7710 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7712 /* strange behaviour (does nothing) but like the
7713 * original */
7715 if (!ppTInfo || !ppTComp)
7716 return E_POINTER;
7718 *ppTInfo = NULL;
7719 *ppTComp = NULL;
7721 return S_OK;
7724 static const ITypeCompVtbl tcompvt =
7727 ITypeComp_fnQueryInterface,
7728 ITypeComp_fnAddRef,
7729 ITypeComp_fnRelease,
7731 ITypeComp_fnBind,
7732 ITypeComp_fnBindType