jscript: Added ActiveXObject tests.
[wine/testsucceed.git] / dlls / oleaut32 / typelib.c
blob8fe6ce9b4df69e3d5d6bea870fa3502323ca141a
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
48 #include "config.h"
49 #include "wine/port.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
67 #include "lzexpand.h"
69 #include "wine/unicode.h"
70 #include "objbase.h"
71 #include "typelib.h"
72 #include "wine/debug.h"
73 #include "variant.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 typedef struct
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
89 typedef struct
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
95 * Name info array.
97 } NE_TYPEINFO;
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
102 /****************************************************************************
103 * FromLExxx
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
116 static DWORD FromLEDWord(DWORD p_iVal)
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
123 #else
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
126 #endif
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
132 * FromLExxx
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
139 WORD *Val = p_Val;
141 p_iSize /= sizeof(WORD);
143 while (p_iSize) {
144 *Val = FromLEWord(*Val);
145 Val++;
146 p_iSize--;
151 static void FromLEDWords(void *p_Val, int p_iSize)
153 DWORD *Val = p_Val;
155 p_iSize /= sizeof(DWORD);
157 while (p_iSize) {
158 *Val = FromLEDWord(*Val);
159 Val++;
160 p_iSize--;
163 #else
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
166 #endif
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
174 WCHAR buffer[60];
175 char key_name[16];
176 DWORD len, i;
177 INT best_maj = -1, best_min = -1;
178 HKEY hkey;
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 INT v_maj, v_min;
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
203 best_maj = v_maj;
205 if (*wMin == v_min)
207 best_min = v_min;
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
215 RegCloseKey( hkey );
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
223 *wMaj = best_maj;
224 *wMin = best_min;
225 return TRUE;
229 if (*wMaj == best_maj && best_min >= 0)
231 *wMin = best_min;
232 return TRUE;
234 return FALSE;
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
244 memcpy( buffer, TypelibW, sizeof(TypelibW) );
245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
247 return buffer;
250 /* get the path of an interface key, in the form "Interface\\<guid>" */
251 /* buffer must be at least 50 characters long */
252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
258 return buffer;
261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
262 /* buffer must be at least 16 characters long */
263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
266 static const WCHAR win16W[] = {'w','i','n','1','6',0};
267 static const WCHAR win32W[] = {'w','i','n','3','2',0};
268 static const WCHAR win64W[] = {'w','i','n','6','4',0};
270 sprintfW( buffer, LcidFormatW, lcid );
271 switch(syskind)
273 case SYS_WIN16: strcatW( buffer, win16W ); break;
274 case SYS_WIN32: strcatW( buffer, win32W ); break;
275 case SYS_WIN64: strcatW( buffer, win64W ); break;
276 default:
277 TRACE("Typelib is for unsupported syskind %i\n", syskind);
278 return NULL;
280 return buffer;
283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
286 /****************************************************************************
287 * QueryPathOfRegTypeLib [OLEAUT32.164]
289 * Gets the path to a registered type library.
291 * PARAMS
292 * guid [I] referenced guid
293 * wMaj [I] major version
294 * wMin [I] minor version
295 * lcid [I] locale id
296 * path [O] path of typelib
298 * RETURNS
299 * Success: S_OK.
300 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
301 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
302 * opened.
304 HRESULT WINAPI QueryPathOfRegTypeLib(
305 REFGUID guid,
306 WORD wMaj,
307 WORD wMin,
308 LCID lcid,
309 LPBSTR path )
311 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
312 LCID myLCID = lcid;
313 HKEY hkey;
314 WCHAR buffer[60];
315 WCHAR Path[MAX_PATH];
316 LONG res;
318 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
320 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
321 get_typelib_key( guid, wMaj, wMin, buffer );
323 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
324 if (res == ERROR_FILE_NOT_FOUND)
326 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
327 return TYPE_E_LIBNOTREGISTERED;
329 else if (res != ERROR_SUCCESS)
331 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
332 return TYPE_E_REGISTRYACCESS;
335 while (hr != S_OK)
337 LONG dwPathLen = sizeof(Path);
339 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
341 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
343 if (!lcid)
344 break;
345 else if (myLCID == lcid)
347 /* try with sub-langid */
348 myLCID = SUBLANGID(lcid);
350 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
352 /* try with system langid */
353 myLCID = 0;
355 else
357 break;
360 else
362 *path = SysAllocString( Path );
363 hr = S_OK;
366 RegCloseKey( hkey );
367 TRACE_(typelib)("-- 0x%08x\n", hr);
368 return hr;
371 /******************************************************************************
372 * CreateTypeLib [OLEAUT32.160] creates a typelib
374 * RETURNS
375 * Success: S_OK
376 * Failure: Status
378 HRESULT WINAPI CreateTypeLib(
379 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
381 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
382 return E_FAIL;
385 /******************************************************************************
386 * LoadTypeLib [OLEAUT32.161]
388 * Loads a type library
390 * PARAMS
391 * szFile [I] Name of file to load from.
392 * pptLib [O] Pointer that receives ITypeLib object on success.
394 * RETURNS
395 * Success: S_OK
396 * Failure: Status
398 * SEE
399 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
401 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
403 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
404 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
407 /******************************************************************************
408 * LoadTypeLibEx [OLEAUT32.183]
410 * Loads and optionally registers a type library
412 * RETURNS
413 * Success: S_OK
414 * Failure: Status
416 HRESULT WINAPI LoadTypeLibEx(
417 LPCOLESTR szFile, /* [in] Name of file to load from */
418 REGKIND regkind, /* [in] Specify kind of registration */
419 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
421 WCHAR szPath[MAX_PATH+1];
422 HRESULT res;
424 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
426 *pptLib = NULL;
428 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
430 if (SUCCEEDED(res))
431 switch(regkind)
433 case REGKIND_DEFAULT:
434 /* don't register typelibs supplied with full path. Experimentation confirms the following */
435 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
436 (szFile[0] && (szFile[1] == ':'))) break;
437 /* else fall-through */
439 case REGKIND_REGISTER:
440 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
442 IUnknown_Release(*pptLib);
443 *pptLib = 0;
445 break;
446 case REGKIND_NONE:
447 break;
450 TRACE(" returns %08x\n",res);
451 return res;
454 /******************************************************************************
455 * LoadRegTypeLib [OLEAUT32.162]
457 * Loads a registered type library.
459 * PARAMS
460 * rguid [I] GUID of the registered type library.
461 * wVerMajor [I] major version.
462 * wVerMinor [I] minor version.
463 * lcid [I] locale ID.
464 * ppTLib [O] pointer that receives an ITypeLib object on success.
466 * RETURNS
467 * Success: S_OK.
468 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
469 * LoadTypeLib.
471 HRESULT WINAPI LoadRegTypeLib(
472 REFGUID rguid,
473 WORD wVerMajor,
474 WORD wVerMinor,
475 LCID lcid,
476 ITypeLib **ppTLib)
478 BSTR bstr=NULL;
479 HRESULT res;
481 *ppTLib = NULL;
483 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
485 if(SUCCEEDED(res))
487 res= LoadTypeLib(bstr, ppTLib);
488 SysFreeString(bstr);
491 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
493 return res;
497 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
498 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
499 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
500 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
501 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
502 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
504 /******************************************************************************
505 * RegisterTypeLib [OLEAUT32.163]
506 * Adds information about a type library to the System Registry
507 * NOTES
508 * Docs: ITypeLib FAR * ptlib
509 * Docs: OLECHAR FAR* szFullPath
510 * Docs: OLECHAR FAR* szHelpDir
512 * RETURNS
513 * Success: S_OK
514 * Failure: Status
516 HRESULT WINAPI RegisterTypeLib(
517 ITypeLib * ptlib, /* [in] Pointer to the library*/
518 OLECHAR * szFullPath, /* [in] full Path of the library*/
519 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
520 may be NULL*/
522 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
523 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
524 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
525 HRESULT res;
526 TLIBATTR *attr;
527 WCHAR keyName[60];
528 WCHAR tmp[16];
529 HKEY key, subKey;
530 UINT types, tidx;
531 TYPEKIND kind;
532 DWORD disposition;
534 if (ptlib == NULL || szFullPath == NULL)
535 return E_INVALIDARG;
537 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
538 return E_FAIL;
540 #ifdef _WIN64
541 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
542 #else
543 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
544 #endif
546 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
548 res = S_OK;
549 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
550 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
552 LPOLESTR doc;
554 /* Set the human-readable name of the typelib */
555 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
557 if (RegSetValueExW(key, NULL, 0, REG_SZ,
558 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
559 res = E_FAIL;
561 SysFreeString(doc);
563 else
564 res = E_FAIL;
566 /* Make up the name of the typelib path subkey */
567 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
569 /* Create the typelib path subkey */
570 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
571 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
573 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
574 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
575 res = E_FAIL;
577 RegCloseKey(subKey);
579 else
580 res = E_FAIL;
582 /* Create the flags subkey */
583 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
584 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
586 /* FIXME: is %u correct? */
587 static const WCHAR formatW[] = {'%','u',0};
588 WCHAR buf[20];
589 sprintfW(buf, formatW, attr->wLibFlags);
590 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
591 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
592 res = E_FAIL;
594 RegCloseKey(subKey);
596 else
597 res = E_FAIL;
599 /* create the helpdir subkey */
600 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
601 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
603 BOOL freeHelpDir = FALSE;
604 OLECHAR* pIndexStr;
606 /* if we created a new key, and helpDir was null, set the helpdir
607 to the directory which contains the typelib. However,
608 if we just opened an existing key, we leave the helpdir alone */
609 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
610 szHelpDir = SysAllocString(szFullPath);
611 pIndexStr = strrchrW(szHelpDir, '\\');
612 if (pIndexStr) {
613 *pIndexStr = 0;
615 freeHelpDir = TRUE;
618 /* if we have an szHelpDir, set it! */
619 if (szHelpDir != NULL) {
620 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
621 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
622 res = E_FAIL;
626 /* tidy up */
627 if (freeHelpDir) SysFreeString(szHelpDir);
628 RegCloseKey(subKey);
630 } else {
631 res = E_FAIL;
634 RegCloseKey(key);
636 else
637 res = E_FAIL;
639 /* register OLE Automation-compatible interfaces for this typelib */
640 types = ITypeLib_GetTypeInfoCount(ptlib);
641 for (tidx=0; tidx<types; tidx++) {
642 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
643 LPOLESTR name = NULL;
644 ITypeInfo *tinfo = NULL;
646 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
648 switch (kind) {
649 case TKIND_INTERFACE:
650 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
651 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
652 break;
654 case TKIND_DISPATCH:
655 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
656 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
657 break;
659 default:
660 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
661 break;
664 if (tinfo) {
665 TYPEATTR *tattr = NULL;
666 ITypeInfo_GetTypeAttr(tinfo, &tattr);
668 if (tattr) {
669 TRACE_(typelib)("guid=%s, flags=%04x (",
670 debugstr_guid(&tattr->guid),
671 tattr->wTypeFlags);
673 if (TRACE_ON(typelib)) {
674 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
675 XX(FAPPOBJECT);
676 XX(FCANCREATE);
677 XX(FLICENSED);
678 XX(FPREDECLID);
679 XX(FHIDDEN);
680 XX(FCONTROL);
681 XX(FDUAL);
682 XX(FNONEXTENSIBLE);
683 XX(FOLEAUTOMATION);
684 XX(FRESTRICTED);
685 XX(FAGGREGATABLE);
686 XX(FREPLACEABLE);
687 XX(FDISPATCHABLE);
688 XX(FREVERSEBIND);
689 XX(FPROXY);
690 #undef XX
691 MESSAGE("\n");
694 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
696 /* register interface<->typelib coupling */
697 get_interface_key( &tattr->guid, keyName );
698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
699 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
701 if (name)
702 RegSetValueExW(key, NULL, 0, REG_SZ,
703 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
705 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
706 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
707 RegSetValueExW(subKey, NULL, 0, REG_SZ,
708 (const BYTE *)PSOA, sizeof PSOA);
709 RegCloseKey(subKey);
712 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
713 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
714 RegSetValueExW(subKey, NULL, 0, REG_SZ,
715 (const BYTE *)PSOA, sizeof PSOA);
716 RegCloseKey(subKey);
719 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
720 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
722 WCHAR buffer[40];
723 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
724 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
726 StringFromGUID2(&attr->guid, buffer, 40);
727 RegSetValueExW(subKey, NULL, 0, REG_SZ,
728 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
729 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
730 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
731 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
732 RegCloseKey(subKey);
735 RegCloseKey(key);
739 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
742 ITypeInfo_Release(tinfo);
745 SysFreeString(name);
749 ITypeLib_ReleaseTLibAttr(ptlib, attr);
751 return res;
755 /******************************************************************************
756 * UnRegisterTypeLib [OLEAUT32.186]
757 * Removes information about a type library from the System Registry
758 * NOTES
760 * RETURNS
761 * Success: S_OK
762 * Failure: Status
764 HRESULT WINAPI UnRegisterTypeLib(
765 REFGUID libid, /* [in] Guid of the library */
766 WORD wVerMajor, /* [in] major version */
767 WORD wVerMinor, /* [in] minor version */
768 LCID lcid, /* [in] locale id */
769 SYSKIND syskind)
771 BSTR tlibPath = NULL;
772 DWORD tmpLength;
773 WCHAR keyName[60];
774 WCHAR subKeyName[50];
775 int result = S_OK;
776 DWORD i = 0;
777 BOOL deleteOtherStuff;
778 HKEY key = NULL;
779 HKEY subKey = NULL;
780 TYPEATTR* typeAttr = NULL;
781 TYPEKIND kind;
782 ITypeInfo* typeInfo = NULL;
783 ITypeLib* typeLib = NULL;
784 int numTypes;
786 TRACE("(IID: %s)\n",debugstr_guid(libid));
788 /* Create the path to the key */
789 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
791 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
793 TRACE("Unsupported syskind %i\n", syskind);
794 result = E_INVALIDARG;
795 goto end;
798 /* get the path to the typelib on disk */
799 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
800 result = E_INVALIDARG;
801 goto end;
804 /* Try and open the key to the type library. */
805 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
806 result = E_INVALIDARG;
807 goto end;
810 /* Try and load the type library */
811 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
812 result = TYPE_E_INVALIDSTATE;
813 goto end;
816 /* remove any types registered with this typelib */
817 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
818 for (i=0; i<numTypes; i++) {
819 /* get the kind of type */
820 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
821 goto enddeleteloop;
824 /* skip non-interfaces, and get type info for the type */
825 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
826 goto enddeleteloop;
828 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
829 goto enddeleteloop;
831 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
832 goto enddeleteloop;
835 /* the path to the type */
836 get_interface_key( &typeAttr->guid, subKeyName );
838 /* Delete its bits */
839 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
840 goto enddeleteloop;
842 RegDeleteKeyW(subKey, ProxyStubClsidW);
843 RegDeleteKeyW(subKey, ProxyStubClsid32W);
844 RegDeleteKeyW(subKey, TypeLibW);
845 RegCloseKey(subKey);
846 subKey = NULL;
847 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
849 enddeleteloop:
850 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
851 typeAttr = NULL;
852 if (typeInfo) ITypeInfo_Release(typeInfo);
853 typeInfo = NULL;
856 /* Now, delete the type library path subkey */
857 get_lcid_subkey( lcid, syskind, subKeyName );
858 RegDeleteKeyW(key, subKeyName);
859 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
860 RegDeleteKeyW(key, subKeyName);
862 /* check if there is anything besides the FLAGS/HELPDIR keys.
863 If there is, we don't delete them */
864 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
865 deleteOtherStuff = TRUE;
866 i = 0;
867 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
868 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
870 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
871 if (!strcmpW(subKeyName, FLAGSW)) continue;
872 if (!strcmpW(subKeyName, HELPDIRW)) continue;
873 deleteOtherStuff = FALSE;
874 break;
877 /* only delete the other parts of the key if we're absolutely sure */
878 if (deleteOtherStuff) {
879 RegDeleteKeyW(key, FLAGSW);
880 RegDeleteKeyW(key, HELPDIRW);
881 RegCloseKey(key);
882 key = NULL;
884 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
885 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
886 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
889 end:
890 SysFreeString(tlibPath);
891 if (typeLib) ITypeLib_Release(typeLib);
892 if (subKey) RegCloseKey(subKey);
893 if (key) RegCloseKey(key);
894 return result;
897 /*======================= ITypeLib implementation =======================*/
899 typedef struct tagTLBCustData
901 GUID guid;
902 VARIANT data;
903 struct tagTLBCustData* next;
904 } TLBCustData;
906 /* data structure for import typelibs */
907 typedef struct tagTLBImpLib
909 int offset; /* offset in the file (MSFT)
910 offset in nametable (SLTG)
911 just used to identify library while reading
912 data from file */
913 GUID guid; /* libid */
914 BSTR name; /* name */
916 LCID lcid; /* lcid of imported typelib */
918 WORD wVersionMajor; /* major version number */
919 WORD wVersionMinor; /* minor version number */
921 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
922 NULL if not yet loaded */
923 struct tagTLBImpLib * next;
924 } TLBImpLib;
926 /* internal ITypeLib data */
927 typedef struct tagITypeLibImpl
929 const ITypeLib2Vtbl *lpVtbl;
930 const ITypeCompVtbl *lpVtblTypeComp;
931 LONG ref;
932 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
933 LCID lcid;
935 /* strings can be stored in tlb as multibyte strings BUT they are *always*
936 * exported to the application as a UNICODE string.
938 BSTR Name;
939 BSTR DocString;
940 BSTR HelpFile;
941 BSTR HelpStringDll;
942 DWORD dwHelpContext;
943 int TypeInfoCount; /* nr of typeinfo's in librarry */
944 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
945 int ctCustData; /* number of items in cust data list */
946 TLBCustData * pCustData; /* linked list to cust data */
947 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
948 int ctTypeDesc; /* number of items in type desc array */
949 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
950 library. Only used while reading MSFT
951 typelibs */
952 struct list ref_list; /* list of ref types in this typelib */
953 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
956 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
957 struct tagITypeLibImpl *next, *prev;
958 WCHAR *path;
959 INT index;
960 } ITypeLibImpl;
962 static const ITypeLib2Vtbl tlbvt;
963 static const ITypeCompVtbl tlbtcvt;
965 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
967 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
970 /* ITypeLib methods */
971 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
972 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
974 /*======================= ITypeInfo implementation =======================*/
976 /* data for referenced types */
977 typedef struct tagTLBRefType
979 INT index; /* Type index for internal ref or for external ref
980 it the format is SLTG. -2 indicates to
981 use guid */
983 GUID guid; /* guid of the referenced type */
984 /* if index == TLB_REF_USE_GUID */
986 HREFTYPE reference; /* The href of this ref */
987 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
988 TLB_REF_INTERNAL for internal refs
989 TLB_REF_NOT_FOUND for broken refs */
991 struct list entry;
992 } TLBRefType;
994 #define TLB_REF_USE_GUID -2
996 #define TLB_REF_INTERNAL (void*)-2
997 #define TLB_REF_NOT_FOUND (void*)-1
999 /* internal Parameter data */
1000 typedef struct tagTLBParDesc
1002 BSTR Name;
1003 int ctCustData;
1004 TLBCustData * pCustData; /* linked list to cust data */
1005 } TLBParDesc;
1007 /* internal Function data */
1008 typedef struct tagTLBFuncDesc
1010 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1011 BSTR Name; /* the name of this function */
1012 TLBParDesc *pParamDesc; /* array with param names and custom data */
1013 int helpcontext;
1014 int HelpStringContext;
1015 BSTR HelpString;
1016 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
1017 int ctCustData;
1018 TLBCustData * pCustData; /* linked list to cust data; */
1019 struct tagTLBFuncDesc * next;
1020 } TLBFuncDesc;
1022 /* internal Variable data */
1023 typedef struct tagTLBVarDesc
1025 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1026 BSTR Name; /* the name of this variable */
1027 int HelpContext;
1028 int HelpStringContext; /* FIXME: where? */
1029 BSTR HelpString;
1030 int ctCustData;
1031 TLBCustData * pCustData;/* linked list to cust data; */
1032 struct tagTLBVarDesc * next;
1033 } TLBVarDesc;
1035 /* internal implemented interface data */
1036 typedef struct tagTLBImplType
1038 HREFTYPE hRef; /* hRef of interface */
1039 int implflags; /* IMPLFLAG_*s */
1040 int ctCustData;
1041 TLBCustData * pCustData;/* linked list to custom data; */
1042 struct tagTLBImplType *next;
1043 } TLBImplType;
1045 /* internal TypeInfo data */
1046 typedef struct tagITypeInfoImpl
1048 const ITypeInfo2Vtbl *lpVtbl;
1049 const ITypeCompVtbl *lpVtblTypeComp;
1050 LONG ref;
1051 BOOL no_free_data; /* don't free data structures */
1052 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1053 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1054 int index; /* index in this typelib; */
1055 HREFTYPE hreftype; /* hreftype for app object binding */
1056 /* type libs seem to store the doc strings in ascii
1057 * so why should we do it in unicode?
1059 BSTR Name;
1060 BSTR DocString;
1061 BSTR DllName;
1062 DWORD dwHelpContext;
1063 DWORD dwHelpStringContext;
1065 /* functions */
1066 TLBFuncDesc * funclist; /* linked list with function descriptions */
1068 /* variables */
1069 TLBVarDesc * varlist; /* linked list with variable descriptions */
1071 /* Implemented Interfaces */
1072 TLBImplType * impltypelist;
1074 int ctCustData;
1075 TLBCustData * pCustData; /* linked list to cust data; */
1076 struct tagITypeInfoImpl * next;
1077 } ITypeInfoImpl;
1079 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1081 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1084 static const ITypeInfo2Vtbl tinfvt;
1085 static const ITypeCompVtbl tcompvt;
1087 static ITypeInfo2 * ITypeInfo_Constructor(void);
1089 typedef struct tagTLBContext
1091 unsigned int oStart; /* start of TLB in file */
1092 unsigned int pos; /* current pos */
1093 unsigned int length; /* total length */
1094 void *mapping; /* memory mapping */
1095 MSFT_SegDir * pTblDir;
1096 ITypeLibImpl* pLibInfo;
1097 } TLBContext;
1100 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1103 debug
1105 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1106 if (pTD->vt & VT_RESERVED)
1107 szVarType += strlen(strcpy(szVarType, "reserved | "));
1108 if (pTD->vt & VT_BYREF)
1109 szVarType += strlen(strcpy(szVarType, "ref to "));
1110 if (pTD->vt & VT_ARRAY)
1111 szVarType += strlen(strcpy(szVarType, "array of "));
1112 if (pTD->vt & VT_VECTOR)
1113 szVarType += strlen(strcpy(szVarType, "vector of "));
1114 switch(pTD->vt & VT_TYPEMASK) {
1115 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1116 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1117 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1118 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1119 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1120 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1121 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1122 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1123 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1124 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1125 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1126 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1127 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1128 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1129 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1130 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1131 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1132 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1133 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1134 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1135 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1136 pTD->u.hreftype); break;
1137 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1138 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1139 case VT_PTR: sprintf(szVarType, "ptr to ");
1140 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1141 break;
1142 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1143 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1144 break;
1145 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1146 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1147 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1148 break;
1150 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1154 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1155 char buf[200];
1156 USHORT flags = edesc->u.paramdesc.wParamFlags;
1157 dump_TypeDesc(&edesc->tdesc,buf);
1158 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1159 MESSAGE("\t\tu.paramdesc.wParamFlags");
1160 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1161 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1162 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1163 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1164 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1165 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1166 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1167 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1168 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1170 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1171 int i;
1172 MESSAGE("memid is %08x\n",funcdesc->memid);
1173 for (i=0;i<funcdesc->cParams;i++) {
1174 MESSAGE("Param %d:\n",i);
1175 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1177 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1178 switch (funcdesc->funckind) {
1179 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1180 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1181 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1182 case FUNC_STATIC: MESSAGE("static");break;
1183 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1184 default: MESSAGE("unknown");break;
1186 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1187 switch (funcdesc->invkind) {
1188 case INVOKE_FUNC: MESSAGE("func");break;
1189 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1190 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1191 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1193 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1194 switch (funcdesc->callconv) {
1195 case CC_CDECL: MESSAGE("cdecl");break;
1196 case CC_PASCAL: MESSAGE("pascal");break;
1197 case CC_STDCALL: MESSAGE("stdcall");break;
1198 case CC_SYSCALL: MESSAGE("syscall");break;
1199 default:break;
1201 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1202 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1203 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1205 MESSAGE("\telemdescFunc (return value type):\n");
1206 dump_ELEMDESC(&funcdesc->elemdescFunc);
1209 static const char * const typekind_desc[] =
1211 "TKIND_ENUM",
1212 "TKIND_RECORD",
1213 "TKIND_MODULE",
1214 "TKIND_INTERFACE",
1215 "TKIND_DISPATCH",
1216 "TKIND_COCLASS",
1217 "TKIND_ALIAS",
1218 "TKIND_UNION",
1219 "TKIND_MAX"
1222 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1224 int i;
1225 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1226 for (i=0;i<pfd->funcdesc.cParams;i++)
1227 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1230 dump_FUNCDESC(&(pfd->funcdesc));
1232 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1233 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1235 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1237 while (pfd)
1239 dump_TLBFuncDescOne(pfd);
1240 pfd = pfd->next;
1243 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1245 while (pvd)
1247 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1248 pvd = pvd->next;
1252 static void dump_TLBImpLib(const TLBImpLib *import)
1254 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1255 debugstr_w(import->name));
1256 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1257 import->wVersionMinor, import->lcid, import->offset);
1260 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1262 TLBRefType *ref;
1264 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1266 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1267 if(ref->index == -1)
1268 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1269 else
1270 TRACE_(typelib)("type no: %d\n", ref->index);
1272 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1274 TRACE_(typelib)("in lib\n");
1275 dump_TLBImpLib(ref->pImpTLInfo);
1280 static void dump_TLBImplType(const TLBImplType * impl)
1282 while (impl) {
1283 TRACE_(typelib)(
1284 "implementing/inheriting interface hRef = %x implflags %x\n",
1285 impl->hRef, impl->implflags);
1286 impl = impl->next;
1290 static void dump_Variant(const VARIANT * pvar)
1292 SYSTEMTIME st;
1294 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1296 if (pvar)
1298 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1299 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1301 TRACE(",%p", V_BYREF(pvar));
1303 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1305 TRACE(",%p", V_ARRAY(pvar));
1307 else switch (V_TYPE(pvar))
1309 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1310 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1311 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1312 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1313 case VT_INT:
1314 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1315 case VT_UINT:
1316 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1317 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1318 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1319 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1320 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1321 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1322 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1323 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1324 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1325 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1326 V_CY(pvar).s.Lo); break;
1327 case VT_DATE:
1328 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1329 TRACE(",<invalid>");
1330 else
1331 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1332 st.wHour, st.wMinute, st.wSecond);
1333 break;
1334 case VT_ERROR:
1335 case VT_VOID:
1336 case VT_USERDEFINED:
1337 case VT_EMPTY:
1338 case VT_NULL: break;
1339 default: TRACE(",?"); break;
1342 TRACE("}\n");
1345 static void dump_DispParms(const DISPPARAMS * pdp)
1347 unsigned int index;
1349 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1351 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1353 TRACE("named args:\n");
1354 for (index = 0; index < pdp->cNamedArgs; index++)
1355 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1358 if (pdp->cArgs && pdp->rgvarg)
1360 TRACE("args:\n");
1361 for (index = 0; index < pdp->cArgs; index++)
1362 dump_Variant( &pdp->rgvarg[index] );
1366 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1368 TRACE("%p ref=%u\n", pty, pty->ref);
1369 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1370 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1371 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1372 TRACE("fct:%u var:%u impl:%u\n",
1373 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1374 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1375 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1376 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1377 if (TRACE_ON(ole))
1378 dump_TLBFuncDesc(pty->funclist);
1379 dump_TLBVarDesc(pty->varlist);
1380 dump_TLBImplType(pty->impltypelist);
1383 static void dump_VARDESC(const VARDESC *v)
1385 MESSAGE("memid %d\n",v->memid);
1386 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1387 MESSAGE("oInst %d\n",v->u.oInst);
1388 dump_ELEMDESC(&(v->elemdescVar));
1389 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1390 MESSAGE("varkind %d\n",v->varkind);
1393 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1395 /* VT_LPWSTR is largest type that */
1396 /* may appear in type description*/
1397 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1398 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1399 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1400 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1401 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1402 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1403 {{0},30},{{0},31}
1406 static void TLB_abort(void)
1408 DebugBreak();
1411 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1412 static void * TLB_Alloc(unsigned size)
1414 void * ret;
1415 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1416 /* FIXME */
1417 ERR("cannot allocate memory\n");
1419 return ret;
1422 static void TLB_Free(void * ptr)
1424 HeapFree(GetProcessHeap(), 0, ptr);
1427 /* returns the size required for a deep copy of a typedesc into a
1428 * flat buffer */
1429 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1431 SIZE_T size = 0;
1433 if (alloc_initial_space)
1434 size += sizeof(TYPEDESC);
1436 switch (tdesc->vt)
1438 case VT_PTR:
1439 case VT_SAFEARRAY:
1440 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1441 break;
1442 case VT_CARRAY:
1443 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1444 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1445 break;
1447 return size;
1450 /* deep copy a typedesc into a flat buffer */
1451 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1453 if (!dest)
1455 dest = buffer;
1456 buffer = (char *)buffer + sizeof(TYPEDESC);
1459 *dest = *src;
1461 switch (src->vt)
1463 case VT_PTR:
1464 case VT_SAFEARRAY:
1465 dest->u.lptdesc = buffer;
1466 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1467 break;
1468 case VT_CARRAY:
1469 dest->u.lpadesc = buffer;
1470 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1471 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1472 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1473 break;
1475 return buffer;
1478 /* free custom data allocated by MSFT_CustData */
1479 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1481 TLBCustData *pCustDataNext;
1482 for (; pCustData; pCustData = pCustDataNext)
1484 VariantClear(&pCustData->data);
1486 pCustDataNext = pCustData->next;
1487 TLB_Free(pCustData);
1491 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1493 DWORD len;
1494 BSTR ret;
1496 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1497 ret = SysAllocStringLen(NULL, len - 1);
1498 if (!ret) return ret;
1499 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1500 return ret;
1503 /**********************************************************************
1505 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1507 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1509 return pcx->pos;
1512 static inline void MSFT_Seek(TLBContext *pcx, long where)
1514 if (where != DO_NOT_SEEK)
1516 where += pcx->oStart;
1517 if (where > pcx->length)
1519 /* FIXME */
1520 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1521 TLB_abort();
1523 pcx->pos = where;
1527 /* read function */
1528 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1530 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1531 pcx->pos, count, pcx->oStart, pcx->length, where);
1533 MSFT_Seek(pcx, where);
1534 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1535 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1536 pcx->pos += count;
1537 return count;
1540 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1541 long where )
1543 DWORD ret;
1545 ret = MSFT_Read(buffer, count, pcx, where);
1546 FromLEDWords(buffer, ret);
1548 return ret;
1551 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1552 long where )
1554 DWORD ret;
1556 ret = MSFT_Read(buffer, count, pcx, where);
1557 FromLEWords(buffer, ret);
1559 return ret;
1562 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1564 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1565 memset(pGuid,0, sizeof(GUID));
1566 return;
1568 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1569 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1570 pGuid->Data2 = FromLEWord(pGuid->Data2);
1571 pGuid->Data3 = FromLEWord(pGuid->Data3);
1572 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1575 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1577 MSFT_NameIntro niName;
1579 if (offset < 0)
1581 ERR_(typelib)("bad offset %d\n", offset);
1582 return -1;
1585 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1586 pcx->pTblDir->pNametab.offset+offset);
1588 return niName.hreftype;
1591 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1593 char * name;
1594 MSFT_NameIntro niName;
1595 int lengthInChars;
1596 BSTR bstrName = NULL;
1598 if (offset < 0)
1600 ERR_(typelib)("bad offset %d\n", offset);
1601 return NULL;
1603 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1604 pcx->pTblDir->pNametab.offset+offset);
1605 niName.namelen &= 0xFF; /* FIXME: correct ? */
1606 name=TLB_Alloc((niName.namelen & 0xff) +1);
1607 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1608 name[niName.namelen & 0xff]='\0';
1610 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1611 name, -1, NULL, 0);
1613 /* no invalid characters in string */
1614 if (lengthInChars)
1616 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1618 /* don't check for invalid character since this has been done previously */
1619 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1621 TLB_Free(name);
1623 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1624 return bstrName;
1627 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1629 char * string;
1630 INT16 length;
1631 int lengthInChars;
1632 BSTR bstr = NULL;
1634 if(offset<0) return NULL;
1635 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1636 if(length <= 0) return 0;
1637 string=TLB_Alloc(length +1);
1638 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1639 string[length]='\0';
1641 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1642 string, -1, NULL, 0);
1644 /* no invalid characters in string */
1645 if (lengthInChars)
1647 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1649 /* don't check for invalid character since this has been done previously */
1650 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1652 TLB_Free(string);
1654 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1655 return bstr;
1658 * read a value and fill a VARIANT structure
1660 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1662 int size;
1664 TRACE_(typelib)("\n");
1666 if(offset <0) { /* data are packed in here */
1667 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1668 V_I4(pVar) = offset & 0x3ffffff;
1669 return;
1671 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1672 pcx->pTblDir->pCustData.offset + offset );
1673 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1674 switch (V_VT(pVar)){
1675 case VT_EMPTY: /* FIXME: is this right? */
1676 case VT_NULL: /* FIXME: is this right? */
1677 case VT_I2 : /* this should not happen */
1678 case VT_I4 :
1679 case VT_R4 :
1680 case VT_ERROR :
1681 case VT_BOOL :
1682 case VT_I1 :
1683 case VT_UI1 :
1684 case VT_UI2 :
1685 case VT_UI4 :
1686 case VT_INT :
1687 case VT_UINT :
1688 case VT_VOID : /* FIXME: is this right? */
1689 case VT_HRESULT :
1690 size=4; break;
1691 case VT_R8 :
1692 case VT_CY :
1693 case VT_DATE :
1694 case VT_I8 :
1695 case VT_UI8 :
1696 case VT_DECIMAL : /* FIXME: is this right? */
1697 case VT_FILETIME :
1698 size=8;break;
1699 /* pointer types with known behaviour */
1700 case VT_BSTR :{
1701 char * ptr;
1702 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1703 if(size < 0) {
1704 char next;
1705 DWORD origPos = MSFT_Tell(pcx), nullPos;
1707 do {
1708 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1709 } while (next);
1710 nullPos = MSFT_Tell(pcx);
1711 size = nullPos - origPos;
1712 MSFT_Seek(pcx, origPos);
1714 ptr=TLB_Alloc(size);/* allocate temp buffer */
1715 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1716 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1717 /* FIXME: do we need a AtoW conversion here? */
1718 V_UNION(pVar, bstrVal[size])='\0';
1719 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1720 TLB_Free(ptr);
1722 size=-4; break;
1723 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1724 case VT_DISPATCH :
1725 case VT_VARIANT :
1726 case VT_UNKNOWN :
1727 case VT_PTR :
1728 case VT_SAFEARRAY :
1729 case VT_CARRAY :
1730 case VT_USERDEFINED :
1731 case VT_LPSTR :
1732 case VT_LPWSTR :
1733 case VT_BLOB :
1734 case VT_STREAM :
1735 case VT_STORAGE :
1736 case VT_STREAMED_OBJECT :
1737 case VT_STORED_OBJECT :
1738 case VT_BLOB_OBJECT :
1739 case VT_CF :
1740 case VT_CLSID :
1741 default:
1742 size=0;
1743 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1744 V_VT(pVar));
1747 if(size>0) /* (big|small) endian correct? */
1748 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1749 return;
1752 * create a linked list with custom data
1754 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1756 MSFT_CDGuid entry;
1757 TLBCustData* pNew;
1758 int count=0;
1760 TRACE_(typelib)("\n");
1762 while(offset >=0){
1763 count++;
1764 pNew=TLB_Alloc(sizeof(TLBCustData));
1765 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1766 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1767 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1768 /* add new custom data at head of the list */
1769 pNew->next=*ppCustData;
1770 *ppCustData=pNew;
1771 offset = entry.next;
1773 return count;
1776 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1777 ITypeInfoImpl *pTI)
1779 if(type <0)
1780 pTd->vt=type & VT_TYPEMASK;
1781 else
1782 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1784 if(pTd->vt == VT_USERDEFINED)
1785 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1787 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1790 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1792 /* resolve referenced type if any */
1793 while (lpTypeDesc)
1795 switch (lpTypeDesc->vt)
1797 case VT_PTR:
1798 lpTypeDesc = lpTypeDesc->u.lptdesc;
1799 break;
1801 case VT_CARRAY:
1802 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1803 break;
1805 case VT_USERDEFINED:
1806 MSFT_DoRefType(pcx, pTI->pTypeLib,
1807 lpTypeDesc->u.hreftype);
1809 lpTypeDesc = NULL;
1810 break;
1812 default:
1813 lpTypeDesc = NULL;
1818 static void
1819 MSFT_DoFuncs(TLBContext* pcx,
1820 ITypeInfoImpl* pTI,
1821 int cFuncs,
1822 int cVars,
1823 int offset,
1824 TLBFuncDesc** pptfd)
1827 * member information is stored in a data structure at offset
1828 * indicated by the memoffset field of the typeinfo structure
1829 * There are several distinctive parts.
1830 * The first part starts with a field that holds the total length
1831 * of this (first) part excluding this field. Then follow the records,
1832 * for each member there is one record.
1834 * The first entry is always the length of the record (including this
1835 * length word).
1836 * The rest of the record depends on the type of the member. If there is
1837 * a field indicating the member type (function, variable, interface, etc)
1838 * I have not found it yet. At this time we depend on the information
1839 * in the type info and the usual order how things are stored.
1841 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1842 * for each member;
1844 * Third is an equal sized array with file offsets to the name entry
1845 * of each member.
1847 * The fourth and last (?) part is an array with offsets to the records
1848 * in the first part of this file segment.
1851 int infolen, nameoffset, reclength, nrattributes, i;
1852 int recoffset = offset + sizeof(INT);
1854 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1855 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1856 TLBFuncDesc *ptfd_prev = NULL;
1858 TRACE_(typelib)("\n");
1860 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1862 for ( i = 0; i < cFuncs ; i++ )
1864 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1866 /* name, eventually add to a hash table */
1867 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1868 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1870 /* nameoffset is sometimes -1 on the second half of a propget/propput
1871 * pair of functions */
1872 if ((nameoffset == -1) && (i > 0))
1873 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1874 else
1875 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1877 /* read the function information record */
1878 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1880 reclength &= 0xffff;
1882 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1884 /* do the attributes */
1885 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1886 / sizeof(int);
1888 if ( nrattributes > 0 )
1890 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1892 if ( nrattributes > 1 )
1894 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1895 pFuncRec->OptAttr[1]) ;
1897 if ( nrattributes > 2 )
1899 if ( pFuncRec->FKCCIC & 0x2000 )
1901 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1902 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1903 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1905 else
1907 (*pptfd)->Entry = MSFT_ReadString(pcx,
1908 pFuncRec->OptAttr[2]);
1910 if( nrattributes > 5 )
1912 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1914 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1916 MSFT_CustData(pcx,
1917 pFuncRec->OptAttr[6],
1918 &(*pptfd)->pCustData);
1922 else
1924 (*pptfd)->Entry = (BSTR)-1;
1929 /* fill the FuncDesc Structure */
1930 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1931 offset + infolen + ( i + 1) * sizeof(INT));
1933 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1934 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1935 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1936 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1937 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1938 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1939 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1941 MSFT_GetTdesc(pcx,
1942 pFuncRec->DataType,
1943 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1944 pTI);
1945 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1947 /* do the parameters/arguments */
1948 if(pFuncRec->nrargs)
1950 int j = 0;
1951 MSFT_ParameterInfo paraminfo;
1953 (*pptfd)->funcdesc.lprgelemdescParam =
1954 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1956 (*pptfd)->pParamDesc =
1957 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1959 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1960 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1962 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1964 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1966 MSFT_GetTdesc(pcx,
1967 paraminfo.DataType,
1968 &elemdesc->tdesc,
1969 pTI);
1971 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1973 /* name */
1974 if (paraminfo.oName == -1)
1975 /* this occurs for [propput] or [propget] methods, so
1976 * we should just set the name of the parameter to the
1977 * name of the method. */
1978 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1979 else
1980 (*pptfd)->pParamDesc[j].Name =
1981 MSFT_ReadName( pcx, paraminfo.oName );
1982 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1984 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1986 /* default value */
1987 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1988 (pFuncRec->FKCCIC & 0x1000) )
1990 INT* pInt = (INT *)((char *)pFuncRec +
1991 reclength -
1992 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1994 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1996 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1997 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1999 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2000 pInt[j], pcx);
2002 else
2003 elemdesc->u.paramdesc.pparamdescex = NULL;
2004 /* custom info */
2005 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2007 MSFT_CustData(pcx,
2008 pFuncRec->OptAttr[7+j],
2009 &(*pptfd)->pParamDesc[j].pCustData);
2012 /* SEEK value = jump to offset,
2013 * from there jump to the end of record,
2014 * go back by (j-1) arguments
2016 MSFT_ReadLEDWords( &paraminfo ,
2017 sizeof(MSFT_ParameterInfo), pcx,
2018 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2019 * sizeof(MSFT_ParameterInfo)));
2023 /* scode is not used: archaic win16 stuff FIXME: right? */
2024 (*pptfd)->funcdesc.cScodes = 0 ;
2025 (*pptfd)->funcdesc.lprgscode = NULL ;
2027 ptfd_prev = *pptfd;
2028 pptfd = & ((*pptfd)->next);
2029 recoffset += reclength;
2031 HeapFree(GetProcessHeap(), 0, recbuf);
2034 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2035 int cVars, int offset, TLBVarDesc ** pptvd)
2037 int infolen, nameoffset, reclength;
2038 char recbuf[256];
2039 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2040 int i;
2041 int recoffset;
2043 TRACE_(typelib)("\n");
2045 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2046 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2047 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2048 recoffset += offset+sizeof(INT);
2049 for(i=0;i<cVars;i++){
2050 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2051 /* name, eventually add to a hash table */
2052 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2053 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2054 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2055 /* read the variable information record */
2056 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2057 reclength &=0xff;
2058 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2059 /* Optional data */
2060 if(reclength >(6*sizeof(INT)) )
2061 (*pptvd)->HelpContext=pVarRec->HelpContext;
2062 if(reclength >(7*sizeof(INT)) )
2063 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2064 if(reclength >(8*sizeof(INT)) )
2065 if(reclength >(9*sizeof(INT)) )
2066 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2067 /* fill the VarDesc Structure */
2068 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2069 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2070 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2071 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2072 MSFT_GetTdesc(pcx, pVarRec->DataType,
2073 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2074 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2075 if(pVarRec->VarKind == VAR_CONST ){
2076 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2077 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2078 pVarRec->OffsValue, pcx);
2079 } else
2080 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2081 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2082 pptvd=&((*pptvd)->next);
2083 recoffset += reclength;
2086 /* fill in data for a hreftype (offset). When the referenced type is contained
2087 * in the typelib, it's just an (file) offset in the type info base dir.
2088 * If comes from import, it's an offset+1 in the ImpInfo table
2089 * */
2090 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2091 int offset)
2093 TLBRefType *ref;
2095 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2097 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2099 if(ref->reference == offset) return;
2102 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2103 list_add_tail(&pTL->ref_list, &ref->entry);
2105 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2106 /* external typelib */
2107 MSFT_ImpInfo impinfo;
2108 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2110 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2112 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2113 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2114 while (pImpLib){ /* search the known offsets of all import libraries */
2115 if(pImpLib->offset==impinfo.oImpFile) break;
2116 pImpLib=pImpLib->next;
2118 if(pImpLib){
2119 ref->reference = offset;
2120 ref->pImpTLInfo = pImpLib;
2121 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2122 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2123 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2124 ref->index = TLB_REF_USE_GUID;
2125 } else
2126 ref->index = impinfo.oGuid;
2127 }else{
2128 ERR("Cannot find a reference\n");
2129 ref->reference = -1;
2130 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2132 }else{
2133 /* in this typelib */
2134 ref->index = MSFT_HREFTYPE_INDEX(offset);
2135 ref->reference = offset;
2136 ref->pImpTLInfo = TLB_REF_INTERNAL;
2140 /* process Implemented Interfaces of a com class */
2141 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2142 int offset)
2144 int i;
2145 MSFT_RefRecord refrec;
2146 TLBImplType **ppImpl = &pTI->impltypelist;
2148 TRACE_(typelib)("\n");
2150 for(i=0;i<count;i++){
2151 if(offset<0) break; /* paranoia */
2152 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2153 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2154 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2155 (*ppImpl)->hRef = refrec.reftype;
2156 (*ppImpl)->implflags=refrec.flags;
2157 (*ppImpl)->ctCustData=
2158 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2159 offset=refrec.onext;
2160 ppImpl=&((*ppImpl)->next);
2164 * process a typeinfo record
2166 static ITypeInfoImpl * MSFT_DoTypeInfo(
2167 TLBContext *pcx,
2168 int count,
2169 ITypeLibImpl * pLibInfo)
2171 MSFT_TypeInfoBase tiBase;
2172 ITypeInfoImpl *ptiRet;
2174 TRACE_(typelib)("count=%u\n", count);
2176 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2177 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2178 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2180 /* this is where we are coming from */
2181 ptiRet->pTypeLib = pLibInfo;
2182 ptiRet->index=count;
2183 /* fill in the typeattr fields */
2185 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2186 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2187 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2188 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2189 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2190 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2191 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2192 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2193 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2194 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2195 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2196 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2197 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2198 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2199 MSFT_GetTdesc(pcx, tiBase.datatype1,
2200 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2202 /* FIXME: */
2203 /* IDLDESC idldescType; *//* never saw this one != zero */
2205 /* name, eventually add to a hash table */
2206 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2207 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2208 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2209 /* help info */
2210 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2211 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2212 ptiRet->dwHelpContext=tiBase.helpcontext;
2214 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2215 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2217 /* note: InfoType's Help file and HelpStringDll come from the containing
2218 * library. Further HelpString and Docstring appear to be the same thing :(
2220 /* functions */
2221 if(ptiRet->TypeAttr.cFuncs >0 )
2222 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2223 ptiRet->TypeAttr.cVars,
2224 tiBase.memoffset, & ptiRet->funclist);
2225 /* variables */
2226 if(ptiRet->TypeAttr.cVars >0 )
2227 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2228 ptiRet->TypeAttr.cVars,
2229 tiBase.memoffset, & ptiRet->varlist);
2230 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2231 switch(ptiRet->TypeAttr.typekind)
2233 case TKIND_COCLASS:
2234 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2235 tiBase.datatype1);
2236 break;
2237 case TKIND_DISPATCH:
2238 /* This is not -1 when the interface is a non-base dual interface or
2239 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2240 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2241 not this interface.
2244 if (tiBase.datatype1 != -1)
2246 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2247 ptiRet->impltypelist->hRef = tiBase.datatype1;
2248 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2250 break;
2251 default:
2252 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2253 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2254 ptiRet->impltypelist->hRef = tiBase.datatype1;
2255 break;
2258 ptiRet->ctCustData=
2259 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2261 TRACE_(typelib)("%s guid: %s kind:%s\n",
2262 debugstr_w(ptiRet->Name),
2263 debugstr_guid(&ptiRet->TypeAttr.guid),
2264 typekind_desc[ptiRet->TypeAttr.typekind]);
2265 if (TRACE_ON(typelib))
2266 dump_TypeInfo(ptiRet);
2268 return ptiRet;
2271 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2272 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2273 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2274 * tradeoff here.
2276 static ITypeLibImpl *tlb_cache_first;
2277 static CRITICAL_SECTION cache_section;
2278 static CRITICAL_SECTION_DEBUG cache_section_debug =
2280 0, 0, &cache_section,
2281 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2282 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2284 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2287 typedef struct TLB_PEFile
2289 const IUnknownVtbl *lpvtbl;
2290 LONG refs;
2291 HMODULE dll;
2292 HRSRC typelib_resource;
2293 HGLOBAL typelib_global;
2294 LPVOID typelib_base;
2295 } TLB_PEFile;
2297 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2299 if (IsEqualIID(riid, &IID_IUnknown))
2301 *ppv = iface;
2302 IUnknown_AddRef(iface);
2303 return S_OK;
2305 *ppv = NULL;
2306 return E_NOINTERFACE;
2309 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2311 TLB_PEFile *This = (TLB_PEFile *)iface;
2312 return InterlockedIncrement(&This->refs);
2315 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2317 TLB_PEFile *This = (TLB_PEFile *)iface;
2318 ULONG refs = InterlockedDecrement(&This->refs);
2319 if (!refs)
2321 if (This->typelib_global)
2322 FreeResource(This->typelib_global);
2323 if (This->dll)
2324 FreeLibrary(This->dll);
2325 HeapFree(GetProcessHeap(), 0, This);
2327 return refs;
2330 static const IUnknownVtbl TLB_PEFile_Vtable =
2332 TLB_PEFile_QueryInterface,
2333 TLB_PEFile_AddRef,
2334 TLB_PEFile_Release
2337 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2339 TLB_PEFile *This;
2341 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2342 if (!This)
2343 return E_OUTOFMEMORY;
2345 This->lpvtbl = &TLB_PEFile_Vtable;
2346 This->refs = 1;
2347 This->dll = NULL;
2348 This->typelib_resource = NULL;
2349 This->typelib_global = NULL;
2350 This->typelib_base = NULL;
2352 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2353 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2355 if (This->dll)
2357 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2358 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2359 if (This->typelib_resource)
2361 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2362 if (This->typelib_global)
2364 This->typelib_base = LockResource(This->typelib_global);
2366 if (This->typelib_base)
2368 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2369 *ppBase = This->typelib_base;
2370 *ppFile = (IUnknown *)&This->lpvtbl;
2371 return S_OK;
2377 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2378 return TYPE_E_CANTLOADLIBRARY;
2381 typedef struct TLB_NEFile
2383 const IUnknownVtbl *lpvtbl;
2384 LONG refs;
2385 LPVOID typelib_base;
2386 } TLB_NEFile;
2388 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2390 if (IsEqualIID(riid, &IID_IUnknown))
2392 *ppv = iface;
2393 IUnknown_AddRef(iface);
2394 return S_OK;
2396 *ppv = NULL;
2397 return E_NOINTERFACE;
2400 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2402 TLB_NEFile *This = (TLB_NEFile *)iface;
2403 return InterlockedIncrement(&This->refs);
2406 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2408 TLB_NEFile *This = (TLB_NEFile *)iface;
2409 ULONG refs = InterlockedDecrement(&This->refs);
2410 if (!refs)
2412 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2413 HeapFree(GetProcessHeap(), 0, This);
2415 return refs;
2418 static const IUnknownVtbl TLB_NEFile_Vtable =
2420 TLB_NEFile_QueryInterface,
2421 TLB_NEFile_AddRef,
2422 TLB_NEFile_Release
2425 /***********************************************************************
2426 * read_xx_header [internal]
2428 static int read_xx_header( HFILE lzfd )
2430 IMAGE_DOS_HEADER mzh;
2431 char magic[3];
2433 LZSeek( lzfd, 0, SEEK_SET );
2434 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2435 return 0;
2436 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2437 return 0;
2439 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2440 if ( 2 != LZRead( lzfd, magic, 2 ) )
2441 return 0;
2443 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2445 if ( magic[0] == 'N' && magic[1] == 'E' )
2446 return IMAGE_OS2_SIGNATURE;
2447 if ( magic[0] == 'P' && magic[1] == 'E' )
2448 return IMAGE_NT_SIGNATURE;
2450 magic[2] = '\0';
2451 WARN("Can't handle %s files.\n", magic );
2452 return 0;
2456 /***********************************************************************
2457 * find_ne_resource [internal]
2459 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2460 DWORD *resLen, DWORD *resOff )
2462 IMAGE_OS2_HEADER nehd;
2463 NE_TYPEINFO *typeInfo;
2464 NE_NAMEINFO *nameInfo;
2465 DWORD nehdoffset;
2466 LPBYTE resTab;
2467 DWORD resTabSize;
2468 int count;
2470 /* Read in NE header */
2471 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2472 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2474 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2475 if ( !resTabSize )
2477 TRACE("No resources in NE dll\n" );
2478 return FALSE;
2481 /* Read in resource table */
2482 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2483 if ( !resTab ) return FALSE;
2485 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2486 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2488 HeapFree( GetProcessHeap(), 0, resTab );
2489 return FALSE;
2492 /* Find resource */
2493 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2495 if (HIWORD(typeid) != 0) /* named type */
2497 BYTE len = strlen( typeid );
2498 while (typeInfo->type_id)
2500 if (!(typeInfo->type_id & 0x8000))
2502 BYTE *p = resTab + typeInfo->type_id;
2503 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2505 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2506 typeInfo->count * sizeof(NE_NAMEINFO));
2509 else /* numeric type id */
2511 WORD id = LOWORD(typeid) | 0x8000;
2512 while (typeInfo->type_id)
2514 if (typeInfo->type_id == id) goto found_type;
2515 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2516 typeInfo->count * sizeof(NE_NAMEINFO));
2519 TRACE("No typeid entry found for %p\n", typeid );
2520 HeapFree( GetProcessHeap(), 0, resTab );
2521 return FALSE;
2523 found_type:
2524 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2526 if (HIWORD(resid) != 0) /* named resource */
2528 BYTE len = strlen( resid );
2529 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2531 BYTE *p = resTab + nameInfo->id;
2532 if (nameInfo->id & 0x8000) continue;
2533 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2536 else /* numeric resource id */
2538 WORD id = LOWORD(resid) | 0x8000;
2539 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2540 if (nameInfo->id == id) goto found_name;
2542 TRACE("No resid entry found for %p\n", typeid );
2543 HeapFree( GetProcessHeap(), 0, resTab );
2544 return FALSE;
2546 found_name:
2547 /* Return resource data */
2548 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2549 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2551 HeapFree( GetProcessHeap(), 0, resTab );
2552 return TRUE;
2555 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2557 HFILE lzfd = -1;
2558 OFSTRUCT ofs;
2559 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2560 TLB_NEFile *This = NULL;
2562 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2563 if (!This) return E_OUTOFMEMORY;
2565 This->lpvtbl = &TLB_NEFile_Vtable;
2566 This->refs = 1;
2567 This->typelib_base = NULL;
2569 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2570 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2572 DWORD reslen, offset;
2573 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2575 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2576 if( !This->typelib_base )
2577 hr = E_OUTOFMEMORY;
2578 else
2580 LZSeek( lzfd, offset, SEEK_SET );
2581 reslen = LZRead( lzfd, This->typelib_base, reslen );
2582 LZClose( lzfd );
2583 *ppBase = This->typelib_base;
2584 *pdwTLBLength = reslen;
2585 *ppFile = (IUnknown *)&This->lpvtbl;
2586 return S_OK;
2591 if( lzfd >= 0) LZClose( lzfd );
2592 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2593 return hr;
2596 typedef struct TLB_Mapping
2598 const IUnknownVtbl *lpvtbl;
2599 LONG refs;
2600 HANDLE file;
2601 HANDLE mapping;
2602 LPVOID typelib_base;
2603 } TLB_Mapping;
2605 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2607 if (IsEqualIID(riid, &IID_IUnknown))
2609 *ppv = iface;
2610 IUnknown_AddRef(iface);
2611 return S_OK;
2613 *ppv = NULL;
2614 return E_NOINTERFACE;
2617 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2619 TLB_Mapping *This = (TLB_Mapping *)iface;
2620 return InterlockedIncrement(&This->refs);
2623 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2625 TLB_Mapping *This = (TLB_Mapping *)iface;
2626 ULONG refs = InterlockedDecrement(&This->refs);
2627 if (!refs)
2629 if (This->typelib_base)
2630 UnmapViewOfFile(This->typelib_base);
2631 if (This->mapping)
2632 CloseHandle(This->mapping);
2633 if (This->file != INVALID_HANDLE_VALUE)
2634 CloseHandle(This->file);
2635 HeapFree(GetProcessHeap(), 0, This);
2637 return refs;
2640 static const IUnknownVtbl TLB_Mapping_Vtable =
2642 TLB_Mapping_QueryInterface,
2643 TLB_Mapping_AddRef,
2644 TLB_Mapping_Release
2647 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2649 TLB_Mapping *This;
2651 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2652 if (!This)
2653 return E_OUTOFMEMORY;
2655 This->lpvtbl = &TLB_Mapping_Vtable;
2656 This->refs = 1;
2657 This->file = INVALID_HANDLE_VALUE;
2658 This->mapping = NULL;
2659 This->typelib_base = NULL;
2661 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2662 if (INVALID_HANDLE_VALUE != This->file)
2664 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2665 if (This->mapping)
2667 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2668 if(This->typelib_base)
2670 /* retrieve file size */
2671 *pdwTLBLength = GetFileSize(This->file, NULL);
2672 *ppBase = This->typelib_base;
2673 *ppFile = (IUnknown *)&This->lpvtbl;
2674 return S_OK;
2679 IUnknown_Release((IUnknown *)&This->lpvtbl);
2680 return TYPE_E_CANTLOADLIBRARY;
2683 /****************************************************************************
2684 * TLB_ReadTypeLib
2686 * find the type of the typelib file and map the typelib resource into
2687 * the memory
2689 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2690 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2691 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2693 ITypeLibImpl *entry;
2694 HRESULT ret;
2695 INT index = 1;
2696 LPWSTR index_str, file = (LPWSTR)pszFileName;
2697 LPVOID pBase = NULL;
2698 DWORD dwTLBLength = 0;
2699 IUnknown *pFile = NULL;
2701 *ppTypeLib = NULL;
2703 index_str = strrchrW(pszFileName, '\\');
2704 if(index_str && *++index_str != '\0')
2706 LPWSTR end_ptr;
2707 long idx = strtolW(index_str, &end_ptr, 10);
2708 if(*end_ptr == '\0')
2710 int str_len = index_str - pszFileName - 1;
2711 index = idx;
2712 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2713 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2714 file[str_len] = 0;
2718 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2720 if(strchrW(file, '\\'))
2722 lstrcpyW(pszPath, file);
2724 else
2726 int len = GetSystemDirectoryW(pszPath, cchPath);
2727 pszPath[len] = '\\';
2728 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2732 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2734 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2736 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2737 EnterCriticalSection(&cache_section);
2738 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2740 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2742 TRACE("cache hit\n");
2743 *ppTypeLib = (ITypeLib2*)entry;
2744 ITypeLib_AddRef(*ppTypeLib);
2745 LeaveCriticalSection(&cache_section);
2746 return S_OK;
2749 LeaveCriticalSection(&cache_section);
2751 /* now actually load and parse the typelib */
2753 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2754 if (ret == TYPE_E_CANTLOADLIBRARY)
2755 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2756 if (ret == TYPE_E_CANTLOADLIBRARY)
2757 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2758 if (SUCCEEDED(ret))
2760 if (dwTLBLength >= 4)
2762 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2763 if (dwSignature == MSFT_SIGNATURE)
2764 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2765 else if (dwSignature == SLTG_SIGNATURE)
2766 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2767 else
2769 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2770 ret = TYPE_E_CANTLOADLIBRARY;
2773 else
2774 ret = TYPE_E_CANTLOADLIBRARY;
2775 IUnknown_Release(pFile);
2778 if(*ppTypeLib) {
2779 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2781 TRACE("adding to cache\n");
2782 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2783 lstrcpyW(impl->path, pszPath);
2784 /* We should really canonicalise the path here. */
2785 impl->index = index;
2787 /* FIXME: check if it has added already in the meantime */
2788 EnterCriticalSection(&cache_section);
2789 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2790 impl->prev = NULL;
2791 tlb_cache_first = impl;
2792 LeaveCriticalSection(&cache_section);
2793 ret = S_OK;
2794 } else
2795 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2797 return ret;
2800 /*================== ITypeLib(2) Methods ===================================*/
2802 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2804 ITypeLibImpl* pTypeLibImpl;
2806 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2807 if (!pTypeLibImpl) return NULL;
2809 pTypeLibImpl->lpVtbl = &tlbvt;
2810 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2811 pTypeLibImpl->ref = 1;
2813 list_init(&pTypeLibImpl->ref_list);
2814 pTypeLibImpl->dispatch_href = -1;
2816 return pTypeLibImpl;
2819 /****************************************************************************
2820 * ITypeLib2_Constructor_MSFT
2822 * loading an MSFT typelib from an in-memory image
2824 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2826 TLBContext cx;
2827 long lPSegDir;
2828 MSFT_Header tlbHeader;
2829 MSFT_SegDir tlbSegDir;
2830 ITypeLibImpl * pTypeLibImpl;
2832 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2834 pTypeLibImpl = TypeLibImpl_Constructor();
2835 if (!pTypeLibImpl) return NULL;
2837 /* get pointer to beginning of typelib data */
2838 cx.pos = 0;
2839 cx.oStart=0;
2840 cx.mapping = pLib;
2841 cx.pLibInfo = pTypeLibImpl;
2842 cx.length = dwTLBLength;
2844 /* read header */
2845 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2846 TRACE_(typelib)("header:\n");
2847 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2848 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2849 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2850 return NULL;
2852 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2854 /* there is a small amount of information here until the next important
2855 * part:
2856 * the segment directory . Try to calculate the amount of data */
2857 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2859 /* now read the segment directory */
2860 TRACE("read segment directory (at %ld)\n",lPSegDir);
2861 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2862 cx.pTblDir = &tlbSegDir;
2864 /* just check two entries */
2865 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2867 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2868 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2869 return NULL;
2872 /* now fill our internal data */
2873 /* TLIBATTR fields */
2874 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2876 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2877 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2878 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2879 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2880 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2882 pTypeLibImpl->lcid = tlbHeader.lcid;
2884 /* name, eventually add to a hash table */
2885 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2887 /* help info */
2888 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2889 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2891 if( tlbHeader.varflags & HELPDLLFLAG)
2893 int offset;
2894 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2895 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2898 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2900 /* custom data */
2901 if(tlbHeader.CustomDataOffset >= 0)
2903 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2906 /* fill in type descriptions */
2907 if(tlbSegDir.pTypdescTab.length > 0)
2909 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2910 INT16 td[4];
2911 pTypeLibImpl->ctTypeDesc = cTD;
2912 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2913 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2914 for(i=0; i<cTD; )
2916 /* FIXME: add several sanity checks here */
2917 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2918 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2920 /* FIXME: check safearray */
2921 if(td[3] < 0)
2922 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2923 else
2924 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2926 else if(td[0] == VT_CARRAY)
2928 /* array descr table here */
2929 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2931 else if(td[0] == VT_USERDEFINED)
2933 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2935 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2938 /* second time around to fill the array subscript info */
2939 for(i=0;i<cTD;i++)
2941 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2942 if(tlbSegDir.pArrayDescriptions.offset>0)
2944 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2945 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2947 if(td[1]<0)
2948 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2949 else
2950 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2952 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2954 for(j = 0; j<td[2]; j++)
2956 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2957 sizeof(INT), &cx, DO_NOT_SEEK);
2958 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2959 sizeof(INT), &cx, DO_NOT_SEEK);
2962 else
2964 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2965 ERR("didn't find array description data\n");
2970 /* imported type libs */
2971 if(tlbSegDir.pImpFiles.offset>0)
2973 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2974 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2975 UINT16 size;
2977 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2979 char *name;
2981 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2982 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2983 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2985 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2986 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2987 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2988 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2990 size >>= 2;
2991 name = TLB_Alloc(size+1);
2992 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2993 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2995 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2996 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2998 ppImpLib = &(*ppImpLib)->next;
3002 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3003 if(pTypeLibImpl->dispatch_href != -1)
3004 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3006 /* type info's */
3007 if(tlbHeader.nrtypeinfos >= 0 )
3009 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3010 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3011 int i;
3013 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3015 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3017 ppTI = &((*ppTI)->next);
3018 (pTypeLibImpl->TypeInfoCount)++;
3022 TRACE("(%p)\n", pTypeLibImpl);
3023 return (ITypeLib2*) pTypeLibImpl;
3027 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3029 char b[3];
3030 int i;
3031 short s;
3033 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3034 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3035 return FALSE;
3038 guid->Data4[0] = s >> 8;
3039 guid->Data4[1] = s & 0xff;
3041 b[2] = '\0';
3042 for(i = 0; i < 6; i++) {
3043 memcpy(b, str + 24 + 2 * i, 2);
3044 guid->Data4[i + 2] = strtol(b, NULL, 16);
3046 return TRUE;
3049 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3051 WORD bytelen;
3052 DWORD len;
3054 *pBstr = NULL;
3055 bytelen = *(const WORD*)ptr;
3056 if(bytelen == 0xffff) return 2;
3057 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3058 *pBstr = SysAllocStringLen(NULL, len);
3059 if (*pBstr)
3060 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3061 return bytelen + 2;
3064 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3066 WORD bytelen;
3068 *str = NULL;
3069 bytelen = *(const WORD*)ptr;
3070 if(bytelen == 0xffff) return 2;
3071 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3072 memcpy(*str, ptr + 2, bytelen);
3073 (*str)[bytelen] = '\0';
3074 return bytelen + 2;
3077 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3079 char *ptr = pLibBlk;
3080 WORD w;
3082 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3083 FIXME("libblk magic = %04x\n", w);
3084 return 0;
3087 ptr += 6;
3088 if((w = *(WORD*)ptr) != 0xffff) {
3089 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3090 ptr += w;
3092 ptr += 2;
3094 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3096 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3098 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3099 ptr += 4;
3101 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3102 ptr += 2;
3104 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3105 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3106 else
3107 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3108 ptr += 2;
3110 ptr += 4; /* skip res12 */
3112 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3113 ptr += 2;
3115 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3116 ptr += 2;
3118 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3119 ptr += 2;
3121 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3122 ptr += sizeof(GUID);
3124 return ptr - (char*)pLibBlk;
3127 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3128 typedef struct
3130 unsigned int num;
3131 HREFTYPE refs[1];
3132 } sltg_ref_lookup_t;
3134 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3135 HREFTYPE *typelib_ref)
3137 if(table && typeinfo_ref < table->num)
3139 *typelib_ref = table->refs[typeinfo_ref];
3140 return S_OK;
3143 ERR_(typelib)("Unable to find reference\n");
3144 *typelib_ref = -1;
3145 return E_FAIL;
3148 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3150 BOOL done = FALSE;
3152 while(!done) {
3153 if((*pType & 0xe00) == 0xe00) {
3154 pTD->vt = VT_PTR;
3155 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3156 sizeof(TYPEDESC));
3157 pTD = pTD->u.lptdesc;
3159 switch(*pType & 0x3f) {
3160 case VT_PTR:
3161 pTD->vt = VT_PTR;
3162 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3163 sizeof(TYPEDESC));
3164 pTD = pTD->u.lptdesc;
3165 break;
3167 case VT_USERDEFINED:
3168 pTD->vt = VT_USERDEFINED;
3169 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3170 done = TRUE;
3171 break;
3173 case VT_CARRAY:
3175 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3176 array */
3178 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3180 pTD->vt = VT_CARRAY;
3181 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3182 sizeof(ARRAYDESC) +
3183 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3184 pTD->u.lpadesc->cDims = pSA->cDims;
3185 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3186 pSA->cDims * sizeof(SAFEARRAYBOUND));
3188 pTD = &pTD->u.lpadesc->tdescElem;
3189 break;
3192 case VT_SAFEARRAY:
3194 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3195 useful? */
3197 pType++;
3198 pTD->vt = VT_SAFEARRAY;
3199 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3200 sizeof(TYPEDESC));
3201 pTD = pTD->u.lptdesc;
3202 break;
3204 default:
3205 pTD->vt = *pType & 0x3f;
3206 done = TRUE;
3207 break;
3209 pType++;
3211 return pType;
3214 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3215 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3217 /* Handle [in/out] first */
3218 if((*pType & 0xc000) == 0xc000)
3219 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3220 else if(*pType & 0x8000)
3221 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3222 else if(*pType & 0x4000)
3223 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3224 else
3225 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3227 if(*pType & 0x2000)
3228 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3230 if(*pType & 0x80)
3231 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3233 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3237 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3238 char *pNameTable)
3240 unsigned int ref;
3241 char *name;
3242 TLBRefType *ref_type;
3243 sltg_ref_lookup_t *table;
3244 HREFTYPE typelib_ref;
3246 if(pRef->magic != SLTG_REF_MAGIC) {
3247 FIXME("Ref magic = %x\n", pRef->magic);
3248 return NULL;
3250 name = ( (char*)pRef->names + pRef->number);
3252 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3253 table->num = pRef->number >> 3;
3255 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3257 /* We don't want the first href to be 0 */
3258 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3260 for(ref = 0; ref < pRef->number >> 3; ref++) {
3261 char *refname;
3262 unsigned int lib_offs, type_num;
3264 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3266 name += SLTG_ReadStringA(name, &refname);
3267 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3268 FIXME_(typelib)("Can't sscanf ref\n");
3269 if(lib_offs != 0xffff) {
3270 TLBImpLib **import = &pTL->pImpLibs;
3272 while(*import) {
3273 if((*import)->offset == lib_offs)
3274 break;
3275 import = &(*import)->next;
3277 if(!*import) {
3278 char fname[MAX_PATH+1];
3279 int len;
3281 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3282 sizeof(**import));
3283 (*import)->offset = lib_offs;
3284 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3285 &(*import)->guid);
3286 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3287 &(*import)->wVersionMajor,
3288 &(*import)->wVersionMinor,
3289 &(*import)->lcid, fname) != 4) {
3290 FIXME_(typelib)("can't sscanf ref %s\n",
3291 pNameTable + lib_offs + 40);
3293 len = strlen(fname);
3294 if(fname[len-1] != '#')
3295 FIXME("fname = %s\n", fname);
3296 fname[len-1] = '\0';
3297 (*import)->name = TLB_MultiByteToBSTR(fname);
3299 ref_type->pImpTLInfo = *import;
3301 /* Store a reference to IDispatch */
3302 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3303 pTL->dispatch_href = typelib_ref;
3305 } else { /* internal ref */
3306 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3308 ref_type->reference = typelib_ref;
3309 ref_type->index = type_num;
3311 HeapFree(GetProcessHeap(), 0, refname);
3312 list_add_tail(&pTL->ref_list, &ref_type->entry);
3314 table->refs[ref] = typelib_ref;
3315 typelib_ref += 4;
3317 if((BYTE)*name != SLTG_REF_MAGIC)
3318 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3319 dump_TLBRefType(pTL);
3320 return table;
3323 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3324 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3326 SLTG_ImplInfo *info;
3327 TLBImplType **ppImplType = &pTI->impltypelist;
3328 /* I don't really get this structure, usually it's 0x16 bytes
3329 long, but iuser.tlb contains some that are 0x18 bytes long.
3330 That's ok because we can use the next ptr to jump to the next
3331 one. But how do we know the length of the last one? The WORD
3332 at offs 0x8 might be the clue. For now I'm just assuming that
3333 the last one is the regular 0x16 bytes. */
3335 info = (SLTG_ImplInfo*)pBlk;
3336 while(1) {
3337 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3338 sizeof(**ppImplType));
3339 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3340 (*ppImplType)->implflags = info->impltypeflags;
3341 pTI->TypeAttr.cImplTypes++;
3342 ppImplType = &(*ppImplType)->next;
3344 if(info->next == 0xffff)
3345 break;
3346 if(OneOnly)
3347 FIXME_(typelib)("Interface inheriting more than one interface\n");
3348 info = (SLTG_ImplInfo*)(pBlk + info->next);
3350 info++; /* see comment at top of function */
3351 return (char*)info;
3354 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3355 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3357 TLBVarDesc **ppVarDesc = &pTI->varlist;
3358 BSTR bstrPrevName = NULL;
3359 SLTG_Variable *pItem;
3360 unsigned short i;
3361 WORD *pType;
3363 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3364 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3366 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3367 sizeof(**ppVarDesc));
3368 (*ppVarDesc)->vardesc.memid = pItem->memid;
3370 if (pItem->magic != SLTG_VAR_MAGIC &&
3371 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3372 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3373 return;
3376 if (pItem->name == 0xfffe)
3377 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3378 else
3379 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3381 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3382 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3383 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3385 if(pItem->flags & 0x02)
3386 pType = &pItem->type;
3387 else
3388 pType = (WORD*)(pBlk + pItem->type);
3390 if (pItem->flags & ~0xda)
3391 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3393 SLTG_DoElem(pType, pBlk,
3394 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3396 if (TRACE_ON(typelib)) {
3397 char buf[300];
3398 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3399 TRACE_(typelib)("elemdescVar: %s\n", buf);
3402 if (pItem->flags & 0x40) {
3403 TRACE_(typelib)("VAR_DISPATCH\n");
3404 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3406 else if (pItem->flags & 0x10) {
3407 TRACE_(typelib)("VAR_CONST\n");
3408 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3409 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3410 sizeof(VARIANT));
3411 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3412 if (pItem->flags & 0x08)
3413 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3414 else {
3415 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3417 case VT_LPSTR:
3418 case VT_LPWSTR:
3419 case VT_BSTR:
3421 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3422 BSTR str;
3423 TRACE_(typelib)("len = %u\n", len);
3424 if (len == 0xffff) {
3425 str = NULL;
3426 } else {
3427 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3428 str = SysAllocStringLen(NULL, alloc_len);
3429 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3431 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3432 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3433 break;
3435 case VT_I2:
3436 case VT_UI2:
3437 case VT_I4:
3438 case VT_UI4:
3439 case VT_INT:
3440 case VT_UINT:
3441 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3442 *(INT*)(pBlk + pItem->byte_offs);
3443 break;
3444 default:
3445 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3449 else {
3450 TRACE_(typelib)("VAR_PERINSTANCE\n");
3451 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3452 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3455 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3456 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3458 if (pItem->flags & 0x80)
3459 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3461 bstrPrevName = (*ppVarDesc)->Name;
3462 ppVarDesc = &((*ppVarDesc)->next);
3464 pTI->TypeAttr.cVars = cVars;
3467 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3468 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3470 SLTG_Function *pFunc;
3471 unsigned short i;
3472 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3474 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3475 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3477 int param;
3478 WORD *pType, *pArg;
3480 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3481 sizeof(**ppFuncDesc));
3483 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3484 case SLTG_FUNCTION_MAGIC:
3485 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3486 break;
3487 case SLTG_DISPATCH_FUNCTION_MAGIC:
3488 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3489 break;
3490 case SLTG_STATIC_FUNCTION_MAGIC:
3491 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3492 break;
3493 default:
3494 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3495 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3496 *ppFuncDesc = NULL;
3497 return;
3499 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3501 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3502 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3503 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3504 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3505 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3506 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3508 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3509 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3511 if(pFunc->retnextopt & 0x80)
3512 pType = &pFunc->rettype;
3513 else
3514 pType = (WORD*)(pBlk + pFunc->rettype);
3516 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3518 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3519 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3520 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3521 (*ppFuncDesc)->pParamDesc =
3522 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3523 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3525 pArg = (WORD*)(pBlk + pFunc->arg_off);
3527 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3528 char *paramName = pNameTable + *pArg;
3529 BOOL HaveOffs;
3530 /* If arg type follows then paramName points to the 2nd
3531 letter of the name, else the next WORD is an offset to
3532 the arg type and paramName points to the first letter.
3533 So let's take one char off paramName and see if we're
3534 pointing at an alpha-numeric char. However if *pArg is
3535 0xffff or 0xfffe then the param has no name, the former
3536 meaning that the next WORD is the type, the latter
3537 meaning that the next WORD is an offset to the type. */
3539 HaveOffs = FALSE;
3540 if(*pArg == 0xffff)
3541 paramName = NULL;
3542 else if(*pArg == 0xfffe) {
3543 paramName = NULL;
3544 HaveOffs = TRUE;
3546 else if(paramName[-1] && !isalnum(paramName[-1]))
3547 HaveOffs = TRUE;
3549 pArg++;
3551 if(HaveOffs) { /* the next word is an offset to type */
3552 pType = (WORD*)(pBlk + *pArg);
3553 SLTG_DoElem(pType, pBlk,
3554 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3555 pArg++;
3556 } else {
3557 if(paramName)
3558 paramName--;
3559 pArg = SLTG_DoElem(pArg, pBlk,
3560 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3563 /* Are we an optional param ? */
3564 if((*ppFuncDesc)->funcdesc.cParams - param <=
3565 (*ppFuncDesc)->funcdesc.cParamsOpt)
3566 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3568 if(paramName) {
3569 (*ppFuncDesc)->pParamDesc[param].Name =
3570 TLB_MultiByteToBSTR(paramName);
3571 } else {
3572 (*ppFuncDesc)->pParamDesc[param].Name =
3573 SysAllocString((*ppFuncDesc)->Name);
3577 ppFuncDesc = &((*ppFuncDesc)->next);
3578 if(pFunc->next == 0xffff) break;
3580 pTI->TypeAttr.cFuncs = cFuncs;
3583 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3584 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3585 SLTG_TypeInfoTail *pTITail)
3587 char *pFirstItem;
3588 sltg_ref_lookup_t *ref_lookup = NULL;
3590 if(pTIHeader->href_table != 0xffffffff) {
3591 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3592 pNameTable);
3595 pFirstItem = pBlk;
3597 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3598 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3600 HeapFree(GetProcessHeap(), 0, ref_lookup);
3604 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3605 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3606 const SLTG_TypeInfoTail *pTITail)
3608 char *pFirstItem;
3609 sltg_ref_lookup_t *ref_lookup = NULL;
3611 if(pTIHeader->href_table != 0xffffffff) {
3612 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3613 pNameTable);
3616 pFirstItem = pBlk;
3618 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3619 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3622 if (pTITail->funcs_off != 0xffff)
3623 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3625 HeapFree(GetProcessHeap(), 0, ref_lookup);
3627 if (TRACE_ON(typelib))
3628 dump_TLBFuncDesc(pTI->funclist);
3631 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3632 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3633 const SLTG_TypeInfoTail *pTITail)
3635 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3638 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3639 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3640 const SLTG_TypeInfoTail *pTITail)
3642 WORD *pType;
3643 sltg_ref_lookup_t *ref_lookup = NULL;
3645 if (pTITail->simple_alias) {
3646 /* if simple alias, no more processing required */
3647 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3648 return;
3651 if(pTIHeader->href_table != 0xffffffff) {
3652 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3653 pNameTable);
3656 /* otherwise it is an offset to a type */
3657 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3659 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3661 HeapFree(GetProcessHeap(), 0, ref_lookup);
3664 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3665 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3666 const SLTG_TypeInfoTail *pTITail)
3668 sltg_ref_lookup_t *ref_lookup = NULL;
3669 if (pTIHeader->href_table != 0xffffffff)
3670 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3671 pNameTable);
3673 if (pTITail->vars_off != 0xffff)
3674 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3676 if (pTITail->funcs_off != 0xffff)
3677 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3679 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3680 * of dispinterface functions including the IDispatch ones, so
3681 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3682 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3684 HeapFree(GetProcessHeap(), 0, ref_lookup);
3685 if (TRACE_ON(typelib))
3686 dump_TLBFuncDesc(pTI->funclist);
3689 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3690 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3691 const SLTG_TypeInfoTail *pTITail)
3693 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3696 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3697 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3698 const SLTG_TypeInfoTail *pTITail)
3700 sltg_ref_lookup_t *ref_lookup = NULL;
3701 if (pTIHeader->href_table != 0xffffffff)
3702 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3703 pNameTable);
3705 if (pTITail->vars_off != 0xffff)
3706 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3708 if (pTITail->funcs_off != 0xffff)
3709 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3710 HeapFree(GetProcessHeap(), 0, ref_lookup);
3711 if (TRACE_ON(typelib))
3712 dump_TypeInfo(pTI);
3715 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3716 managable copy of it into this */
3717 typedef struct {
3718 WORD small_no;
3719 char *index_name;
3720 char *other_name;
3721 WORD res1a;
3722 WORD name_offs;
3723 WORD more_bytes;
3724 char *extra;
3725 WORD res20;
3726 DWORD helpcontext;
3727 WORD res26;
3728 GUID uuid;
3729 } SLTG_InternalOtherTypeInfo;
3731 /****************************************************************************
3732 * ITypeLib2_Constructor_SLTG
3734 * loading a SLTG typelib from an in-memory image
3736 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3738 ITypeLibImpl *pTypeLibImpl;
3739 SLTG_Header *pHeader;
3740 SLTG_BlkEntry *pBlkEntry;
3741 SLTG_Magic *pMagic;
3742 SLTG_Index *pIndex;
3743 SLTG_Pad9 *pPad9;
3744 LPVOID pBlk, pFirstBlk;
3745 SLTG_LibBlk *pLibBlk;
3746 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3747 char *pAfterOTIBlks = NULL;
3748 char *pNameTable, *ptr;
3749 int i;
3750 DWORD len, order;
3751 ITypeInfoImpl **ppTypeInfoImpl;
3753 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3756 pTypeLibImpl = TypeLibImpl_Constructor();
3757 if (!pTypeLibImpl) return NULL;
3759 pHeader = pLib;
3761 TRACE_(typelib)("header:\n");
3762 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3763 pHeader->nrOfFileBlks );
3764 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3765 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3766 pHeader->SLTG_magic);
3767 return NULL;
3770 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3771 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3773 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3774 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3776 /* Next we have a magic block */
3777 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3779 /* Let's see if we're still in sync */
3780 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3781 sizeof(SLTG_COMPOBJ_MAGIC))) {
3782 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3783 return NULL;
3785 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3786 sizeof(SLTG_DIR_MAGIC))) {
3787 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3788 return NULL;
3791 pIndex = (SLTG_Index*)(pMagic+1);
3793 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3795 pFirstBlk = pPad9 + 1;
3797 /* We'll set up a ptr to the main library block, which is the last one. */
3799 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3800 pBlkEntry[order].next != 0;
3801 order = pBlkEntry[order].next - 1, i++) {
3802 pBlk = (char*)pBlk + pBlkEntry[order].len;
3804 pLibBlk = pBlk;
3806 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3808 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3809 interspersed */
3811 len += 0x40;
3813 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3815 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3816 sizeof(*pOtherTypeInfoBlks) *
3817 pTypeLibImpl->TypeInfoCount);
3820 ptr = (char*)pLibBlk + len;
3822 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3823 WORD w, extra;
3824 len = 0;
3826 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3828 w = *(WORD*)(ptr + 2);
3829 if(w != 0xffff) {
3830 len += w;
3831 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3832 w+1);
3833 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3834 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3836 w = *(WORD*)(ptr + 4 + len);
3837 if(w != 0xffff) {
3838 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3839 len += w;
3840 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3841 w+1);
3842 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3843 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3845 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3846 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3847 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3848 if(extra) {
3849 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3850 extra);
3851 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3852 len += extra;
3854 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3855 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3856 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3857 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3858 len += sizeof(SLTG_OtherTypeInfo);
3859 ptr += len;
3862 pAfterOTIBlks = ptr;
3864 /* Skip this WORD and get the next DWORD */
3865 len = *(DWORD*)(pAfterOTIBlks + 2);
3867 /* Now add this to pLibBLk look at what we're pointing at and
3868 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3869 dust and we should be pointing at the beginning of the name
3870 table */
3872 pNameTable = (char*)pLibBlk + len;
3874 switch(*(WORD*)pNameTable) {
3875 case 0xffff:
3876 break;
3877 case 0x0200:
3878 pNameTable += 0x20;
3879 break;
3880 default:
3881 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3882 break;
3885 pNameTable += 0x216;
3887 pNameTable += 2;
3889 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3891 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3894 /* Hopefully we now have enough ptrs set up to actually read in
3895 some TypeInfos. It's not clear which order to do them in, so
3896 I'll just follow the links along the BlkEntry chain and read
3897 them in the order in which they are in the file */
3899 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3901 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3902 pBlkEntry[order].next != 0;
3903 order = pBlkEntry[order].next - 1, i++) {
3905 SLTG_TypeInfoHeader *pTIHeader;
3906 SLTG_TypeInfoTail *pTITail;
3907 SLTG_MemberHeader *pMemHeader;
3909 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3910 pOtherTypeInfoBlks[i].index_name)) {
3911 FIXME_(typelib)("Index strings don't match\n");
3912 return NULL;
3915 pTIHeader = pBlk;
3916 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3917 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3918 return NULL;
3920 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3921 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3922 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3924 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3925 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3926 (*ppTypeInfoImpl)->index = i;
3927 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3928 pOtherTypeInfoBlks[i].name_offs +
3929 pNameTable);
3930 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3931 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3932 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3933 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3934 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3935 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3936 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3938 if((pTIHeader->typeflags1 & 7) != 2)
3939 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3940 if(pTIHeader->typeflags3 != 2)
3941 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3943 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3944 debugstr_w((*ppTypeInfoImpl)->Name),
3945 typekind_desc[pTIHeader->typekind],
3946 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3947 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3949 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3951 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3953 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3954 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3955 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3957 switch(pTIHeader->typekind) {
3958 case TKIND_ENUM:
3959 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3960 pTIHeader, pTITail);
3961 break;
3963 case TKIND_RECORD:
3964 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3965 pTIHeader, pTITail);
3966 break;
3968 case TKIND_INTERFACE:
3969 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3970 pTIHeader, pTITail);
3971 break;
3973 case TKIND_COCLASS:
3974 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3975 pTIHeader, pTITail);
3976 break;
3978 case TKIND_ALIAS:
3979 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3980 pTIHeader, pTITail);
3981 break;
3983 case TKIND_DISPATCH:
3984 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3985 pTIHeader, pTITail);
3986 break;
3988 case TKIND_MODULE:
3989 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3990 pTIHeader, pTITail);
3991 break;
3993 default:
3994 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3995 break;
3999 /* could get cFuncs, cVars and cImplTypes from here
4000 but we've already set those */
4001 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4002 X(06);
4003 X(16);
4004 X(18);
4005 X(1a);
4006 X(1e);
4007 X(24);
4008 X(26);
4009 X(2a);
4010 X(2c);
4011 X(2e);
4012 X(30);
4013 X(32);
4014 X(34);
4015 #undef X
4016 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4017 pBlk = (char*)pBlk + pBlkEntry[order].len;
4020 if(i != pTypeLibImpl->TypeInfoCount) {
4021 FIXME("Somehow processed %d TypeInfos\n", i);
4022 return NULL;
4025 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4026 return (ITypeLib2*)pTypeLibImpl;
4029 /* ITypeLib::QueryInterface
4031 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4032 ITypeLib2 * iface,
4033 REFIID riid,
4034 VOID **ppvObject)
4036 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4038 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4040 *ppvObject=NULL;
4041 if(IsEqualIID(riid, &IID_IUnknown) ||
4042 IsEqualIID(riid,&IID_ITypeLib)||
4043 IsEqualIID(riid,&IID_ITypeLib2))
4045 *ppvObject = This;
4048 if(*ppvObject)
4050 ITypeLib2_AddRef(iface);
4051 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4052 return S_OK;
4054 TRACE("-- Interface: E_NOINTERFACE\n");
4055 return E_NOINTERFACE;
4058 /* ITypeLib::AddRef
4060 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4062 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4063 ULONG ref = InterlockedIncrement(&This->ref);
4065 TRACE("(%p)->ref was %u\n",This, ref - 1);
4067 return ref;
4070 /* ITypeLib::Release
4072 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4074 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4075 ULONG ref = InterlockedDecrement(&This->ref);
4077 TRACE("(%p)->(%u)\n",This, ref);
4079 if (!ref)
4081 TLBImpLib *pImpLib, *pImpLibNext;
4082 TLBCustData *pCustData, *pCustDataNext;
4083 TLBRefType *ref_type;
4084 void *cursor2;
4085 int i;
4087 /* remove cache entry */
4088 if(This->path)
4090 TRACE("removing from cache list\n");
4091 EnterCriticalSection(&cache_section);
4092 if (This->next) This->next->prev = This->prev;
4093 if (This->prev) This->prev->next = This->next;
4094 else tlb_cache_first = This->next;
4095 LeaveCriticalSection(&cache_section);
4096 HeapFree(GetProcessHeap(), 0, This->path);
4098 TRACE(" destroying ITypeLib(%p)\n",This);
4100 SysFreeString(This->Name);
4101 This->Name = NULL;
4103 SysFreeString(This->DocString);
4104 This->DocString = NULL;
4106 SysFreeString(This->HelpFile);
4107 This->HelpFile = NULL;
4109 SysFreeString(This->HelpStringDll);
4110 This->HelpStringDll = NULL;
4112 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4114 VariantClear(&pCustData->data);
4116 pCustDataNext = pCustData->next;
4117 TLB_Free(pCustData);
4120 for (i = 0; i < This->ctTypeDesc; i++)
4121 if (This->pTypeDesc[i].vt == VT_CARRAY)
4122 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4124 TLB_Free(This->pTypeDesc);
4126 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4128 if (pImpLib->pImpTypeLib)
4129 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4130 SysFreeString(pImpLib->name);
4132 pImpLibNext = pImpLib->next;
4133 TLB_Free(pImpLib);
4136 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4138 list_remove(&ref_type->entry);
4139 TLB_Free(ref_type);
4142 if (This->pTypeInfo) /* can be NULL */
4143 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4144 HeapFree(GetProcessHeap(),0,This);
4145 return 0;
4148 return ref;
4151 /* ITypeLib::GetTypeInfoCount
4153 * Returns the number of type descriptions in the type library
4155 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4157 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4158 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4159 return This->TypeInfoCount;
4162 /* ITypeLib::GetTypeInfo
4164 * retrieves the specified type description in the library.
4166 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4167 ITypeLib2 *iface,
4168 UINT index,
4169 ITypeInfo **ppTInfo)
4171 UINT i;
4173 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4174 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4176 TRACE("(%p)->(index=%d)\n", This, index);
4178 if (!ppTInfo) return E_INVALIDARG;
4180 /* search element n in list */
4181 for(i=0; i < index; i++)
4183 pTypeInfo = pTypeInfo->next;
4184 if (!pTypeInfo)
4186 TRACE("-- element not found\n");
4187 return TYPE_E_ELEMENTNOTFOUND;
4191 *ppTInfo = (ITypeInfo *) pTypeInfo;
4193 ITypeInfo_AddRef(*ppTInfo);
4194 TRACE("-- found (%p)\n",*ppTInfo);
4195 return S_OK;
4199 /* ITypeLibs::GetTypeInfoType
4201 * Retrieves the type of a type description.
4203 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4204 ITypeLib2 *iface,
4205 UINT index,
4206 TYPEKIND *pTKind)
4208 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4209 UINT i;
4210 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4212 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4213 return TYPE_E_ELEMENTNOTFOUND;
4215 TRACE("(%p) index %d\n", This, index);
4217 if(!pTKind) return E_INVALIDARG;
4219 /* search element n in list */
4220 for(i=0; i < index; i++)
4222 if(!pTInfo)
4224 TRACE("-- element not found\n");
4225 return TYPE_E_ELEMENTNOTFOUND;
4227 pTInfo = pTInfo->next;
4230 *pTKind = pTInfo->TypeAttr.typekind;
4231 TRACE("-- found Type (%d)\n", *pTKind);
4232 return S_OK;
4235 /* ITypeLib::GetTypeInfoOfGuid
4237 * Retrieves the type description that corresponds to the specified GUID.
4240 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4241 ITypeLib2 *iface,
4242 REFGUID guid,
4243 ITypeInfo **ppTInfo)
4245 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4246 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4248 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4250 if (!pTypeInfo)
4252 WARN("-- element not found\n");
4253 return TYPE_E_ELEMENTNOTFOUND;
4256 /* search linked list for guid */
4257 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4259 pTypeInfo = pTypeInfo->next;
4261 if (!pTypeInfo)
4263 /* end of list reached */
4264 WARN("-- element not found\n");
4265 return TYPE_E_ELEMENTNOTFOUND;
4269 TRACE("-- found (%p, %s)\n",
4270 pTypeInfo,
4271 debugstr_w(pTypeInfo->Name));
4273 *ppTInfo = (ITypeInfo*)pTypeInfo;
4274 ITypeInfo_AddRef(*ppTInfo);
4275 return S_OK;
4278 /* ITypeLib::GetLibAttr
4280 * Retrieves the structure that contains the library's attributes.
4283 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4284 ITypeLib2 *iface,
4285 LPTLIBATTR *ppTLibAttr)
4287 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4288 TRACE("(%p)\n",This);
4289 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4290 **ppTLibAttr = This->LibAttr;
4291 return S_OK;
4294 /* ITypeLib::GetTypeComp
4296 * Enables a client compiler to bind to a library's types, variables,
4297 * constants, and global functions.
4300 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4301 ITypeLib2 *iface,
4302 ITypeComp **ppTComp)
4304 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4306 TRACE("(%p)->(%p)\n",This,ppTComp);
4307 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4308 ITypeComp_AddRef(*ppTComp);
4310 return S_OK;
4313 /* ITypeLib::GetDocumentation
4315 * Retrieves the library's documentation string, the complete Help file name
4316 * and path, and the context identifier for the library Help topic in the Help
4317 * file.
4319 * On a successful return all non-null BSTR pointers will have been set,
4320 * possibly to NULL.
4322 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4323 ITypeLib2 *iface,
4324 INT index,
4325 BSTR *pBstrName,
4326 BSTR *pBstrDocString,
4327 DWORD *pdwHelpContext,
4328 BSTR *pBstrHelpFile)
4330 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4332 HRESULT result = E_INVALIDARG;
4334 ITypeInfo *pTInfo;
4337 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4338 This, index,
4339 pBstrName, pBstrDocString,
4340 pdwHelpContext, pBstrHelpFile);
4342 if(index<0)
4344 /* documentation for the typelib */
4345 if(pBstrName)
4347 if (This->Name)
4349 if(!(*pBstrName = SysAllocString(This->Name)))
4350 goto memerr1;
4352 else
4353 *pBstrName = NULL;
4355 if(pBstrDocString)
4357 if (This->DocString)
4359 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4360 goto memerr2;
4362 else if (This->Name)
4364 if(!(*pBstrDocString = SysAllocString(This->Name)))
4365 goto memerr2;
4367 else
4368 *pBstrDocString = NULL;
4370 if(pdwHelpContext)
4372 *pdwHelpContext = This->dwHelpContext;
4374 if(pBstrHelpFile)
4376 if (This->HelpFile)
4378 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4379 goto memerr3;
4381 else
4382 *pBstrHelpFile = NULL;
4385 result = S_OK;
4387 else
4389 /* for a typeinfo */
4390 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4392 if(SUCCEEDED(result))
4394 result = ITypeInfo_GetDocumentation(pTInfo,
4395 MEMBERID_NIL,
4396 pBstrName,
4397 pBstrDocString,
4398 pdwHelpContext, pBstrHelpFile);
4400 ITypeInfo_Release(pTInfo);
4403 return result;
4404 memerr3:
4405 if (pBstrDocString) SysFreeString (*pBstrDocString);
4406 memerr2:
4407 if (pBstrName) SysFreeString (*pBstrName);
4408 memerr1:
4409 return STG_E_INSUFFICIENTMEMORY;
4412 /* ITypeLib::IsName
4414 * Indicates whether a passed-in string contains the name of a type or member
4415 * described in the library.
4418 static HRESULT WINAPI ITypeLib2_fnIsName(
4419 ITypeLib2 *iface,
4420 LPOLESTR szNameBuf,
4421 ULONG lHashVal,
4422 BOOL *pfName)
4424 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4425 ITypeInfoImpl *pTInfo;
4426 TLBFuncDesc *pFInfo;
4427 TLBVarDesc *pVInfo;
4428 int i;
4429 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4431 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4432 pfName);
4434 *pfName=TRUE;
4435 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4436 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4437 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4438 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4439 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4440 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4441 goto ITypeLib2_fnIsName_exit;
4443 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4444 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4447 *pfName=FALSE;
4449 ITypeLib2_fnIsName_exit:
4450 TRACE("(%p)slow! search for %s: %s found!\n", This,
4451 debugstr_w(szNameBuf), *pfName?"NOT":"");
4453 return S_OK;
4456 /* ITypeLib::FindName
4458 * Finds occurrences of a type description in a type library. This may be used
4459 * to quickly verify that a name exists in a type library.
4462 static HRESULT WINAPI ITypeLib2_fnFindName(
4463 ITypeLib2 *iface,
4464 LPOLESTR szNameBuf,
4465 ULONG lHashVal,
4466 ITypeInfo **ppTInfo,
4467 MEMBERID *rgMemId,
4468 UINT16 *pcFound)
4470 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4471 ITypeInfoImpl *pTInfo;
4472 TLBFuncDesc *pFInfo;
4473 TLBVarDesc *pVInfo;
4474 int i,j = 0;
4475 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4477 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4478 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4479 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4480 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4481 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4482 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4483 goto ITypeLib2_fnFindName_exit;
4486 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4487 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4488 continue;
4489 ITypeLib2_fnFindName_exit:
4490 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4491 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4492 j++;
4494 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4495 This, *pcFound, debugstr_w(szNameBuf), j);
4497 *pcFound=j;
4499 return S_OK;
4502 /* ITypeLib::ReleaseTLibAttr
4504 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4507 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4508 ITypeLib2 *iface,
4509 TLIBATTR *pTLibAttr)
4511 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4512 TRACE("freeing (%p)\n",This);
4513 HeapFree(GetProcessHeap(),0,pTLibAttr);
4517 /* ITypeLib2::GetCustData
4519 * gets the custom data
4521 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4522 ITypeLib2 * iface,
4523 REFGUID guid,
4524 VARIANT *pVarVal)
4526 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4527 TLBCustData *pCData;
4529 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4531 if( IsEqualIID(guid, &pCData->guid)) break;
4534 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4536 if(pCData)
4538 VariantInit( pVarVal);
4539 VariantCopy( pVarVal, &pCData->data);
4540 return S_OK;
4542 return E_INVALIDARG; /* FIXME: correct? */
4545 /* ITypeLib2::GetLibStatistics
4547 * Returns statistics about a type library that are required for efficient
4548 * sizing of hash tables.
4551 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4552 ITypeLib2 * iface,
4553 ULONG *pcUniqueNames,
4554 ULONG *pcchUniqueNames)
4556 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4558 FIXME("(%p): stub!\n", This);
4560 if(pcUniqueNames) *pcUniqueNames=1;
4561 if(pcchUniqueNames) *pcchUniqueNames=1;
4562 return S_OK;
4565 /* ITypeLib2::GetDocumentation2
4567 * Retrieves the library's documentation string, the complete Help file name
4568 * and path, the localization context to use, and the context ID for the
4569 * library Help topic in the Help file.
4572 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4573 ITypeLib2 * iface,
4574 INT index,
4575 LCID lcid,
4576 BSTR *pbstrHelpString,
4577 DWORD *pdwHelpStringContext,
4578 BSTR *pbstrHelpStringDll)
4580 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4581 HRESULT result;
4582 ITypeInfo *pTInfo;
4584 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4586 /* the help string should be obtained from the helpstringdll,
4587 * using the _DLLGetDocumentation function, based on the supplied
4588 * lcid. Nice to do sometime...
4590 if(index<0)
4592 /* documentation for the typelib */
4593 if(pbstrHelpString)
4594 *pbstrHelpString=SysAllocString(This->DocString);
4595 if(pdwHelpStringContext)
4596 *pdwHelpStringContext=This->dwHelpContext;
4597 if(pbstrHelpStringDll)
4598 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4600 result = S_OK;
4602 else
4604 /* for a typeinfo */
4605 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4607 if(SUCCEEDED(result))
4609 ITypeInfo2 * pTInfo2;
4610 result = ITypeInfo_QueryInterface(pTInfo,
4611 &IID_ITypeInfo2,
4612 (LPVOID*) &pTInfo2);
4614 if(SUCCEEDED(result))
4616 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4617 MEMBERID_NIL,
4618 lcid,
4619 pbstrHelpString,
4620 pdwHelpStringContext,
4621 pbstrHelpStringDll);
4623 ITypeInfo2_Release(pTInfo2);
4626 ITypeInfo_Release(pTInfo);
4629 return result;
4632 /* ITypeLib2::GetAllCustData
4634 * Gets all custom data items for the library.
4637 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4638 ITypeLib2 * iface,
4639 CUSTDATA *pCustData)
4641 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4642 TLBCustData *pCData;
4643 int i;
4644 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4645 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4646 if(pCustData->prgCustData ){
4647 pCustData->cCustData=This->ctCustData;
4648 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4649 pCustData->prgCustData[i].guid=pCData->guid;
4650 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4652 }else{
4653 ERR(" OUT OF MEMORY!\n");
4654 return E_OUTOFMEMORY;
4656 return S_OK;
4659 static const ITypeLib2Vtbl tlbvt = {
4660 ITypeLib2_fnQueryInterface,
4661 ITypeLib2_fnAddRef,
4662 ITypeLib2_fnRelease,
4663 ITypeLib2_fnGetTypeInfoCount,
4664 ITypeLib2_fnGetTypeInfo,
4665 ITypeLib2_fnGetTypeInfoType,
4666 ITypeLib2_fnGetTypeInfoOfGuid,
4667 ITypeLib2_fnGetLibAttr,
4668 ITypeLib2_fnGetTypeComp,
4669 ITypeLib2_fnGetDocumentation,
4670 ITypeLib2_fnIsName,
4671 ITypeLib2_fnFindName,
4672 ITypeLib2_fnReleaseTLibAttr,
4674 ITypeLib2_fnGetCustData,
4675 ITypeLib2_fnGetLibStatistics,
4676 ITypeLib2_fnGetDocumentation2,
4677 ITypeLib2_fnGetAllCustData
4681 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4683 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4685 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4688 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4690 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4692 return ITypeLib2_AddRef((ITypeLib2 *)This);
4695 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4697 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4699 return ITypeLib2_Release((ITypeLib2 *)This);
4702 static HRESULT WINAPI ITypeLibComp_fnBind(
4703 ITypeComp * iface,
4704 OLECHAR * szName,
4705 ULONG lHash,
4706 WORD wFlags,
4707 ITypeInfo ** ppTInfo,
4708 DESCKIND * pDescKind,
4709 BINDPTR * pBindPtr)
4711 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4712 ITypeInfoImpl *pTypeInfo;
4714 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4716 *pDescKind = DESCKIND_NONE;
4717 pBindPtr->lptcomp = NULL;
4718 *ppTInfo = NULL;
4720 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4722 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4724 /* FIXME: check wFlags here? */
4725 /* FIXME: we should use a hash table to look this info up using lHash
4726 * instead of an O(n) search */
4727 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4728 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4730 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4732 *pDescKind = DESCKIND_TYPECOMP;
4733 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4734 ITypeComp_AddRef(pBindPtr->lptcomp);
4735 TRACE("module or enum: %s\n", debugstr_w(szName));
4736 return S_OK;
4740 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4741 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4743 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4744 HRESULT hr;
4746 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4747 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4749 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4750 return S_OK;
4754 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4755 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4757 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4758 HRESULT hr;
4759 ITypeInfo *subtypeinfo;
4760 BINDPTR subbindptr;
4761 DESCKIND subdesckind;
4763 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4764 &subtypeinfo, &subdesckind, &subbindptr);
4765 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4767 TYPEDESC tdesc_appobject =
4770 (TYPEDESC *)pTypeInfo->hreftype
4772 VT_USERDEFINED
4774 const VARDESC vardesc_appobject =
4776 -2, /* memid */
4777 NULL, /* lpstrSchema */
4779 0 /* oInst */
4782 /* ELEMDESC */
4784 /* TYPEDESC */
4786 &tdesc_appobject
4788 VT_PTR
4791 0, /* wVarFlags */
4792 VAR_STATIC /* varkind */
4795 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4797 /* cleanup things filled in by Bind call so we can put our
4798 * application object data in there instead */
4799 switch (subdesckind)
4801 case DESCKIND_FUNCDESC:
4802 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4803 break;
4804 case DESCKIND_VARDESC:
4805 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4806 break;
4807 default:
4808 break;
4810 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4812 if (pTypeInfo->hreftype == -1)
4813 FIXME("no hreftype for interface %p\n", pTypeInfo);
4815 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4816 if (FAILED(hr))
4817 return hr;
4819 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4820 *ppTInfo = (ITypeInfo *)pTypeInfo;
4821 ITypeInfo_AddRef(*ppTInfo);
4822 return S_OK;
4827 TRACE("name not found %s\n", debugstr_w(szName));
4828 return S_OK;
4831 static HRESULT WINAPI ITypeLibComp_fnBindType(
4832 ITypeComp * iface,
4833 OLECHAR * szName,
4834 ULONG lHash,
4835 ITypeInfo ** ppTInfo,
4836 ITypeComp ** ppTComp)
4838 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4839 ITypeInfoImpl *pTypeInfo;
4841 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4843 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4845 /* FIXME: should use lHash to do the search */
4846 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4848 TRACE("returning %p\n", pTypeInfo);
4849 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4850 ITypeInfo_AddRef(*ppTInfo);
4851 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4852 ITypeComp_AddRef(*ppTComp);
4853 return S_OK;
4857 TRACE("not found\n");
4858 *ppTInfo = NULL;
4859 *ppTComp = NULL;
4860 return S_OK;
4863 static const ITypeCompVtbl tlbtcvt =
4866 ITypeLibComp_fnQueryInterface,
4867 ITypeLibComp_fnAddRef,
4868 ITypeLibComp_fnRelease,
4870 ITypeLibComp_fnBind,
4871 ITypeLibComp_fnBindType
4874 /*================== ITypeInfo(2) Methods ===================================*/
4875 static ITypeInfo2 * ITypeInfo_Constructor(void)
4877 ITypeInfoImpl * pTypeInfoImpl;
4879 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4880 if (pTypeInfoImpl)
4882 pTypeInfoImpl->lpVtbl = &tinfvt;
4883 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4884 pTypeInfoImpl->ref=1;
4885 pTypeInfoImpl->hreftype = -1;
4886 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4887 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4889 TRACE("(%p)\n", pTypeInfoImpl);
4890 return (ITypeInfo2*) pTypeInfoImpl;
4893 /* ITypeInfo::QueryInterface
4895 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4896 ITypeInfo2 *iface,
4897 REFIID riid,
4898 VOID **ppvObject)
4900 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4902 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4904 *ppvObject=NULL;
4905 if(IsEqualIID(riid, &IID_IUnknown) ||
4906 IsEqualIID(riid,&IID_ITypeInfo)||
4907 IsEqualIID(riid,&IID_ITypeInfo2))
4908 *ppvObject = This;
4910 if(*ppvObject){
4911 ITypeInfo_AddRef(iface);
4912 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4913 return S_OK;
4915 TRACE("-- Interface: E_NOINTERFACE\n");
4916 return E_NOINTERFACE;
4919 /* ITypeInfo::AddRef
4921 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4923 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4924 ULONG ref = InterlockedIncrement(&This->ref);
4926 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4928 TRACE("(%p)->ref is %u\n",This, ref);
4929 return ref;
4932 /* ITypeInfo::Release
4934 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4936 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4937 ULONG ref = InterlockedDecrement(&This->ref);
4939 TRACE("(%p)->(%u)\n",This, ref);
4941 if (ref) {
4942 /* We don't release ITypeLib when ref=0 because
4943 it means that function is called by ITypeLib2_Release */
4944 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4945 } else {
4946 TLBFuncDesc *pFInfo, *pFInfoNext;
4947 TLBVarDesc *pVInfo, *pVInfoNext;
4948 TLBImplType *pImpl, *pImplNext;
4950 TRACE("destroying ITypeInfo(%p)\n",This);
4952 if (This->no_free_data)
4953 goto finish_free;
4955 SysFreeString(This->Name);
4956 This->Name = NULL;
4958 SysFreeString(This->DocString);
4959 This->DocString = NULL;
4961 SysFreeString(This->DllName);
4962 This->DllName = NULL;
4964 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4966 INT i;
4967 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4969 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4970 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4972 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4973 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4975 SysFreeString(pFInfo->pParamDesc[i].Name);
4977 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4978 TLB_Free(pFInfo->pParamDesc);
4979 TLB_FreeCustData(pFInfo->pCustData);
4980 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4981 SysFreeString(pFInfo->Entry);
4982 SysFreeString(pFInfo->HelpString);
4983 SysFreeString(pFInfo->Name);
4985 pFInfoNext = pFInfo->next;
4986 TLB_Free(pFInfo);
4988 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4990 if (pVInfo->vardesc.varkind == VAR_CONST)
4992 VariantClear(pVInfo->vardesc.u.lpvarValue);
4993 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4995 TLB_FreeCustData(pVInfo->pCustData);
4996 SysFreeString(pVInfo->Name);
4997 pVInfoNext = pVInfo->next;
4998 TLB_Free(pVInfo);
5000 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5002 TLB_FreeCustData(pImpl->pCustData);
5003 pImplNext = pImpl->next;
5004 TLB_Free(pImpl);
5006 TLB_FreeCustData(This->pCustData);
5008 finish_free:
5009 if (This->next)
5011 ITypeInfo_Release((ITypeInfo*)This->next);
5014 HeapFree(GetProcessHeap(),0,This);
5015 return 0;
5017 return ref;
5020 /* ITypeInfo::GetTypeAttr
5022 * Retrieves a TYPEATTR structure that contains the attributes of the type
5023 * description.
5026 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5027 LPTYPEATTR *ppTypeAttr)
5029 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5030 SIZE_T size;
5032 TRACE("(%p)\n",This);
5034 size = sizeof(**ppTypeAttr);
5035 if (This->TypeAttr.typekind == TKIND_ALIAS)
5036 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5038 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5039 if (!*ppTypeAttr)
5040 return E_OUTOFMEMORY;
5042 **ppTypeAttr = This->TypeAttr;
5044 if (This->TypeAttr.typekind == TKIND_ALIAS)
5045 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5046 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5048 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5049 /* This should include all the inherited funcs */
5050 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5051 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5052 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5054 return S_OK;
5057 /* ITypeInfo::GetTypeComp
5059 * Retrieves the ITypeComp interface for the type description, which enables a
5060 * client compiler to bind to the type description's members.
5063 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5064 ITypeComp * *ppTComp)
5066 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5068 TRACE("(%p)->(%p)\n", This, ppTComp);
5070 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5071 ITypeComp_AddRef(*ppTComp);
5072 return S_OK;
5075 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5077 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5078 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5079 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5080 return size;
5083 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5085 *dest = *src;
5086 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5087 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5089 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5090 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5091 *buffer += sizeof(PARAMDESCEX);
5092 *pparamdescex_dest = *pparamdescex_src;
5093 VariantInit(&pparamdescex_dest->varDefaultValue);
5094 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5095 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5097 else
5098 dest->u.paramdesc.pparamdescex = NULL;
5099 return S_OK;
5102 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5104 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5105 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5108 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5110 FUNCDESC *dest;
5111 char *buffer;
5112 SIZE_T size = sizeof(*src);
5113 SHORT i;
5114 HRESULT hr;
5116 size += sizeof(*src->lprgscode) * src->cScodes;
5117 size += TLB_SizeElemDesc(&src->elemdescFunc);
5118 for (i = 0; i < src->cParams; i++)
5120 size += sizeof(ELEMDESC);
5121 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5124 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5125 if (!dest) return E_OUTOFMEMORY;
5127 *dest = *src;
5128 if (dispinterface) /* overwrite funckind */
5129 dest->funckind = FUNC_DISPATCH;
5130 buffer = (char *)(dest + 1);
5132 dest->lprgscode = (SCODE *)buffer;
5133 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5134 buffer += sizeof(*src->lprgscode) * src->cScodes;
5136 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5137 if (FAILED(hr))
5139 SysFreeString((BSTR)dest);
5140 return hr;
5143 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5144 buffer += sizeof(ELEMDESC) * src->cParams;
5145 for (i = 0; i < src->cParams; i++)
5147 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5148 if (FAILED(hr))
5149 break;
5151 if (FAILED(hr))
5153 /* undo the above actions */
5154 for (i = i - 1; i >= 0; i--)
5155 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5156 TLB_FreeElemDesc(&dest->elemdescFunc);
5157 SysFreeString((BSTR)dest);
5158 return hr;
5161 /* special treatment for dispinterfaces: this makes functions appear
5162 * to return their [retval] value when it is really returning an
5163 * HRESULT */
5164 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5166 if (dest->cParams &&
5167 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5169 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5170 if (elemdesc->tdesc.vt != VT_PTR)
5172 ERR("elemdesc should have started with VT_PTR instead of:\n");
5173 if (ERR_ON(ole))
5174 dump_ELEMDESC(elemdesc);
5175 return E_UNEXPECTED;
5178 /* copy last parameter to the return value. we are using a flat
5179 * buffer so there is no danger of leaking memory in
5180 * elemdescFunc */
5181 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5183 /* remove the last parameter */
5184 dest->cParams--;
5186 else
5187 /* otherwise this function is made to appear to have no return
5188 * value */
5189 dest->elemdescFunc.tdesc.vt = VT_VOID;
5193 *dest_ptr = dest;
5194 return S_OK;
5197 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5199 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5200 const TLBFuncDesc *pFDesc;
5201 UINT i;
5203 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5206 if (pFDesc)
5208 *ppFuncDesc = &pFDesc->funcdesc;
5209 return S_OK;
5212 return TYPE_E_ELEMENTNOTFOUND;
5215 /* internal function to make the inherited interfaces' methods appear
5216 * part of the interface */
5217 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5218 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5220 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5221 HRESULT hr;
5222 UINT implemented_funcs = 0;
5224 if (funcs)
5225 *funcs = 0;
5226 else
5227 *hrefoffset = DISPATCH_HREF_OFFSET;
5229 if(This->impltypelist)
5231 ITypeInfo *pSubTypeInfo;
5232 UINT sub_funcs;
5234 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5235 if (FAILED(hr))
5236 return hr;
5238 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5239 index,
5240 ppFuncDesc,
5241 &sub_funcs, hrefoffset);
5242 implemented_funcs += sub_funcs;
5243 ITypeInfo_Release(pSubTypeInfo);
5244 if (SUCCEEDED(hr))
5245 return hr;
5246 *hrefoffset += DISPATCH_HREF_OFFSET;
5249 if (funcs)
5250 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5251 else
5252 *hrefoffset = 0;
5254 if (index < implemented_funcs)
5255 return E_INVALIDARG;
5256 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5257 ppFuncDesc);
5260 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5262 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5263 while (TRUE)
5265 switch (pTypeDesc->vt)
5267 case VT_USERDEFINED:
5268 pTypeDesc->u.hreftype += hrefoffset;
5269 return;
5270 case VT_PTR:
5271 case VT_SAFEARRAY:
5272 pTypeDesc = pTypeDesc->u.lptdesc;
5273 break;
5274 case VT_CARRAY:
5275 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5276 break;
5277 default:
5278 return;
5283 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5285 SHORT i;
5286 for (i = 0; i < pFuncDesc->cParams; i++)
5287 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5288 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5291 /* ITypeInfo::GetFuncDesc
5293 * Retrieves the FUNCDESC structure that contains information about a
5294 * specified function.
5297 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5298 LPFUNCDESC *ppFuncDesc)
5300 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5301 const FUNCDESC *internal_funcdesc;
5302 HRESULT hr;
5303 UINT hrefoffset = 0;
5305 TRACE("(%p) index %d\n", This, index);
5307 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5308 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5309 &internal_funcdesc, NULL,
5310 &hrefoffset);
5311 else
5312 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5313 &internal_funcdesc);
5314 if (FAILED(hr))
5316 WARN("description for function %d not found\n", index);
5317 return hr;
5320 hr = TLB_AllocAndInitFuncDesc(
5321 internal_funcdesc,
5322 ppFuncDesc,
5323 This->TypeAttr.typekind == TKIND_DISPATCH);
5325 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5326 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5328 TRACE("-- 0x%08x\n", hr);
5329 return hr;
5332 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5334 VARDESC *dest;
5335 char *buffer;
5336 SIZE_T size = sizeof(*src);
5337 HRESULT hr;
5339 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5340 if (src->varkind == VAR_CONST)
5341 size += sizeof(VARIANT);
5342 size += TLB_SizeElemDesc(&src->elemdescVar);
5344 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5345 if (!dest) return E_OUTOFMEMORY;
5347 *dest = *src;
5348 buffer = (char *)(dest + 1);
5349 if (src->lpstrSchema)
5351 int len;
5352 dest->lpstrSchema = (LPOLESTR)buffer;
5353 len = strlenW(src->lpstrSchema);
5354 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5355 buffer += (len + 1) * sizeof(WCHAR);
5358 if (src->varkind == VAR_CONST)
5360 HRESULT hr;
5362 dest->u.lpvarValue = (VARIANT *)buffer;
5363 *dest->u.lpvarValue = *src->u.lpvarValue;
5364 buffer += sizeof(VARIANT);
5365 VariantInit(dest->u.lpvarValue);
5366 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5367 if (FAILED(hr))
5369 SysFreeString((BSTR)dest_ptr);
5370 return hr;
5373 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5374 if (FAILED(hr))
5376 if (src->varkind == VAR_CONST)
5377 VariantClear(dest->u.lpvarValue);
5378 SysFreeString((BSTR)dest);
5379 return hr;
5381 *dest_ptr = dest;
5382 return S_OK;
5385 /* ITypeInfo::GetVarDesc
5387 * Retrieves a VARDESC structure that describes the specified variable.
5390 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5391 LPVARDESC *ppVarDesc)
5393 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5394 UINT i;
5395 const TLBVarDesc *pVDesc;
5397 TRACE("(%p) index %d\n", This, index);
5399 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5402 if (pVDesc)
5403 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5405 return E_INVALIDARG;
5408 /* ITypeInfo_GetNames
5410 * Retrieves the variable with the specified member ID (or the name of the
5411 * property or method and its parameters) that correspond to the specified
5412 * function ID.
5414 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5415 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5417 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5418 const TLBFuncDesc *pFDesc;
5419 const TLBVarDesc *pVDesc;
5420 int i;
5421 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5422 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5423 if(pFDesc)
5425 /* function found, now return function and parameter names */
5426 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5428 if(!i)
5429 *rgBstrNames=SysAllocString(pFDesc->Name);
5430 else
5431 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5433 *pcNames=i;
5435 else
5437 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5438 if(pVDesc)
5440 *rgBstrNames=SysAllocString(pVDesc->Name);
5441 *pcNames=1;
5443 else
5445 if(This->impltypelist &&
5446 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5447 /* recursive search */
5448 ITypeInfo *pTInfo;
5449 HRESULT result;
5450 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5451 &pTInfo);
5452 if(SUCCEEDED(result))
5454 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5455 ITypeInfo_Release(pTInfo);
5456 return result;
5458 WARN("Could not search inherited interface!\n");
5460 else
5462 WARN("no names found\n");
5464 *pcNames=0;
5465 return TYPE_E_ELEMENTNOTFOUND;
5468 return S_OK;
5472 /* ITypeInfo::GetRefTypeOfImplType
5474 * If a type description describes a COM class, it retrieves the type
5475 * description of the implemented interface types. For an interface,
5476 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5477 * if any exist.
5480 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5481 ITypeInfo2 *iface,
5482 UINT index,
5483 HREFTYPE *pRefType)
5485 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5486 UINT i;
5487 HRESULT hr = S_OK;
5488 const TLBImplType *pImpl = This->impltypelist;
5490 TRACE("(%p) index %d\n", This, index);
5491 if (TRACE_ON(ole)) dump_TypeInfo(This);
5493 if(index==(UINT)-1)
5495 /* only valid on dual interfaces;
5496 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5498 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5500 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5501 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5503 *pRefType = -1;
5505 else
5507 hr = TYPE_E_ELEMENTNOTFOUND;
5510 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5512 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5513 *pRefType = This->pTypeLib->dispatch_href;
5515 else
5517 /* get element n from linked list */
5518 for(i=0; pImpl && i<index; i++)
5520 pImpl = pImpl->next;
5523 if (pImpl)
5524 *pRefType = pImpl->hRef;
5525 else
5526 hr = TYPE_E_ELEMENTNOTFOUND;
5529 if(TRACE_ON(ole))
5531 if(SUCCEEDED(hr))
5532 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5533 else
5534 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5537 return hr;
5540 /* ITypeInfo::GetImplTypeFlags
5542 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5543 * or base interface in a type description.
5545 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5546 UINT index, INT *pImplTypeFlags)
5548 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5549 UINT i;
5550 TLBImplType *pImpl;
5552 TRACE("(%p) index %d\n", This, index);
5553 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5554 i++, pImpl=pImpl->next)
5556 if(i==index && pImpl){
5557 *pImplTypeFlags=pImpl->implflags;
5558 return S_OK;
5560 *pImplTypeFlags=0;
5561 return TYPE_E_ELEMENTNOTFOUND;
5564 /* GetIDsOfNames
5565 * Maps between member names and member IDs, and parameter names and
5566 * parameter IDs.
5568 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5569 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5571 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5572 const TLBFuncDesc *pFDesc;
5573 const TLBVarDesc *pVDesc;
5574 HRESULT ret=S_OK;
5575 UINT i;
5577 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5578 cNames);
5580 /* init out parameters in case of failure */
5581 for (i = 0; i < cNames; i++)
5582 pMemId[i] = MEMBERID_NIL;
5584 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5585 int j;
5586 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5587 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5588 for(i=1; i < cNames; i++){
5589 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5590 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5591 break;
5592 if( j<pFDesc->funcdesc.cParams)
5593 pMemId[i]=j;
5594 else
5595 ret=DISP_E_UNKNOWNNAME;
5597 TRACE("-- 0x%08x\n", ret);
5598 return ret;
5601 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5602 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5603 if(cNames) *pMemId=pVDesc->vardesc.memid;
5604 return ret;
5607 /* not found, see if it can be found in an inherited interface */
5608 if(This->impltypelist) {
5609 /* recursive search */
5610 ITypeInfo *pTInfo;
5611 ret=ITypeInfo_GetRefTypeInfo(iface,
5612 This->impltypelist->hRef, &pTInfo);
5613 if(SUCCEEDED(ret)){
5614 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5615 ITypeInfo_Release(pTInfo);
5616 return ret;
5618 WARN("Could not search inherited interface!\n");
5619 } else
5620 WARN("no names found\n");
5621 return DISP_E_UNKNOWNNAME;
5624 /* ITypeInfo::Invoke
5626 * Invokes a method, or accesses a property of an object, that implements the
5627 * interface described by the type description.
5629 DWORD
5630 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5631 DWORD res;
5633 if (TRACE_ON(ole)) {
5634 int i;
5635 TRACE("Calling %p(",func);
5636 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5637 TRACE(")\n");
5640 switch (callconv) {
5641 case CC_STDCALL:
5643 switch (nrargs) {
5644 case 0:
5645 res = func();
5646 break;
5647 case 1:
5648 res = func(args[0]);
5649 break;
5650 case 2:
5651 res = func(args[0],args[1]);
5652 break;
5653 case 3:
5654 res = func(args[0],args[1],args[2]);
5655 break;
5656 case 4:
5657 res = func(args[0],args[1],args[2],args[3]);
5658 break;
5659 case 5:
5660 res = func(args[0],args[1],args[2],args[3],args[4]);
5661 break;
5662 case 6:
5663 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5664 break;
5665 case 7:
5666 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5667 break;
5668 case 8:
5669 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5670 break;
5671 case 9:
5672 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5673 break;
5674 case 10:
5675 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5676 break;
5677 case 11:
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]);
5679 break;
5680 case 12:
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]);
5682 break;
5683 case 13:
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]);
5685 break;
5686 case 14:
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]);
5688 break;
5689 case 15:
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]);
5691 break;
5692 case 16:
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]);
5694 break;
5695 case 17:
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]);
5697 break;
5698 case 18:
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]);
5700 break;
5701 case 19:
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]);
5703 break;
5704 case 20:
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]);
5706 break;
5707 case 21:
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]);
5709 break;
5710 case 22:
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]);
5712 break;
5713 case 23:
5714 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]);
5715 break;
5716 case 24:
5717 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]);
5718 break;
5719 case 25:
5720 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]);
5721 break;
5722 case 26:
5723 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]);
5724 break;
5725 case 27:
5726 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]);
5727 break;
5728 case 28:
5729 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]);
5730 break;
5731 case 29:
5732 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]);
5733 break;
5734 case 30:
5735 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]);
5736 break;
5737 default:
5738 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5739 res = -1;
5740 break;
5742 break;
5743 default:
5744 FIXME("unsupported calling convention %d\n",callconv);
5745 res = -1;
5746 break;
5748 TRACE("returns %08x\n",res);
5749 return res;
5752 /* The size of the argument on the stack in DWORD units (in all x86 call
5753 * convetions the arguments on the stack are DWORD-aligned)
5755 static int _dispargsize(VARTYPE vt)
5757 switch (vt) {
5758 case VT_I8:
5759 case VT_UI8:
5760 return 8/sizeof(DWORD);
5761 case VT_R8:
5762 return sizeof(double)/sizeof(DWORD);
5763 case VT_DECIMAL:
5764 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5765 case VT_CY:
5766 return sizeof(CY)/sizeof(DWORD);
5767 case VT_DATE:
5768 return sizeof(DATE)/sizeof(DWORD);
5769 case VT_VARIANT:
5770 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5771 case VT_RECORD:
5772 FIXME("VT_RECORD not implemented\n");
5773 return 1;
5774 default:
5775 return 1;
5779 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5781 HRESULT hr = S_OK;
5782 ITypeInfo *tinfo2 = NULL;
5783 TYPEATTR *tattr = NULL;
5785 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5786 if (hr)
5788 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5789 "hr = 0x%08x\n",
5790 tdesc->u.hreftype, hr);
5791 return hr;
5793 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5794 if (hr)
5796 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5797 ITypeInfo_Release(tinfo2);
5798 return hr;
5801 switch (tattr->typekind)
5803 case TKIND_ENUM:
5804 *vt |= VT_I4;
5805 break;
5807 case TKIND_ALIAS:
5808 tdesc = &tattr->tdescAlias;
5809 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5810 break;
5812 case TKIND_INTERFACE:
5813 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5814 *vt |= VT_DISPATCH;
5815 else
5816 *vt |= VT_UNKNOWN;
5817 break;
5819 case TKIND_DISPATCH:
5820 *vt |= VT_DISPATCH;
5821 break;
5823 case TKIND_COCLASS:
5824 *vt |= VT_DISPATCH;
5825 break;
5827 case TKIND_RECORD:
5828 FIXME("TKIND_RECORD unhandled.\n");
5829 hr = E_NOTIMPL;
5830 break;
5832 case TKIND_UNION:
5833 FIXME("TKIND_UNION unhandled.\n");
5834 hr = E_NOTIMPL;
5835 break;
5837 default:
5838 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5839 hr = E_NOTIMPL;
5840 break;
5842 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5843 ITypeInfo_Release(tinfo2);
5844 return hr;
5847 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5849 HRESULT hr = S_OK;
5851 /* enforce only one level of pointer indirection */
5852 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5854 tdesc = tdesc->u.lptdesc;
5856 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5857 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5858 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5859 if ((tdesc->vt == VT_USERDEFINED) ||
5860 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5862 VARTYPE vt_userdefined = 0;
5863 const TYPEDESC *tdesc_userdefined = tdesc;
5864 if (tdesc->vt == VT_PTR)
5866 vt_userdefined = VT_BYREF;
5867 tdesc_userdefined = tdesc->u.lptdesc;
5869 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5870 if ((hr == S_OK) &&
5871 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5872 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5874 *vt |= vt_userdefined;
5875 return S_OK;
5878 *vt = VT_BYREF;
5881 switch (tdesc->vt)
5883 case VT_HRESULT:
5884 *vt |= VT_ERROR;
5885 break;
5886 case VT_USERDEFINED:
5887 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5888 break;
5889 case VT_VOID:
5890 case VT_CARRAY:
5891 case VT_PTR:
5892 case VT_LPSTR:
5893 case VT_LPWSTR:
5894 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5895 hr = DISP_E_BADVARTYPE;
5896 break;
5897 case VT_SAFEARRAY:
5898 *vt |= VT_ARRAY;
5899 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5900 break;
5901 case VT_INT:
5902 *vt |= VT_I4;
5903 break;
5904 case VT_UINT:
5905 *vt |= VT_UI4;
5906 break;
5907 default:
5908 *vt |= tdesc->vt;
5909 break;
5911 return hr;
5914 /***********************************************************************
5915 * DispCallFunc (OLEAUT32.@)
5917 * Invokes a function of the specified calling convention, passing the
5918 * specified arguments and returns the result.
5920 * PARAMS
5921 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5922 * oVft [I] The offset in the vtable. See notes.
5923 * cc [I] Calling convention of the function to call.
5924 * vtReturn [I] The return type of the function.
5925 * cActuals [I] Number of parameters.
5926 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5927 * prgpvarg [I] The arguments to pass.
5928 * pvargResult [O] The return value of the function. Can be NULL.
5930 * RETURNS
5931 * Success: S_OK.
5932 * Failure: HRESULT code.
5934 * NOTES
5935 * The HRESULT return value of this function is not affected by the return
5936 * value of the user supplied function, which is returned in pvargResult.
5938 * If pvInstance is NULL then a non-object function is to be called and oVft
5939 * is the address of the function to call.
5941 * The cc parameter can be one of the following values:
5942 *|CC_FASTCALL
5943 *|CC_CDECL
5944 *|CC_PASCAL
5945 *|CC_STDCALL
5946 *|CC_FPFASTCALL
5947 *|CC_SYSCALL
5948 *|CC_MPWCDECL
5949 *|CC_MPWPASCAL
5952 HRESULT WINAPI
5953 DispCallFunc(
5954 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5955 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5957 int argsize, argspos;
5958 UINT i;
5959 DWORD *args;
5960 HRESULT hres;
5962 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5963 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5964 pvargResult, V_VT(pvargResult));
5966 argsize = 0;
5967 if (pvInstance)
5968 argsize++; /* for This pointer */
5970 for (i=0;i<cActuals;i++)
5972 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5973 dump_Variant(prgpvarg[i]);
5974 argsize += _dispargsize(prgvt[i]);
5976 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5978 argspos = 0;
5979 if (pvInstance)
5981 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5982 argspos++;
5985 for (i=0;i<cActuals;i++)
5987 VARIANT *arg = prgpvarg[i];
5988 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5989 if (prgvt[i] == VT_VARIANT)
5990 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5991 else
5992 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5993 argspos += _dispargsize(prgvt[i]);
5996 if (pvInstance)
5998 FARPROC *vtable = *(FARPROC**)pvInstance;
5999 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
6001 else
6002 /* if we aren't invoking an object then the function pointer is stored
6003 * in oVft */
6004 hres = _invoke((FARPROC)oVft, cc, argsize, args);
6006 if (pvargResult && (vtReturn != VT_EMPTY))
6008 TRACE("Method returned 0x%08x\n",hres);
6009 V_VT(pvargResult) = vtReturn;
6010 V_UI4(pvargResult) = hres;
6013 HeapFree(GetProcessHeap(),0,args);
6014 return S_OK;
6017 #define INVBUF_ELEMENT_SIZE \
6018 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6019 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6020 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6021 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6022 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6023 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6024 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6025 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6027 static HRESULT WINAPI ITypeInfo_fnInvoke(
6028 ITypeInfo2 *iface,
6029 VOID *pIUnk,
6030 MEMBERID memid,
6031 UINT16 wFlags,
6032 DISPPARAMS *pDispParams,
6033 VARIANT *pVarResult,
6034 EXCEPINFO *pExcepInfo,
6035 UINT *pArgErr)
6037 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6038 int i;
6039 unsigned int var_index;
6040 TYPEKIND type_kind;
6041 HRESULT hres;
6042 const TLBFuncDesc *pFuncInfo;
6044 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6045 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6048 if (!pDispParams)
6050 ERR("NULL pDispParams not allowed\n");
6051 return E_INVALIDARG;
6054 dump_DispParms(pDispParams);
6056 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6058 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6059 pDispParams->cNamedArgs, pDispParams->cArgs);
6060 return E_INVALIDARG;
6063 /* we do this instead of using GetFuncDesc since it will return a fake
6064 * FUNCDESC for dispinterfaces and we want the real function description */
6065 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6066 if ((memid == pFuncInfo->funcdesc.memid) &&
6067 (wFlags & pFuncInfo->funcdesc.invkind))
6068 break;
6070 if (pFuncInfo) {
6071 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6073 if (TRACE_ON(ole))
6075 TRACE("invoking:\n");
6076 dump_TLBFuncDescOne(pFuncInfo);
6079 switch (func_desc->funckind) {
6080 case FUNC_PUREVIRTUAL:
6081 case FUNC_VIRTUAL: {
6082 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6083 VARIANT varresult;
6084 VARIANT retval; /* pointer for storing byref retvals in */
6085 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6086 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6087 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6088 UINT cNamedArgs = pDispParams->cNamedArgs;
6089 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6090 UINT vargs_converted=0;
6092 hres = S_OK;
6094 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6096 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6098 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6099 hres = DISP_E_PARAMNOTFOUND;
6100 goto func_fail;
6102 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6103 cNamedArgs--;
6104 rgdispidNamedArgs++;
6107 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6109 ERR("functions with the vararg attribute do not support named arguments\n");
6110 hres = DISP_E_NONAMEDARGS;
6111 goto func_fail;
6114 for (i = 0; i < func_desc->cParams; i++)
6116 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6117 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6118 if (FAILED(hres))
6119 goto func_fail;
6122 TRACE("changing args\n");
6123 for (i = 0; i < func_desc->cParams; i++)
6125 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6126 VARIANTARG *src_arg;
6128 if (wParamFlags & PARAMFLAG_FLCID)
6130 VARIANTARG *arg;
6131 arg = prgpvarg[i] = &rgvarg[i];
6132 V_VT(arg) = VT_I4;
6133 V_I4(arg) = This->pTypeLib->lcid;
6134 continue;
6137 if (cNamedArgs)
6139 USHORT j;
6140 src_arg = NULL;
6141 for (j = 0; j < cNamedArgs; j++)
6142 if (rgdispidNamedArgs[j] == i)
6144 src_arg = &pDispParams->rgvarg[j];
6145 break;
6148 else
6150 src_arg = vargs_converted < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted] : NULL;
6151 vargs_converted++;
6154 if (wParamFlags & PARAMFLAG_FRETVAL)
6156 /* under most conditions the caller is not allowed to
6157 * pass in a dispparam arg in the index of what would be
6158 * the retval parameter. however, there is an exception
6159 * where the extra parameter is used in an extra
6160 * IDispatch::Invoke below */
6161 if ((i < pDispParams->cArgs) &&
6162 ((func_desc->cParams != 1) || !pVarResult ||
6163 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6165 hres = DISP_E_BADPARAMCOUNT;
6166 break;
6169 /* note: this check is placed so that if the caller passes
6170 * in a VARIANTARG for the retval we just ignore it, like
6171 * native does */
6172 if (i == func_desc->cParams - 1)
6174 VARIANTARG *arg;
6175 arg = prgpvarg[i] = &rgvarg[i];
6176 memset(arg, 0, sizeof(*arg));
6177 V_VT(arg) = rgvt[i];
6178 memset(&retval, 0, sizeof(retval));
6179 V_BYREF(arg) = &retval;
6181 else
6183 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6184 hres = E_UNEXPECTED;
6185 break;
6188 else if (src_arg)
6190 dump_Variant(src_arg);
6192 if (rgvt[i] == VT_VARIANT)
6193 hres = VariantCopy(&rgvarg[i], src_arg);
6194 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6196 if (rgvt[i] == V_VT(src_arg))
6197 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6198 else
6200 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6201 hres = VariantCopy(&missing_arg[i], src_arg);
6202 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6204 V_VT(&rgvarg[i]) = rgvt[i];
6206 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6208 SAFEARRAY *a;
6209 SAFEARRAYBOUND bound;
6210 VARIANT *v;
6211 LONG j;
6212 bound.lLbound = 0;
6213 bound.cElements = pDispParams->cArgs-i;
6214 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6216 ERR("SafeArrayCreate failed\n");
6217 break;
6219 hres = SafeArrayAccessData(a, (LPVOID)&v);
6220 if (hres != S_OK)
6222 ERR("SafeArrayAccessData failed with %x\n", hres);
6223 break;
6225 for (j = 0; j < bound.cElements; j++)
6226 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6227 hres = SafeArrayUnaccessData(a);
6228 if (hres != S_OK)
6230 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6231 break;
6233 V_ARRAY(&rgvarg[i]) = a;
6234 V_VT(&rgvarg[i]) = rgvt[i];
6236 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6238 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6239 V_VT(&missing_arg[i]) = V_VT(src_arg);
6240 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6241 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6242 V_VT(&rgvarg[i]) = rgvt[i];
6244 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6246 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6247 V_VT(&rgvarg[i]) = rgvt[i];
6249 else
6251 /* FIXME: this doesn't work for VT_BYREF arguments if
6252 * they are not the same type as in the paramdesc */
6253 V_VT(&rgvarg[i]) = V_VT(src_arg);
6254 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6255 V_VT(&rgvarg[i]) = rgvt[i];
6258 if (FAILED(hres))
6260 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6261 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6262 debugstr_VT(src_arg), debugstr_VF(src_arg));
6263 break;
6265 prgpvarg[i] = &rgvarg[i];
6267 else if (wParamFlags & PARAMFLAG_FOPT)
6269 VARIANTARG *arg;
6270 arg = prgpvarg[i] = &rgvarg[i];
6271 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6273 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6274 if (FAILED(hres))
6275 break;
6277 else
6279 VARIANTARG *missing_arg;
6280 /* if the function wants a pointer to a variant then
6281 * set that up, otherwise just pass the VT_ERROR in
6282 * the argument by value */
6283 if (rgvt[i] & VT_BYREF)
6285 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6286 V_VT(arg) = VT_VARIANT | VT_BYREF;
6287 V_VARIANTREF(arg) = missing_arg;
6289 else
6290 missing_arg = arg;
6291 V_VT(missing_arg) = VT_ERROR;
6292 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6295 else
6297 hres = DISP_E_BADPARAMCOUNT;
6298 break;
6301 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6303 /* VT_VOID is a special case for return types, so it is not
6304 * handled in the general function */
6305 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6306 V_VT(&varresult) = VT_EMPTY;
6307 else
6309 V_VT(&varresult) = 0;
6310 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6311 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6314 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6315 V_VT(&varresult), func_desc->cParams, rgvt,
6316 prgpvarg, &varresult);
6318 vargs_converted = 0;
6320 for (i = 0; i < func_desc->cParams; i++)
6322 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6324 if (wParamFlags & PARAMFLAG_FLCID)
6325 continue;
6326 else if (wParamFlags & PARAMFLAG_FRETVAL)
6328 if (TRACE_ON(ole))
6330 TRACE("[retval] value: ");
6331 dump_Variant(prgpvarg[i]);
6334 if (pVarResult)
6336 VariantInit(pVarResult);
6337 /* deref return value */
6338 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6341 /* free data stored in varresult. Note that
6342 * VariantClear doesn't do what we want because we are
6343 * working with byref types. */
6344 /* FIXME: clear safearrays, bstrs, records and
6345 * variants here too */
6346 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6347 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6349 if(*V_UNKNOWNREF(prgpvarg[i]))
6350 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6352 break;
6354 else if (vargs_converted < pDispParams->cArgs)
6356 if (wParamFlags & PARAMFLAG_FOUT)
6358 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6360 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6361 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6363 if (FAILED(hres))
6365 ERR("failed to convert param %d to vt %d\n", i,
6366 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6367 break;
6370 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6371 func_desc->cParamsOpt < 0 &&
6372 i == func_desc->cParams-1)
6374 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6375 LONG j, ubound;
6376 VARIANT *v;
6377 hres = SafeArrayGetUBound(a, 1, &ubound);
6378 if (hres != S_OK)
6380 ERR("SafeArrayGetUBound failed with %x\n", hres);
6381 break;
6383 hres = SafeArrayAccessData(a, (LPVOID)&v);
6384 if (hres != S_OK)
6386 ERR("SafeArrayAccessData failed with %x\n", hres);
6387 break;
6389 for (j = 0; j <= ubound; j++)
6390 VariantClear(&v[j]);
6391 hres = SafeArrayUnaccessData(a);
6392 if (hres != S_OK)
6394 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6395 break;
6398 VariantClear(&rgvarg[i]);
6399 vargs_converted++;
6401 else if (wParamFlags & PARAMFLAG_FOPT)
6403 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6404 VariantClear(&rgvarg[i]);
6408 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6410 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6411 hres = DISP_E_EXCEPTION;
6412 if (pExcepInfo)
6414 IErrorInfo *pErrorInfo;
6415 pExcepInfo->scode = V_ERROR(&varresult);
6416 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6418 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6419 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6420 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6421 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6423 IErrorInfo_Release(pErrorInfo);
6427 if (V_VT(&varresult) != VT_ERROR)
6429 TRACE("varresult value: ");
6430 dump_Variant(&varresult);
6432 if (pVarResult)
6434 VariantClear(pVarResult);
6435 *pVarResult = varresult;
6437 else
6438 VariantClear(&varresult);
6441 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6442 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6443 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6444 (pDispParams->cArgs != 0))
6446 if (V_VT(pVarResult) == VT_DISPATCH)
6448 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6449 /* Note: not VariantClear; we still need the dispatch
6450 * pointer to be valid */
6451 VariantInit(pVarResult);
6452 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6453 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6454 pDispParams, pVarResult, pExcepInfo, pArgErr);
6455 IDispatch_Release(pDispatch);
6457 else
6459 VariantClear(pVarResult);
6460 hres = DISP_E_NOTACOLLECTION;
6464 func_fail:
6465 HeapFree(GetProcessHeap(), 0, buffer);
6466 break;
6468 case FUNC_DISPATCH: {
6469 IDispatch *disp;
6471 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6472 if (SUCCEEDED(hres)) {
6473 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6474 hres = IDispatch_Invoke(
6475 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6476 pVarResult,pExcepInfo,pArgErr
6478 if (FAILED(hres))
6479 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6480 IDispatch_Release(disp);
6481 } else
6482 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6483 break;
6485 default:
6486 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6487 hres = E_FAIL;
6488 break;
6491 TRACE("-- 0x%08x\n", hres);
6492 return hres;
6494 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6495 VARDESC *var_desc;
6497 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6498 if(FAILED(hres)) return hres;
6500 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6501 dump_VARDESC(var_desc);
6502 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6503 return E_NOTIMPL;
6506 /* not found, look for it in inherited interfaces */
6507 ITypeInfo2_GetTypeKind(iface, &type_kind);
6508 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6509 if(This->impltypelist) {
6510 /* recursive search */
6511 ITypeInfo *pTInfo;
6512 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6513 if(SUCCEEDED(hres)){
6514 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6515 ITypeInfo_Release(pTInfo);
6516 return hres;
6518 WARN("Could not search inherited interface!\n");
6521 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6522 return DISP_E_MEMBERNOTFOUND;
6525 /* ITypeInfo::GetDocumentation
6527 * Retrieves the documentation string, the complete Help file name and path,
6528 * and the context ID for the Help topic for a specified type description.
6530 * (Can be tested by the Visual Basic Editor in Word for instance.)
6532 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6533 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6534 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6536 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6537 const TLBFuncDesc *pFDesc;
6538 const TLBVarDesc *pVDesc;
6539 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6540 " HelpContext(%p) HelpFile(%p)\n",
6541 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6542 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6543 if(pBstrName)
6544 *pBstrName=SysAllocString(This->Name);
6545 if(pBstrDocString)
6546 *pBstrDocString=SysAllocString(This->DocString);
6547 if(pdwHelpContext)
6548 *pdwHelpContext=This->dwHelpContext;
6549 if(pBstrHelpFile)
6550 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6551 return S_OK;
6552 }else {/* for a member */
6553 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6554 if(pFDesc->funcdesc.memid==memid){
6555 if(pBstrName)
6556 *pBstrName = SysAllocString(pFDesc->Name);
6557 if(pBstrDocString)
6558 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6559 if(pdwHelpContext)
6560 *pdwHelpContext=pFDesc->helpcontext;
6561 return S_OK;
6563 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6564 if(pVDesc->vardesc.memid==memid){
6565 if(pBstrName)
6566 *pBstrName = SysAllocString(pVDesc->Name);
6567 if(pBstrDocString)
6568 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6569 if(pdwHelpContext)
6570 *pdwHelpContext=pVDesc->HelpContext;
6571 return S_OK;
6575 if(This->impltypelist &&
6576 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6577 /* recursive search */
6578 ITypeInfo *pTInfo;
6579 HRESULT result;
6580 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6581 &pTInfo);
6582 if(SUCCEEDED(result)) {
6583 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6584 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6585 ITypeInfo_Release(pTInfo);
6586 return result;
6588 WARN("Could not search inherited interface!\n");
6591 WARN("member %d not found\n", memid);
6592 return TYPE_E_ELEMENTNOTFOUND;
6595 /* ITypeInfo::GetDllEntry
6597 * Retrieves a description or specification of an entry point for a function
6598 * in a DLL.
6600 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6601 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6602 WORD *pwOrdinal)
6604 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6605 const TLBFuncDesc *pFDesc;
6607 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6609 if (pBstrDllName) *pBstrDllName = NULL;
6610 if (pBstrName) *pBstrName = NULL;
6611 if (pwOrdinal) *pwOrdinal = 0;
6613 if (This->TypeAttr.typekind != TKIND_MODULE)
6614 return TYPE_E_BADMODULEKIND;
6616 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6617 if(pFDesc->funcdesc.memid==memid){
6618 dump_TypeInfo(This);
6619 if (TRACE_ON(ole))
6620 dump_TLBFuncDescOne(pFDesc);
6622 if (pBstrDllName)
6623 *pBstrDllName = SysAllocString(This->DllName);
6625 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6626 if (pBstrName)
6627 *pBstrName = SysAllocString(pFDesc->Entry);
6628 if (pwOrdinal)
6629 *pwOrdinal = -1;
6630 return S_OK;
6632 if (pBstrName)
6633 *pBstrName = NULL;
6634 if (pwOrdinal)
6635 *pwOrdinal = (DWORD)pFDesc->Entry;
6636 return S_OK;
6638 return TYPE_E_ELEMENTNOTFOUND;
6641 /* internal function to make the inherited interfaces' methods appear
6642 * part of the interface */
6643 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6644 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6646 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6647 HRESULT hr;
6649 TRACE("%p, 0x%x\n", iface, *hRefType);
6651 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6653 ITypeInfo *pSubTypeInfo;
6655 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6656 if (FAILED(hr))
6657 return hr;
6659 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6660 hRefType, ppTInfo);
6661 ITypeInfo_Release(pSubTypeInfo);
6662 if (SUCCEEDED(hr))
6663 return hr;
6665 *hRefType -= DISPATCH_HREF_OFFSET;
6667 if (!(*hRefType & DISPATCH_HREF_MASK))
6668 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6669 else
6670 return E_FAIL;
6673 /* ITypeInfo::GetRefTypeInfo
6675 * If a type description references other type descriptions, it retrieves
6676 * the referenced type descriptions.
6678 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6679 ITypeInfo2 *iface,
6680 HREFTYPE hRefType,
6681 ITypeInfo **ppTInfo)
6683 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6684 HRESULT result = E_FAIL;
6686 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6688 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6689 ITypeInfo_AddRef(*ppTInfo);
6690 result = S_OK;
6692 else if (hRefType == -1 &&
6693 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6694 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6696 /* when we meet a DUAL dispinterface, we must create the interface
6697 * version of it.
6699 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6702 /* the interface version contains the same information as the dispinterface
6703 * copy the contents of the structs.
6705 *pTypeInfoImpl = *This;
6706 pTypeInfoImpl->ref = 0;
6708 /* change the type to interface */
6709 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6711 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6713 /* we use data structures from This, so we need to keep a reference
6714 * to it to stop it being destroyed and signal to the new instance to
6715 * not free its data structures when it is destroyed */
6716 pTypeInfoImpl->no_free_data = TRUE;
6717 pTypeInfoImpl->next = This;
6718 ITypeInfo_AddRef((ITypeInfo*) This);
6720 ITypeInfo_AddRef(*ppTInfo);
6722 result = S_OK;
6724 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6725 (This->TypeAttr.typekind == TKIND_DISPATCH))
6727 HREFTYPE href_dispatch = hRefType;
6728 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6729 } else {
6730 TLBRefType *ref_type;
6731 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6733 if(ref_type->reference == hRefType)
6734 break;
6736 if(&ref_type->entry == &This->pTypeLib->ref_list)
6738 FIXME("Can't find pRefType for ref %x\n", hRefType);
6739 goto end;
6741 if(hRefType != -1) {
6742 ITypeLib *pTLib = NULL;
6744 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6745 UINT Index;
6746 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6747 } else {
6748 if(ref_type->pImpTLInfo->pImpTypeLib) {
6749 TRACE("typeinfo in imported typelib that is already loaded\n");
6750 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6751 ITypeLib2_AddRef(pTLib);
6752 result = S_OK;
6753 } else {
6754 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6755 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6756 ref_type->pImpTLInfo->wVersionMajor,
6757 ref_type->pImpTLInfo->wVersionMinor,
6758 ref_type->pImpTLInfo->lcid,
6759 &pTLib);
6761 if(FAILED(result)) {
6762 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6763 result=LoadTypeLib(libnam, &pTLib);
6764 SysFreeString(libnam);
6766 if(SUCCEEDED(result)) {
6767 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6768 ITypeLib2_AddRef(pTLib);
6772 if(SUCCEEDED(result)) {
6773 if(ref_type->index == TLB_REF_USE_GUID)
6774 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6775 &ref_type->guid,
6776 ppTInfo);
6777 else
6778 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6779 ppTInfo);
6781 if (pTLib != NULL)
6782 ITypeLib2_Release(pTLib);
6786 end:
6787 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6788 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6789 return result;
6792 /* ITypeInfo::AddressOfMember
6794 * Retrieves the addresses of static functions or variables, such as those
6795 * defined in a DLL.
6797 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6798 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6800 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6801 HRESULT hr;
6802 BSTR dll, entry;
6803 WORD ordinal;
6804 HMODULE module;
6806 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6808 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6809 if (FAILED(hr))
6810 return hr;
6812 module = LoadLibraryW(dll);
6813 if (!module)
6815 ERR("couldn't load %s\n", debugstr_w(dll));
6816 SysFreeString(dll);
6817 SysFreeString(entry);
6818 return STG_E_FILENOTFOUND;
6820 /* FIXME: store library somewhere where we can free it */
6822 if (entry)
6824 LPSTR entryA;
6825 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6826 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6827 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6829 *ppv = GetProcAddress(module, entryA);
6830 if (!*ppv)
6831 ERR("function not found %s\n", debugstr_a(entryA));
6833 HeapFree(GetProcessHeap(), 0, entryA);
6835 else
6837 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6838 if (!*ppv)
6839 ERR("function not found %d\n", ordinal);
6842 SysFreeString(dll);
6843 SysFreeString(entry);
6845 if (!*ppv)
6846 return TYPE_E_DLLFUNCTIONNOTFOUND;
6848 return S_OK;
6851 /* ITypeInfo::CreateInstance
6853 * Creates a new instance of a type that describes a component object class
6854 * (coclass).
6856 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6857 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6859 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6860 HRESULT hr;
6861 TYPEATTR *pTA;
6863 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6865 *ppvObj = NULL;
6867 if(pOuterUnk)
6869 WARN("Not able to aggregate\n");
6870 return CLASS_E_NOAGGREGATION;
6873 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6874 if(FAILED(hr)) return hr;
6876 if(pTA->typekind != TKIND_COCLASS)
6878 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6879 hr = E_INVALIDARG;
6880 goto end;
6883 hr = S_FALSE;
6884 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6886 IUnknown *pUnk;
6887 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6888 TRACE("GetActiveObject rets %08x\n", hr);
6889 if(hr == S_OK)
6891 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6892 IUnknown_Release(pUnk);
6896 if(hr != S_OK)
6897 hr = CoCreateInstance(&pTA->guid, NULL,
6898 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6899 riid, ppvObj);
6901 end:
6902 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6903 return hr;
6906 /* ITypeInfo::GetMops
6908 * Retrieves marshalling information.
6910 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6911 BSTR *pBstrMops)
6913 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6914 FIXME("(%p) stub!\n", This);
6915 return S_OK;
6918 /* ITypeInfo::GetContainingTypeLib
6920 * Retrieves the containing type library and the index of the type description
6921 * within that type library.
6923 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6924 ITypeLib * *ppTLib, UINT *pIndex)
6926 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6928 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6929 if (pIndex) {
6930 *pIndex=This->index;
6931 TRACE("returning pIndex=%d\n", *pIndex);
6934 if (ppTLib) {
6935 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6936 ITypeLib2_AddRef(*ppTLib);
6937 TRACE("returning ppTLib=%p\n", *ppTLib);
6940 return S_OK;
6943 /* ITypeInfo::ReleaseTypeAttr
6945 * Releases a TYPEATTR previously returned by GetTypeAttr.
6948 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6949 TYPEATTR* pTypeAttr)
6951 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6952 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6953 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6956 /* ITypeInfo::ReleaseFuncDesc
6958 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6960 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6961 ITypeInfo2 *iface,
6962 FUNCDESC *pFuncDesc)
6964 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6965 SHORT i;
6967 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6969 for (i = 0; i < pFuncDesc->cParams; i++)
6970 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6971 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6973 SysFreeString((BSTR)pFuncDesc);
6976 /* ITypeInfo::ReleaseVarDesc
6978 * Releases a VARDESC previously returned by GetVarDesc.
6980 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6981 VARDESC *pVarDesc)
6983 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6984 TRACE("(%p)->(%p)\n", This, pVarDesc);
6986 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6987 if (pVarDesc->varkind == VAR_CONST)
6988 VariantClear(pVarDesc->u.lpvarValue);
6989 SysFreeString((BSTR)pVarDesc);
6992 /* ITypeInfo2::GetTypeKind
6994 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6997 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6998 TYPEKIND *pTypeKind)
7000 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7001 *pTypeKind=This->TypeAttr.typekind;
7002 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7003 return S_OK;
7006 /* ITypeInfo2::GetTypeFlags
7008 * Returns the type flags without any allocations. This returns a DWORD type
7009 * flag, which expands the type flags without growing the TYPEATTR (type
7010 * attribute).
7013 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7015 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7016 *pTypeFlags=This->TypeAttr.wTypeFlags;
7017 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7018 return S_OK;
7021 /* ITypeInfo2::GetFuncIndexOfMemId
7022 * Binds to a specific member based on a known DISPID, where the member name
7023 * is not known (for example, when binding to a default member).
7026 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7027 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7029 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7030 const TLBFuncDesc *pFuncInfo;
7031 int i;
7032 HRESULT result;
7034 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7035 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7036 break;
7037 if(pFuncInfo) {
7038 *pFuncIndex = i;
7039 result = S_OK;
7040 } else
7041 result = TYPE_E_ELEMENTNOTFOUND;
7043 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7044 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7045 return result;
7048 /* TypeInfo2::GetVarIndexOfMemId
7050 * Binds to a specific member based on a known DISPID, where the member name
7051 * is not known (for example, when binding to a default member).
7054 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7055 MEMBERID memid, UINT *pVarIndex)
7057 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7058 TLBVarDesc *pVarInfo;
7059 int i;
7060 HRESULT result;
7061 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7062 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7064 if(pVarInfo) {
7065 *pVarIndex = i;
7066 result = S_OK;
7067 } else
7068 result = TYPE_E_ELEMENTNOTFOUND;
7070 TRACE("(%p) memid 0x%08x -> %s\n", This,
7071 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7072 return result;
7075 /* ITypeInfo2::GetCustData
7077 * Gets the custom data
7079 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7080 ITypeInfo2 * iface,
7081 REFGUID guid,
7082 VARIANT *pVarVal)
7084 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7085 TLBCustData *pCData;
7087 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7088 if( IsEqualIID(guid, &pCData->guid)) break;
7090 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7092 VariantInit( pVarVal);
7093 if (pCData)
7094 VariantCopy( pVarVal, &pCData->data);
7095 else
7096 VariantClear( pVarVal );
7097 return S_OK;
7100 /* ITypeInfo2::GetFuncCustData
7102 * Gets the custom data
7104 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7105 ITypeInfo2 * iface,
7106 UINT index,
7107 REFGUID guid,
7108 VARIANT *pVarVal)
7110 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7111 TLBCustData *pCData=NULL;
7112 TLBFuncDesc * pFDesc;
7113 UINT i;
7114 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7115 pFDesc=pFDesc->next);
7117 if(pFDesc)
7118 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7119 if( IsEqualIID(guid, &pCData->guid)) break;
7121 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7123 if(pCData){
7124 VariantInit( pVarVal);
7125 VariantCopy( pVarVal, &pCData->data);
7126 return S_OK;
7128 return E_INVALIDARG; /* FIXME: correct? */
7131 /* ITypeInfo2::GetParamCustData
7133 * Gets the custom data
7135 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7136 ITypeInfo2 * iface,
7137 UINT indexFunc,
7138 UINT indexParam,
7139 REFGUID guid,
7140 VARIANT *pVarVal)
7142 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7143 TLBCustData *pCData=NULL;
7144 TLBFuncDesc * pFDesc;
7145 UINT i;
7147 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7149 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7150 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7151 pCData = pCData->next)
7152 if( IsEqualIID(guid, &pCData->guid)) break;
7154 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7156 if(pCData)
7158 VariantInit( pVarVal);
7159 VariantCopy( pVarVal, &pCData->data);
7160 return S_OK;
7162 return E_INVALIDARG; /* FIXME: correct? */
7165 /* ITypeInfo2::GetVarCustData
7167 * Gets the custom data
7169 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7170 ITypeInfo2 * iface,
7171 UINT index,
7172 REFGUID guid,
7173 VARIANT *pVarVal)
7175 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7176 TLBCustData *pCData=NULL;
7177 TLBVarDesc * pVDesc;
7178 UINT i;
7180 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7182 if(pVDesc)
7184 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7186 if( IsEqualIID(guid, &pCData->guid)) break;
7190 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7192 if(pCData)
7194 VariantInit( pVarVal);
7195 VariantCopy( pVarVal, &pCData->data);
7196 return S_OK;
7198 return E_INVALIDARG; /* FIXME: correct? */
7201 /* ITypeInfo2::GetImplCustData
7203 * Gets the custom data
7205 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7206 ITypeInfo2 * iface,
7207 UINT index,
7208 REFGUID guid,
7209 VARIANT *pVarVal)
7211 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7212 TLBCustData *pCData=NULL;
7213 TLBImplType * pRDesc;
7214 UINT i;
7216 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7218 if(pRDesc)
7220 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7222 if( IsEqualIID(guid, &pCData->guid)) break;
7226 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7228 if(pCData)
7230 VariantInit( pVarVal);
7231 VariantCopy( pVarVal, &pCData->data);
7232 return S_OK;
7234 return E_INVALIDARG; /* FIXME: correct? */
7237 /* ITypeInfo2::GetDocumentation2
7239 * Retrieves the documentation string, the complete Help file name and path,
7240 * the localization context to use, and the context ID for the library Help
7241 * topic in the Help file.
7244 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7245 ITypeInfo2 * iface,
7246 MEMBERID memid,
7247 LCID lcid,
7248 BSTR *pbstrHelpString,
7249 DWORD *pdwHelpStringContext,
7250 BSTR *pbstrHelpStringDll)
7252 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7253 const TLBFuncDesc *pFDesc;
7254 const TLBVarDesc *pVDesc;
7255 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7256 "HelpStringContext(%p) HelpStringDll(%p)\n",
7257 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7258 pbstrHelpStringDll );
7259 /* the help string should be obtained from the helpstringdll,
7260 * using the _DLLGetDocumentation function, based on the supplied
7261 * lcid. Nice to do sometime...
7263 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7264 if(pbstrHelpString)
7265 *pbstrHelpString=SysAllocString(This->Name);
7266 if(pdwHelpStringContext)
7267 *pdwHelpStringContext=This->dwHelpStringContext;
7268 if(pbstrHelpStringDll)
7269 *pbstrHelpStringDll=
7270 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7271 return S_OK;
7272 }else {/* for a member */
7273 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7274 if(pFDesc->funcdesc.memid==memid){
7275 if(pbstrHelpString)
7276 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7277 if(pdwHelpStringContext)
7278 *pdwHelpStringContext=pFDesc->HelpStringContext;
7279 if(pbstrHelpStringDll)
7280 *pbstrHelpStringDll=
7281 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7282 return S_OK;
7284 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7285 if(pVDesc->vardesc.memid==memid){
7286 if(pbstrHelpString)
7287 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7288 if(pdwHelpStringContext)
7289 *pdwHelpStringContext=pVDesc->HelpStringContext;
7290 if(pbstrHelpStringDll)
7291 *pbstrHelpStringDll=
7292 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7293 return S_OK;
7296 return TYPE_E_ELEMENTNOTFOUND;
7299 /* ITypeInfo2::GetAllCustData
7301 * Gets all custom data items for the Type info.
7304 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7305 ITypeInfo2 * iface,
7306 CUSTDATA *pCustData)
7308 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7309 TLBCustData *pCData;
7310 int i;
7312 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7314 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7315 if(pCustData->prgCustData ){
7316 pCustData->cCustData=This->ctCustData;
7317 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7318 pCustData->prgCustData[i].guid=pCData->guid;
7319 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7321 }else{
7322 ERR(" OUT OF MEMORY!\n");
7323 return E_OUTOFMEMORY;
7325 return S_OK;
7328 /* ITypeInfo2::GetAllFuncCustData
7330 * Gets all custom data items for the specified Function
7333 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7334 ITypeInfo2 * iface,
7335 UINT index,
7336 CUSTDATA *pCustData)
7338 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7339 TLBCustData *pCData;
7340 TLBFuncDesc * pFDesc;
7341 UINT i;
7342 TRACE("(%p) index %d\n", This, index);
7343 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7344 pFDesc=pFDesc->next)
7346 if(pFDesc){
7347 pCustData->prgCustData =
7348 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7349 if(pCustData->prgCustData ){
7350 pCustData->cCustData=pFDesc->ctCustData;
7351 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7352 pCData = pCData->next){
7353 pCustData->prgCustData[i].guid=pCData->guid;
7354 VariantCopy(& pCustData->prgCustData[i].varValue,
7355 & pCData->data);
7357 }else{
7358 ERR(" OUT OF MEMORY!\n");
7359 return E_OUTOFMEMORY;
7361 return S_OK;
7363 return TYPE_E_ELEMENTNOTFOUND;
7366 /* ITypeInfo2::GetAllParamCustData
7368 * Gets all custom data items for the Functions
7371 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7372 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7374 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7375 TLBCustData *pCData=NULL;
7376 TLBFuncDesc * pFDesc;
7377 UINT i;
7378 TRACE("(%p) index %d\n", This, indexFunc);
7379 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7380 pFDesc=pFDesc->next)
7382 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7383 pCustData->prgCustData =
7384 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7385 sizeof(CUSTDATAITEM));
7386 if(pCustData->prgCustData ){
7387 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7388 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7389 pCData; i++, pCData = pCData->next){
7390 pCustData->prgCustData[i].guid=pCData->guid;
7391 VariantCopy(& pCustData->prgCustData[i].varValue,
7392 & pCData->data);
7394 }else{
7395 ERR(" OUT OF MEMORY!\n");
7396 return E_OUTOFMEMORY;
7398 return S_OK;
7400 return TYPE_E_ELEMENTNOTFOUND;
7403 /* ITypeInfo2::GetAllVarCustData
7405 * Gets all custom data items for the specified Variable
7408 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7409 UINT index, CUSTDATA *pCustData)
7411 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7412 TLBCustData *pCData;
7413 TLBVarDesc * pVDesc;
7414 UINT i;
7415 TRACE("(%p) index %d\n", This, index);
7416 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7417 pVDesc=pVDesc->next)
7419 if(pVDesc){
7420 pCustData->prgCustData =
7421 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7422 if(pCustData->prgCustData ){
7423 pCustData->cCustData=pVDesc->ctCustData;
7424 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7425 pCData = pCData->next){
7426 pCustData->prgCustData[i].guid=pCData->guid;
7427 VariantCopy(& pCustData->prgCustData[i].varValue,
7428 & pCData->data);
7430 }else{
7431 ERR(" OUT OF MEMORY!\n");
7432 return E_OUTOFMEMORY;
7434 return S_OK;
7436 return TYPE_E_ELEMENTNOTFOUND;
7439 /* ITypeInfo2::GetAllImplCustData
7441 * Gets all custom data items for the specified implementation type
7444 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7445 ITypeInfo2 * iface,
7446 UINT index,
7447 CUSTDATA *pCustData)
7449 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7450 TLBCustData *pCData;
7451 TLBImplType * pRDesc;
7452 UINT i;
7453 TRACE("(%p) index %d\n", This, index);
7454 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7455 pRDesc=pRDesc->next)
7457 if(pRDesc){
7458 pCustData->prgCustData =
7459 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7460 if(pCustData->prgCustData ){
7461 pCustData->cCustData=pRDesc->ctCustData;
7462 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7463 pCData = pCData->next){
7464 pCustData->prgCustData[i].guid=pCData->guid;
7465 VariantCopy(& pCustData->prgCustData[i].varValue,
7466 & pCData->data);
7468 }else{
7469 ERR(" OUT OF MEMORY!\n");
7470 return E_OUTOFMEMORY;
7472 return S_OK;
7474 return TYPE_E_ELEMENTNOTFOUND;
7477 static const ITypeInfo2Vtbl tinfvt =
7480 ITypeInfo_fnQueryInterface,
7481 ITypeInfo_fnAddRef,
7482 ITypeInfo_fnRelease,
7484 ITypeInfo_fnGetTypeAttr,
7485 ITypeInfo_fnGetTypeComp,
7486 ITypeInfo_fnGetFuncDesc,
7487 ITypeInfo_fnGetVarDesc,
7488 ITypeInfo_fnGetNames,
7489 ITypeInfo_fnGetRefTypeOfImplType,
7490 ITypeInfo_fnGetImplTypeFlags,
7491 ITypeInfo_fnGetIDsOfNames,
7492 ITypeInfo_fnInvoke,
7493 ITypeInfo_fnGetDocumentation,
7494 ITypeInfo_fnGetDllEntry,
7495 ITypeInfo_fnGetRefTypeInfo,
7496 ITypeInfo_fnAddressOfMember,
7497 ITypeInfo_fnCreateInstance,
7498 ITypeInfo_fnGetMops,
7499 ITypeInfo_fnGetContainingTypeLib,
7500 ITypeInfo_fnReleaseTypeAttr,
7501 ITypeInfo_fnReleaseFuncDesc,
7502 ITypeInfo_fnReleaseVarDesc,
7504 ITypeInfo2_fnGetTypeKind,
7505 ITypeInfo2_fnGetTypeFlags,
7506 ITypeInfo2_fnGetFuncIndexOfMemId,
7507 ITypeInfo2_fnGetVarIndexOfMemId,
7508 ITypeInfo2_fnGetCustData,
7509 ITypeInfo2_fnGetFuncCustData,
7510 ITypeInfo2_fnGetParamCustData,
7511 ITypeInfo2_fnGetVarCustData,
7512 ITypeInfo2_fnGetImplTypeCustData,
7513 ITypeInfo2_fnGetDocumentation2,
7514 ITypeInfo2_fnGetAllCustData,
7515 ITypeInfo2_fnGetAllFuncCustData,
7516 ITypeInfo2_fnGetAllParamCustData,
7517 ITypeInfo2_fnGetAllVarCustData,
7518 ITypeInfo2_fnGetAllImplTypeCustData,
7521 /******************************************************************************
7522 * CreateDispTypeInfo [OLEAUT32.31]
7524 * Build type information for an object so it can be called through an
7525 * IDispatch interface.
7527 * RETURNS
7528 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7529 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7531 * NOTES
7532 * This call allows an objects methods to be accessed through IDispatch, by
7533 * building an ITypeInfo object that IDispatch can use to call through.
7535 HRESULT WINAPI CreateDispTypeInfo(
7536 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7537 LCID lcid, /* [I] Locale Id */
7538 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7540 ITypeInfoImpl *pTIClass, *pTIIface;
7541 ITypeLibImpl *pTypeLibImpl;
7542 unsigned int param, func;
7543 TLBFuncDesc **ppFuncDesc;
7544 TLBRefType *ref;
7546 TRACE("\n");
7547 pTypeLibImpl = TypeLibImpl_Constructor();
7548 if (!pTypeLibImpl) return E_FAIL;
7550 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7551 pTIIface->pTypeLib = pTypeLibImpl;
7552 pTIIface->index = 0;
7553 pTIIface->Name = NULL;
7554 pTIIface->dwHelpContext = -1;
7555 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7556 pTIIface->TypeAttr.lcid = lcid;
7557 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7558 pTIIface->TypeAttr.wMajorVerNum = 0;
7559 pTIIface->TypeAttr.wMinorVerNum = 0;
7560 pTIIface->TypeAttr.cbAlignment = 2;
7561 pTIIface->TypeAttr.cbSizeInstance = -1;
7562 pTIIface->TypeAttr.cbSizeVft = -1;
7563 pTIIface->TypeAttr.cFuncs = 0;
7564 pTIIface->TypeAttr.cImplTypes = 0;
7565 pTIIface->TypeAttr.cVars = 0;
7566 pTIIface->TypeAttr.wTypeFlags = 0;
7568 ppFuncDesc = &pTIIface->funclist;
7569 for(func = 0; func < pidata->cMembers; func++) {
7570 METHODDATA *md = pidata->pmethdata + func;
7571 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7572 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7573 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7574 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7575 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7576 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7577 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7578 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7579 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7580 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7581 (*ppFuncDesc)->funcdesc.cScodes = 0;
7582 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7583 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7584 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7585 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7586 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7587 md->cArgs * sizeof(ELEMDESC));
7588 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7589 md->cArgs * sizeof(TLBParDesc));
7590 for(param = 0; param < md->cArgs; param++) {
7591 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7592 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7594 (*ppFuncDesc)->helpcontext = 0;
7595 (*ppFuncDesc)->HelpStringContext = 0;
7596 (*ppFuncDesc)->HelpString = NULL;
7597 (*ppFuncDesc)->Entry = NULL;
7598 (*ppFuncDesc)->ctCustData = 0;
7599 (*ppFuncDesc)->pCustData = NULL;
7600 (*ppFuncDesc)->next = NULL;
7601 pTIIface->TypeAttr.cFuncs++;
7602 ppFuncDesc = &(*ppFuncDesc)->next;
7605 dump_TypeInfo(pTIIface);
7607 pTypeLibImpl->pTypeInfo = pTIIface;
7608 pTypeLibImpl->TypeInfoCount++;
7610 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7611 pTIClass->pTypeLib = pTypeLibImpl;
7612 pTIClass->index = 1;
7613 pTIClass->Name = NULL;
7614 pTIClass->dwHelpContext = -1;
7615 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7616 pTIClass->TypeAttr.lcid = lcid;
7617 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7618 pTIClass->TypeAttr.wMajorVerNum = 0;
7619 pTIClass->TypeAttr.wMinorVerNum = 0;
7620 pTIClass->TypeAttr.cbAlignment = 2;
7621 pTIClass->TypeAttr.cbSizeInstance = -1;
7622 pTIClass->TypeAttr.cbSizeVft = -1;
7623 pTIClass->TypeAttr.cFuncs = 0;
7624 pTIClass->TypeAttr.cImplTypes = 1;
7625 pTIClass->TypeAttr.cVars = 0;
7626 pTIClass->TypeAttr.wTypeFlags = 0;
7628 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7629 pTIClass->impltypelist->hRef = 0;
7631 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7632 ref->index = 0;
7633 ref->reference = 0;
7634 ref->pImpTLInfo = TLB_REF_INTERNAL;
7635 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7637 dump_TypeInfo(pTIClass);
7639 pTIIface->next = pTIClass;
7640 pTypeLibImpl->TypeInfoCount++;
7642 *pptinfo = (ITypeInfo*)pTIClass;
7644 ITypeInfo_AddRef(*pptinfo);
7645 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7647 return S_OK;
7651 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7653 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7655 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7658 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7660 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7662 return ITypeInfo_AddRef((ITypeInfo *)This);
7665 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7667 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7669 return ITypeInfo_Release((ITypeInfo *)This);
7672 static HRESULT WINAPI ITypeComp_fnBind(
7673 ITypeComp * iface,
7674 OLECHAR * szName,
7675 ULONG lHash,
7676 WORD wFlags,
7677 ITypeInfo ** ppTInfo,
7678 DESCKIND * pDescKind,
7679 BINDPTR * pBindPtr)
7681 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7682 const TLBFuncDesc *pFDesc;
7683 const TLBVarDesc *pVDesc;
7684 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7686 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7688 *pDescKind = DESCKIND_NONE;
7689 pBindPtr->lpfuncdesc = NULL;
7690 *ppTInfo = NULL;
7692 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7693 if (!strcmpiW(pFDesc->Name, szName)) {
7694 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7695 break;
7696 else
7697 /* name found, but wrong flags */
7698 hr = TYPE_E_TYPEMISMATCH;
7701 if (pFDesc)
7703 HRESULT hr = TLB_AllocAndInitFuncDesc(
7704 &pFDesc->funcdesc,
7705 &pBindPtr->lpfuncdesc,
7706 This->TypeAttr.typekind == TKIND_DISPATCH);
7707 if (FAILED(hr))
7708 return hr;
7709 *pDescKind = DESCKIND_FUNCDESC;
7710 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7711 ITypeInfo_AddRef(*ppTInfo);
7712 return S_OK;
7713 } else {
7714 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7715 if (!strcmpiW(pVDesc->Name, szName)) {
7716 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7717 if (FAILED(hr))
7718 return hr;
7719 *pDescKind = DESCKIND_VARDESC;
7720 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7721 ITypeInfo_AddRef(*ppTInfo);
7722 return S_OK;
7726 /* FIXME: search each inherited interface, not just the first */
7727 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7728 /* recursive search */
7729 ITypeInfo *pTInfo;
7730 ITypeComp *pTComp;
7731 HRESULT hr;
7732 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7733 if (SUCCEEDED(hr))
7735 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7736 ITypeInfo_Release(pTInfo);
7738 if (SUCCEEDED(hr))
7740 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7741 ITypeComp_Release(pTComp);
7742 return hr;
7744 WARN("Could not search inherited interface!\n");
7746 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7747 return hr;
7750 static HRESULT WINAPI ITypeComp_fnBindType(
7751 ITypeComp * iface,
7752 OLECHAR * szName,
7753 ULONG lHash,
7754 ITypeInfo ** ppTInfo,
7755 ITypeComp ** ppTComp)
7757 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7759 /* strange behaviour (does nothing) but like the
7760 * original */
7762 if (!ppTInfo || !ppTComp)
7763 return E_POINTER;
7765 *ppTInfo = NULL;
7766 *ppTComp = NULL;
7768 return S_OK;
7771 static const ITypeCompVtbl tcompvt =
7774 ITypeComp_fnQueryInterface,
7775 ITypeComp_fnAddRef,
7776 ITypeComp_fnRelease,
7778 ITypeComp_fnBind,
7779 ITypeComp_fnBindType