oleaut32: Implement basic ICreateTypeLib functions.
[wine.git] / dlls / oleaut32 / typelib.c
blob9bbd86f54d9a00faba95496a99af686353a3191e
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 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
45 * behaviour.
46 * -. lousy fatal error handling
50 #include "config.h"
51 #include "wine/port.h"
53 #include <stdlib.h>
54 #include <string.h>
55 #include <stdarg.h>
56 #include <stdio.h>
57 #include <ctype.h>
59 #define COBJMACROS
60 #define NONAMELESSUNION
61 #define NONAMELESSSTRUCT
63 #include "winerror.h"
64 #include "windef.h"
65 #include "winbase.h"
66 #include "winnls.h"
67 #include "winreg.h"
68 #include "winuser.h"
69 #include "lzexpand.h"
71 #include "wine/unicode.h"
72 #include "objbase.h"
73 #include "typelib.h"
74 #include "wine/debug.h"
75 #include "variant.h"
76 #include "wine/list.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib);
81 typedef struct
83 WORD offset;
84 WORD length;
85 WORD flags;
86 WORD id;
87 WORD handle;
88 WORD usage;
89 } NE_NAMEINFO;
91 typedef struct
93 WORD type_id; /* Type identifier */
94 WORD count; /* Number of resources of this type */
95 DWORD resloader; /* SetResourceHandler() */
97 * Name info array.
99 } NE_TYPEINFO;
101 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
102 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
104 /****************************************************************************
105 * FromLExxx
107 * Takes p_iVal (which is in little endian) and returns it
108 * in the host machine's byte order.
110 #ifdef WORDS_BIGENDIAN
111 static WORD FromLEWord(WORD p_iVal)
113 return (((p_iVal & 0x00FF) << 8) |
114 ((p_iVal & 0xFF00) >> 8));
118 static DWORD FromLEDWord(DWORD p_iVal)
120 return (((p_iVal & 0x000000FF) << 24) |
121 ((p_iVal & 0x0000FF00) << 8) |
122 ((p_iVal & 0x00FF0000) >> 8) |
123 ((p_iVal & 0xFF000000) >> 24));
125 #else
126 #define FromLEWord(X) (X)
127 #define FromLEDWord(X) (X)
128 #endif
130 #define DISPATCH_HREF_OFFSET 0x01000000
131 #define DISPATCH_HREF_MASK 0xff000000
133 /****************************************************************************
134 * FromLExxx
136 * Fix byte order in any structure if necessary
138 #ifdef WORDS_BIGENDIAN
139 static void FromLEWords(void *p_Val, int p_iSize)
141 WORD *Val = p_Val;
143 p_iSize /= sizeof(WORD);
145 while (p_iSize) {
146 *Val = FromLEWord(*Val);
147 Val++;
148 p_iSize--;
153 static void FromLEDWords(void *p_Val, int p_iSize)
155 DWORD *Val = p_Val;
157 p_iSize /= sizeof(DWORD);
159 while (p_iSize) {
160 *Val = FromLEDWord(*Val);
161 Val++;
162 p_iSize--;
165 #else
166 #define FromLEWords(X,Y) /*nothing*/
167 #define FromLEDWords(X,Y) /*nothing*/
168 #endif
171 * Find a typelib key which matches a requested maj.min version.
173 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
175 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
176 WCHAR buffer[60];
177 char key_name[16];
178 DWORD len, i;
179 INT best_maj = -1, best_min = -1;
180 HKEY hkey;
182 memcpy( buffer, typelibW, sizeof(typelibW) );
183 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
185 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
186 return FALSE;
188 len = sizeof(key_name);
189 i = 0;
190 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
192 INT v_maj, v_min;
194 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
196 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
198 if (*wMaj == 0xffff && *wMin == 0xffff)
200 if (v_maj > best_maj) best_maj = v_maj;
201 if (v_min > best_min) best_min = v_min;
203 else if (*wMaj == v_maj)
205 best_maj = v_maj;
207 if (*wMin == v_min)
209 best_min = v_min;
210 break; /* exact match */
212 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
215 len = sizeof(key_name);
217 RegCloseKey( hkey );
219 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
221 if (*wMaj == 0xffff && *wMin == 0xffff)
223 if (best_maj >= 0 && best_min >= 0)
225 *wMaj = best_maj;
226 *wMin = best_min;
227 return TRUE;
231 if (*wMaj == best_maj && best_min >= 0)
233 *wMin = best_min;
234 return TRUE;
236 return FALSE;
239 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
240 /* buffer must be at least 60 characters long */
241 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
243 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
244 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
246 memcpy( buffer, TypelibW, sizeof(TypelibW) );
247 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
248 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
249 return buffer;
252 /* get the path of an interface key, in the form "Interface\\<guid>" */
253 /* buffer must be at least 50 characters long */
254 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
256 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
258 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
259 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
260 return buffer;
263 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
264 /* buffer must be at least 16 characters long */
265 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
267 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
268 static const WCHAR win16W[] = {'w','i','n','1','6',0};
269 static const WCHAR win32W[] = {'w','i','n','3','2',0};
270 static const WCHAR win64W[] = {'w','i','n','6','4',0};
272 sprintfW( buffer, LcidFormatW, lcid );
273 switch(syskind)
275 case SYS_WIN16: strcatW( buffer, win16W ); break;
276 case SYS_WIN32: strcatW( buffer, win32W ); break;
277 case SYS_WIN64: strcatW( buffer, win64W ); break;
278 default:
279 TRACE("Typelib is for unsupported syskind %i\n", syskind);
280 return NULL;
282 return buffer;
285 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
288 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
289 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
290 SYSKIND syskind, LCID lcid, LPBSTR path )
292 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
293 LCID myLCID = lcid;
294 HKEY hkey;
295 WCHAR buffer[60];
296 WCHAR Path[MAX_PATH];
297 LONG res;
299 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
301 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
302 get_typelib_key( guid, wMaj, wMin, buffer );
304 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
305 if (res == ERROR_FILE_NOT_FOUND)
307 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
308 return TYPE_E_LIBNOTREGISTERED;
310 else if (res != ERROR_SUCCESS)
312 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
313 return TYPE_E_REGISTRYACCESS;
316 while (hr != S_OK)
318 LONG dwPathLen = sizeof(Path);
320 get_lcid_subkey( myLCID, syskind, buffer );
322 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
324 if (!lcid)
325 break;
326 else if (myLCID == lcid)
328 /* try with sub-langid */
329 myLCID = SUBLANGID(lcid);
331 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
333 /* try with system langid */
334 myLCID = 0;
336 else
338 break;
341 else
343 *path = SysAllocString( Path );
344 hr = S_OK;
347 RegCloseKey( hkey );
348 TRACE_(typelib)("-- 0x%08x\n", hr);
349 return hr;
352 /****************************************************************************
353 * QueryPathOfRegTypeLib [OLEAUT32.164]
355 * Gets the path to a registered type library.
357 * PARAMS
358 * guid [I] referenced guid
359 * wMaj [I] major version
360 * wMin [I] minor version
361 * lcid [I] locale id
362 * path [O] path of typelib
364 * RETURNS
365 * Success: S_OK.
366 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
367 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
368 * opened.
370 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
372 #ifdef _WIN64
373 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path );
374 if(SUCCEEDED(hres))
375 return hres;
376 #endif
377 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
380 /******************************************************************************
381 * CreateTypeLib [OLEAUT32.160] creates a typelib
383 * RETURNS
384 * Success: S_OK
385 * Failure: Status
387 HRESULT WINAPI CreateTypeLib(
388 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
390 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
391 return E_FAIL;
394 /******************************************************************************
395 * LoadTypeLib [OLEAUT32.161]
397 * Loads a type library
399 * PARAMS
400 * szFile [I] Name of file to load from.
401 * pptLib [O] Pointer that receives ITypeLib object on success.
403 * RETURNS
404 * Success: S_OK
405 * Failure: Status
407 * SEE
408 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
410 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
412 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
413 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
416 /******************************************************************************
417 * LoadTypeLibEx [OLEAUT32.183]
419 * Loads and optionally registers a type library
421 * RETURNS
422 * Success: S_OK
423 * Failure: Status
425 HRESULT WINAPI LoadTypeLibEx(
426 LPCOLESTR szFile, /* [in] Name of file to load from */
427 REGKIND regkind, /* [in] Specify kind of registration */
428 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
430 WCHAR szPath[MAX_PATH+1];
431 HRESULT res;
433 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
435 *pptLib = NULL;
437 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
439 if (SUCCEEDED(res))
440 switch(regkind)
442 case REGKIND_DEFAULT:
443 /* don't register typelibs supplied with full path. Experimentation confirms the following */
444 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
445 (szFile[0] && (szFile[1] == ':'))) break;
446 /* else fall-through */
448 case REGKIND_REGISTER:
449 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
451 ITypeLib_Release(*pptLib);
452 *pptLib = 0;
454 break;
455 case REGKIND_NONE:
456 break;
459 TRACE(" returns %08x\n",res);
460 return res;
463 /******************************************************************************
464 * LoadRegTypeLib [OLEAUT32.162]
466 * Loads a registered type library.
468 * PARAMS
469 * rguid [I] GUID of the registered type library.
470 * wVerMajor [I] major version.
471 * wVerMinor [I] minor version.
472 * lcid [I] locale ID.
473 * ppTLib [O] pointer that receives an ITypeLib object on success.
475 * RETURNS
476 * Success: S_OK.
477 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
478 * LoadTypeLib.
480 HRESULT WINAPI LoadRegTypeLib(
481 REFGUID rguid,
482 WORD wVerMajor,
483 WORD wVerMinor,
484 LCID lcid,
485 ITypeLib **ppTLib)
487 BSTR bstr=NULL;
488 HRESULT res;
490 *ppTLib = NULL;
492 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
494 if(SUCCEEDED(res))
496 res= LoadTypeLib(bstr, ppTLib);
497 SysFreeString(bstr);
500 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
502 return res;
506 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
507 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
508 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
509 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
510 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
511 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
513 /******************************************************************************
514 * RegisterTypeLib [OLEAUT32.163]
515 * Adds information about a type library to the System Registry
516 * NOTES
517 * Docs: ITypeLib FAR * ptlib
518 * Docs: OLECHAR FAR* szFullPath
519 * Docs: OLECHAR FAR* szHelpDir
521 * RETURNS
522 * Success: S_OK
523 * Failure: Status
525 HRESULT WINAPI RegisterTypeLib(
526 ITypeLib * ptlib, /* [in] Pointer to the library*/
527 OLECHAR * szFullPath, /* [in] full Path of the library*/
528 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
529 may be NULL*/
531 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
532 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
533 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
534 HRESULT res;
535 TLIBATTR *attr;
536 WCHAR keyName[60];
537 WCHAR tmp[16];
538 HKEY key, subKey;
539 UINT types, tidx;
540 TYPEKIND kind;
541 DWORD disposition;
543 if (ptlib == NULL || szFullPath == NULL)
544 return E_INVALIDARG;
546 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
547 return E_FAIL;
549 #ifdef _WIN64
550 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
551 #else
552 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
553 #endif
555 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
557 res = S_OK;
558 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
559 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
561 LPOLESTR doc;
563 /* Set the human-readable name of the typelib */
564 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
565 res = E_FAIL;
566 else if (doc)
568 if (RegSetValueExW(key, NULL, 0, REG_SZ,
569 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
570 res = E_FAIL;
572 SysFreeString(doc);
575 /* Make up the name of the typelib path subkey */
576 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
578 /* Create the typelib path subkey */
579 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
580 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
582 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
583 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
584 res = E_FAIL;
586 RegCloseKey(subKey);
588 else
589 res = E_FAIL;
591 /* Create the flags subkey */
592 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
593 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
595 /* FIXME: is %u correct? */
596 static const WCHAR formatW[] = {'%','u',0};
597 WCHAR buf[20];
598 sprintfW(buf, formatW, attr->wLibFlags);
599 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
600 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
601 res = E_FAIL;
603 RegCloseKey(subKey);
605 else
606 res = E_FAIL;
608 /* create the helpdir subkey */
609 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
610 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
612 BOOL freeHelpDir = FALSE;
613 OLECHAR* pIndexStr;
615 /* if we created a new key, and helpDir was null, set the helpdir
616 to the directory which contains the typelib. However,
617 if we just opened an existing key, we leave the helpdir alone */
618 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
619 szHelpDir = SysAllocString(szFullPath);
620 pIndexStr = strrchrW(szHelpDir, '\\');
621 if (pIndexStr) {
622 *pIndexStr = 0;
624 freeHelpDir = TRUE;
627 /* if we have an szHelpDir, set it! */
628 if (szHelpDir != NULL) {
629 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
630 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
631 res = E_FAIL;
635 /* tidy up */
636 if (freeHelpDir) SysFreeString(szHelpDir);
637 RegCloseKey(subKey);
639 } else {
640 res = E_FAIL;
643 RegCloseKey(key);
645 else
646 res = E_FAIL;
648 /* register OLE Automation-compatible interfaces for this typelib */
649 types = ITypeLib_GetTypeInfoCount(ptlib);
650 for (tidx=0; tidx<types; tidx++) {
651 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
652 LPOLESTR name = NULL;
653 ITypeInfo *tinfo = NULL;
655 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
657 switch (kind) {
658 case TKIND_INTERFACE:
659 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
660 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
661 break;
663 case TKIND_DISPATCH:
664 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
665 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
666 break;
668 default:
669 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
670 break;
673 if (tinfo) {
674 TYPEATTR *tattr = NULL;
675 ITypeInfo_GetTypeAttr(tinfo, &tattr);
677 if (tattr) {
678 TRACE_(typelib)("guid=%s, flags=%04x (",
679 debugstr_guid(&tattr->guid),
680 tattr->wTypeFlags);
682 if (TRACE_ON(typelib)) {
683 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
684 XX(FAPPOBJECT);
685 XX(FCANCREATE);
686 XX(FLICENSED);
687 XX(FPREDECLID);
688 XX(FHIDDEN);
689 XX(FCONTROL);
690 XX(FDUAL);
691 XX(FNONEXTENSIBLE);
692 XX(FOLEAUTOMATION);
693 XX(FRESTRICTED);
694 XX(FAGGREGATABLE);
695 XX(FREPLACEABLE);
696 XX(FDISPATCHABLE);
697 XX(FREVERSEBIND);
698 XX(FPROXY);
699 #undef XX
700 MESSAGE("\n");
703 /* Register all dispinterfaces (which includes dual interfaces) and
704 oleautomation interfaces */
705 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
706 kind == TKIND_DISPATCH)
708 /* register interface<->typelib coupling */
709 get_interface_key( &tattr->guid, keyName );
710 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
711 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
713 if (name)
714 RegSetValueExW(key, NULL, 0, REG_SZ,
715 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
717 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
718 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
719 RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (const BYTE *)PSOA, sizeof PSOA);
721 RegCloseKey(subKey);
724 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
725 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
726 RegSetValueExW(subKey, NULL, 0, REG_SZ,
727 (const BYTE *)PSOA, sizeof PSOA);
728 RegCloseKey(subKey);
731 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
732 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
734 WCHAR buffer[40];
735 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
736 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
738 StringFromGUID2(&attr->guid, buffer, 40);
739 RegSetValueExW(subKey, NULL, 0, REG_SZ,
740 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
741 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
742 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
743 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
744 RegCloseKey(subKey);
747 RegCloseKey(key);
751 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
754 ITypeInfo_Release(tinfo);
757 SysFreeString(name);
761 ITypeLib_ReleaseTLibAttr(ptlib, attr);
763 return res;
767 /******************************************************************************
768 * UnRegisterTypeLib [OLEAUT32.186]
769 * Removes information about a type library from the System Registry
770 * NOTES
772 * RETURNS
773 * Success: S_OK
774 * Failure: Status
776 HRESULT WINAPI UnRegisterTypeLib(
777 REFGUID libid, /* [in] Guid of the library */
778 WORD wVerMajor, /* [in] major version */
779 WORD wVerMinor, /* [in] minor version */
780 LCID lcid, /* [in] locale id */
781 SYSKIND syskind)
783 BSTR tlibPath = NULL;
784 DWORD tmpLength;
785 WCHAR keyName[60];
786 WCHAR subKeyName[50];
787 int result = S_OK;
788 DWORD i = 0;
789 BOOL deleteOtherStuff;
790 HKEY key = NULL;
791 HKEY subKey = NULL;
792 TYPEATTR* typeAttr = NULL;
793 TYPEKIND kind;
794 ITypeInfo* typeInfo = NULL;
795 ITypeLib* typeLib = NULL;
796 int numTypes;
798 TRACE("(IID: %s)\n",debugstr_guid(libid));
800 /* Create the path to the key */
801 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
803 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
805 TRACE("Unsupported syskind %i\n", syskind);
806 result = E_INVALIDARG;
807 goto end;
810 /* get the path to the typelib on disk */
811 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
812 result = E_INVALIDARG;
813 goto end;
816 /* Try and open the key to the type library. */
817 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
818 result = E_INVALIDARG;
819 goto end;
822 /* Try and load the type library */
823 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
824 result = TYPE_E_INVALIDSTATE;
825 goto end;
828 /* remove any types registered with this typelib */
829 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
830 for (i=0; i<numTypes; i++) {
831 /* get the kind of type */
832 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
833 goto enddeleteloop;
836 /* skip non-interfaces, and get type info for the type */
837 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
838 goto enddeleteloop;
840 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
841 goto enddeleteloop;
843 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
844 goto enddeleteloop;
847 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
848 kind == TKIND_DISPATCH)
850 /* the path to the type */
851 get_interface_key( &typeAttr->guid, subKeyName );
853 /* Delete its bits */
854 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
855 goto enddeleteloop;
857 RegDeleteKeyW(subKey, ProxyStubClsidW);
858 RegDeleteKeyW(subKey, ProxyStubClsid32W);
859 RegDeleteKeyW(subKey, TypeLibW);
860 RegCloseKey(subKey);
861 subKey = NULL;
862 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
865 enddeleteloop:
866 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
867 typeAttr = NULL;
868 if (typeInfo) ITypeInfo_Release(typeInfo);
869 typeInfo = NULL;
872 /* Now, delete the type library path subkey */
873 get_lcid_subkey( lcid, syskind, subKeyName );
874 RegDeleteKeyW(key, subKeyName);
875 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
876 RegDeleteKeyW(key, subKeyName);
878 /* check if there is anything besides the FLAGS/HELPDIR keys.
879 If there is, we don't delete them */
880 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
881 deleteOtherStuff = TRUE;
882 i = 0;
883 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
884 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
886 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
887 if (!strcmpW(subKeyName, FLAGSW)) continue;
888 if (!strcmpW(subKeyName, HELPDIRW)) continue;
889 deleteOtherStuff = FALSE;
890 break;
893 /* only delete the other parts of the key if we're absolutely sure */
894 if (deleteOtherStuff) {
895 RegDeleteKeyW(key, FLAGSW);
896 RegDeleteKeyW(key, HELPDIRW);
897 RegCloseKey(key);
898 key = NULL;
900 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
901 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
902 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
905 end:
906 SysFreeString(tlibPath);
907 if (typeLib) ITypeLib_Release(typeLib);
908 if (subKey) RegCloseKey(subKey);
909 if (key) RegCloseKey(key);
910 return result;
913 /******************************************************************************
914 * RegisterTypeLibForUser [OLEAUT32.442]
915 * Adds information about a type library to the user registry
916 * NOTES
917 * Docs: ITypeLib FAR * ptlib
918 * Docs: OLECHAR FAR* szFullPath
919 * Docs: OLECHAR FAR* szHelpDir
921 * RETURNS
922 * Success: S_OK
923 * Failure: Status
925 HRESULT WINAPI RegisterTypeLibForUser(
926 ITypeLib * ptlib, /* [in] Pointer to the library*/
927 OLECHAR * szFullPath, /* [in] full Path of the library*/
928 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
929 may be NULL*/
931 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
932 debugstr_w(szFullPath), debugstr_w(szHelpDir));
933 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
936 /******************************************************************************
937 * UnRegisterTypeLibForUser [OLEAUT32.443]
938 * Removes information about a type library from the user registry
940 * RETURNS
941 * Success: S_OK
942 * Failure: Status
944 HRESULT WINAPI UnRegisterTypeLibForUser(
945 REFGUID libid, /* [in] GUID of the library */
946 WORD wVerMajor, /* [in] major version */
947 WORD wVerMinor, /* [in] minor version */
948 LCID lcid, /* [in] locale id */
949 SYSKIND syskind)
951 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
952 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
953 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
956 /*======================= ITypeLib implementation =======================*/
958 typedef struct tagTLBCustData
960 GUID guid;
961 VARIANT data;
962 struct list entry;
963 } TLBCustData;
965 /* data structure for import typelibs */
966 typedef struct tagTLBImpLib
968 int offset; /* offset in the file (MSFT)
969 offset in nametable (SLTG)
970 just used to identify library while reading
971 data from file */
972 GUID guid; /* libid */
973 BSTR name; /* name */
975 LCID lcid; /* lcid of imported typelib */
977 WORD wVersionMajor; /* major version number */
978 WORD wVersionMinor; /* minor version number */
980 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
981 NULL if not yet loaded */
982 struct list entry;
983 } TLBImpLib;
985 /* internal ITypeLib data */
986 typedef struct tagITypeLibImpl
988 ITypeLib2 ITypeLib2_iface;
989 ITypeComp ITypeComp_iface;
990 ICreateTypeLib2 ICreateTypeLib2_iface;
991 LONG ref;
992 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
993 LCID lcid;
995 /* strings can be stored in tlb as multibyte strings BUT they are *always*
996 * exported to the application as a UNICODE string.
998 BSTR Name;
999 BSTR DocString;
1000 BSTR HelpFile;
1001 BSTR HelpStringDll;
1002 DWORD dwHelpContext;
1003 int TypeInfoCount; /* nr of typeinfo's in librarry */
1004 struct tagITypeInfoImpl **typeinfos;
1005 struct list custdata_list;
1006 struct list implib_list;
1007 int ctTypeDesc; /* number of items in type desc array */
1008 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1009 library. Only used while reading MSFT
1010 typelibs */
1011 struct list ref_list; /* list of ref types in this typelib */
1012 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1015 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1016 struct list entry;
1017 WCHAR *path;
1018 INT index;
1019 } ITypeLibImpl;
1021 static const ITypeLib2Vtbl tlbvt;
1022 static const ITypeCompVtbl tlbtcvt;
1023 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1025 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1027 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1030 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1032 return impl_from_ITypeLib2((ITypeLib2*)iface);
1035 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1037 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1040 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1042 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1045 /* ITypeLib methods */
1046 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1047 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1049 /*======================= ITypeInfo implementation =======================*/
1051 /* data for referenced types */
1052 typedef struct tagTLBRefType
1054 INT index; /* Type index for internal ref or for external ref
1055 it the format is SLTG. -2 indicates to
1056 use guid */
1058 GUID guid; /* guid of the referenced type */
1059 /* if index == TLB_REF_USE_GUID */
1061 HREFTYPE reference; /* The href of this ref */
1062 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1063 TLB_REF_INTERNAL for internal refs
1064 TLB_REF_NOT_FOUND for broken refs */
1066 struct list entry;
1067 } TLBRefType;
1069 #define TLB_REF_USE_GUID -2
1071 #define TLB_REF_INTERNAL (void*)-2
1072 #define TLB_REF_NOT_FOUND (void*)-1
1074 /* internal Parameter data */
1075 typedef struct tagTLBParDesc
1077 BSTR Name;
1078 struct list custdata_list;
1079 } TLBParDesc;
1081 /* internal Function data */
1082 typedef struct tagTLBFuncDesc
1084 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1085 BSTR Name; /* the name of this function */
1086 TLBParDesc *pParamDesc; /* array with param names and custom data */
1087 int helpcontext;
1088 int HelpStringContext;
1089 BSTR HelpString;
1090 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1091 struct list custdata_list;
1092 } TLBFuncDesc;
1094 /* internal Variable data */
1095 typedef struct tagTLBVarDesc
1097 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1098 BSTR Name; /* the name of this variable */
1099 int HelpContext;
1100 int HelpStringContext;
1101 BSTR HelpString;
1102 struct list custdata_list;
1103 } TLBVarDesc;
1105 /* internal implemented interface data */
1106 typedef struct tagTLBImplType
1108 HREFTYPE hRef; /* hRef of interface */
1109 int implflags; /* IMPLFLAG_*s */
1110 struct list custdata_list;
1111 } TLBImplType;
1113 /* internal TypeInfo data */
1114 typedef struct tagITypeInfoImpl
1116 ITypeInfo2 ITypeInfo2_iface;
1117 ITypeComp ITypeComp_iface;
1118 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1119 LONG ref;
1120 BOOL not_attached_to_typelib;
1121 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1122 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1123 int index; /* index in this typelib; */
1124 HREFTYPE hreftype; /* hreftype for app object binding */
1125 /* type libs seem to store the doc strings in ascii
1126 * so why should we do it in unicode?
1128 BSTR Name;
1129 BSTR DocString;
1130 BSTR DllName;
1131 DWORD dwHelpContext;
1132 DWORD dwHelpStringContext;
1134 /* functions */
1135 TLBFuncDesc *funcdescs;
1137 /* variables */
1138 TLBVarDesc *vardescs;
1140 /* Implemented Interfaces */
1141 TLBImplType *impltypes;
1143 struct list custdata_list;
1144 } ITypeInfoImpl;
1146 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1148 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1151 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1153 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1156 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1158 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1161 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1163 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1166 static const ITypeInfo2Vtbl tinfvt;
1167 static const ITypeCompVtbl tcompvt;
1168 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1170 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1171 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1173 typedef struct tagTLBContext
1175 unsigned int oStart; /* start of TLB in file */
1176 unsigned int pos; /* current pos */
1177 unsigned int length; /* total length */
1178 void *mapping; /* memory mapping */
1179 MSFT_SegDir * pTblDir;
1180 ITypeLibImpl* pLibInfo;
1181 } TLBContext;
1184 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1187 debug
1189 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1190 if (pTD->vt & VT_RESERVED)
1191 szVarType += strlen(strcpy(szVarType, "reserved | "));
1192 if (pTD->vt & VT_BYREF)
1193 szVarType += strlen(strcpy(szVarType, "ref to "));
1194 if (pTD->vt & VT_ARRAY)
1195 szVarType += strlen(strcpy(szVarType, "array of "));
1196 if (pTD->vt & VT_VECTOR)
1197 szVarType += strlen(strcpy(szVarType, "vector of "));
1198 switch(pTD->vt & VT_TYPEMASK) {
1199 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1200 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1201 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1202 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1203 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1204 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1205 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1206 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1207 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1208 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1209 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1210 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1211 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1212 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1213 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1214 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1215 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1216 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1217 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1218 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1219 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1220 pTD->u.hreftype); break;
1221 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1222 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1223 case VT_PTR: sprintf(szVarType, "ptr to ");
1224 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1225 break;
1226 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1227 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1228 break;
1229 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1230 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1231 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1232 break;
1234 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1238 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1239 char buf[200];
1240 USHORT flags = edesc->u.paramdesc.wParamFlags;
1241 dump_TypeDesc(&edesc->tdesc,buf);
1242 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1243 MESSAGE("\t\tu.paramdesc.wParamFlags");
1244 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1245 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1246 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1247 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1248 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1249 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1250 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1251 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1252 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1254 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1255 int i;
1256 MESSAGE("memid is %08x\n",funcdesc->memid);
1257 for (i=0;i<funcdesc->cParams;i++) {
1258 MESSAGE("Param %d:\n",i);
1259 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1261 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1262 switch (funcdesc->funckind) {
1263 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1264 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1265 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1266 case FUNC_STATIC: MESSAGE("static");break;
1267 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1268 default: MESSAGE("unknown");break;
1270 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1271 switch (funcdesc->invkind) {
1272 case INVOKE_FUNC: MESSAGE("func");break;
1273 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1274 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1275 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1277 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1278 switch (funcdesc->callconv) {
1279 case CC_CDECL: MESSAGE("cdecl");break;
1280 case CC_PASCAL: MESSAGE("pascal");break;
1281 case CC_STDCALL: MESSAGE("stdcall");break;
1282 case CC_SYSCALL: MESSAGE("syscall");break;
1283 default:break;
1285 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1286 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1287 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1289 MESSAGE("\telemdescFunc (return value type):\n");
1290 dump_ELEMDESC(&funcdesc->elemdescFunc);
1293 static const char * const typekind_desc[] =
1295 "TKIND_ENUM",
1296 "TKIND_RECORD",
1297 "TKIND_MODULE",
1298 "TKIND_INTERFACE",
1299 "TKIND_DISPATCH",
1300 "TKIND_COCLASS",
1301 "TKIND_ALIAS",
1302 "TKIND_UNION",
1303 "TKIND_MAX"
1306 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1308 int i;
1309 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1310 for (i=0;i<pfd->funcdesc.cParams;i++)
1311 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1314 dump_FUNCDESC(&(pfd->funcdesc));
1316 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1317 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1319 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1321 while (n)
1323 dump_TLBFuncDescOne(pfd);
1324 ++pfd;
1325 --n;
1328 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1330 while (n)
1332 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1333 ++pvd;
1334 --n;
1338 static void dump_TLBImpLib(const TLBImpLib *import)
1340 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1341 debugstr_w(import->name));
1342 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1343 import->wVersionMinor, import->lcid, import->offset);
1346 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1348 TLBRefType *ref;
1350 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1352 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1353 if(ref->index == -1)
1354 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1355 else
1356 TRACE_(typelib)("type no: %d\n", ref->index);
1358 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1360 TRACE_(typelib)("in lib\n");
1361 dump_TLBImpLib(ref->pImpTLInfo);
1366 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1368 if(!impl)
1369 return;
1370 while (n) {
1371 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1372 impl->hRef, impl->implflags);
1373 ++impl;
1374 --n;
1378 static void dump_Variant(const VARIANT * pvar)
1380 SYSTEMTIME st;
1382 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1384 if (pvar)
1386 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1387 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1389 TRACE(",%p", V_BYREF(pvar));
1391 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1393 TRACE(",%p", V_ARRAY(pvar));
1395 else switch (V_TYPE(pvar))
1397 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1398 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1399 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1400 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1401 case VT_INT:
1402 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1403 case VT_UINT:
1404 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1405 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1406 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1407 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1408 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1409 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1410 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1411 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1412 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1413 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1414 V_CY(pvar).s.Lo); break;
1415 case VT_DATE:
1416 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1417 TRACE(",<invalid>");
1418 else
1419 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1420 st.wHour, st.wMinute, st.wSecond);
1421 break;
1422 case VT_ERROR:
1423 case VT_VOID:
1424 case VT_USERDEFINED:
1425 case VT_EMPTY:
1426 case VT_NULL: break;
1427 default: TRACE(",?"); break;
1430 TRACE("}\n");
1433 static void dump_DispParms(const DISPPARAMS * pdp)
1435 unsigned int index;
1437 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1439 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1441 TRACE("named args:\n");
1442 for (index = 0; index < pdp->cNamedArgs; index++)
1443 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1446 if (pdp->cArgs && pdp->rgvarg)
1448 TRACE("args:\n");
1449 for (index = 0; index < pdp->cArgs; index++)
1450 dump_Variant( &pdp->rgvarg[index] );
1454 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1456 TRACE("%p ref=%u\n", pty, pty->ref);
1457 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1458 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1459 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1460 TRACE("fct:%u var:%u impl:%u\n",
1461 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1462 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1463 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1464 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1465 if (TRACE_ON(ole))
1466 dump_TLBFuncDesc(pty->funcdescs, pty->TypeAttr.cFuncs);
1467 dump_TLBVarDesc(pty->vardescs, pty->TypeAttr.cVars);
1468 dump_TLBImplType(pty->impltypes, pty->TypeAttr.cImplTypes);
1471 static void dump_VARDESC(const VARDESC *v)
1473 MESSAGE("memid %d\n",v->memid);
1474 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1475 MESSAGE("oInst %d\n",v->u.oInst);
1476 dump_ELEMDESC(&(v->elemdescVar));
1477 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1478 MESSAGE("varkind %d\n",v->varkind);
1481 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1483 /* VT_LPWSTR is largest type that, may appear in type description */
1484 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1485 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1486 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1487 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1488 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1489 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1490 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1491 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1494 static void TLB_abort(void)
1496 DebugBreak();
1499 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1501 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1502 if (!ret) ERR("cannot allocate memory\n");
1503 return ret;
1506 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1508 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1509 if (!ret) ERR("cannot allocate memory\n");
1510 return ret;
1513 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1515 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1518 void heap_free(void *ptr)
1520 HeapFree(GetProcessHeap(), 0, ptr);
1523 /* returns the size required for a deep copy of a typedesc into a
1524 * flat buffer */
1525 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1527 SIZE_T size = 0;
1529 if (alloc_initial_space)
1530 size += sizeof(TYPEDESC);
1532 switch (tdesc->vt)
1534 case VT_PTR:
1535 case VT_SAFEARRAY:
1536 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1537 break;
1538 case VT_CARRAY:
1539 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1540 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1541 break;
1543 return size;
1546 /* deep copy a typedesc into a flat buffer */
1547 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1549 if (!dest)
1551 dest = buffer;
1552 buffer = (char *)buffer + sizeof(TYPEDESC);
1555 *dest = *src;
1557 switch (src->vt)
1559 case VT_PTR:
1560 case VT_SAFEARRAY:
1561 dest->u.lptdesc = buffer;
1562 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1563 break;
1564 case VT_CARRAY:
1565 dest->u.lpadesc = buffer;
1566 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1567 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1568 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1569 break;
1571 return buffer;
1574 /* free custom data allocated by MSFT_CustData */
1575 static inline void TLB_FreeCustData(struct list *custdata_list)
1577 TLBCustData *cd, *cdn;
1578 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1580 list_remove(&cd->entry);
1581 VariantClear(&cd->data);
1582 heap_free(cd);
1586 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1588 DWORD len;
1589 BSTR ret;
1591 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1592 ret = SysAllocStringLen(NULL, len - 1);
1593 if (!ret) return ret;
1594 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1595 return ret;
1598 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1599 UINT n, MEMBERID memid)
1601 while(n){
1602 if(funcdescs->funcdesc.memid == memid)
1603 return funcdescs;
1604 ++funcdescs;
1605 --n;
1607 return NULL;
1610 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1611 UINT n, const OLECHAR *name)
1613 while(n){
1614 if(!lstrcmpiW(funcdescs->Name, name))
1615 return funcdescs;
1616 ++funcdescs;
1617 --n;
1619 return NULL;
1622 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1623 UINT n, MEMBERID memid)
1625 while(n){
1626 if(vardescs->vardesc.memid == memid)
1627 return vardescs;
1628 ++vardescs;
1629 --n;
1631 return NULL;
1634 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1635 UINT n, const OLECHAR *name)
1637 while(n){
1638 if(!lstrcmpiW(vardescs->Name, name))
1639 return vardescs;
1640 ++vardescs;
1641 --n;
1643 return NULL;
1646 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1648 TLBCustData *cust_data;
1649 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1650 if(IsEqualIID(&cust_data->guid, guid))
1651 return cust_data;
1652 return NULL;
1655 static TLBVarDesc *TLBVarDesc_Constructor(UINT n)
1657 TLBVarDesc *ret;
1659 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1660 if(!ret)
1661 return NULL;
1663 while(n){
1664 list_init(&ret[n-1].custdata_list);
1665 --n;
1668 return ret;
1671 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1673 TLBParDesc *ret;
1675 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1676 if(!ret)
1677 return NULL;
1679 while(n){
1680 list_init(&ret[n-1].custdata_list);
1681 --n;
1684 return ret;
1687 static TLBFuncDesc *TLBFuncDesc_Constructor(UINT n)
1689 TLBFuncDesc *ret;
1691 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1692 if(!ret)
1693 return NULL;
1695 while(n){
1696 list_init(&ret[n-1].custdata_list);
1697 --n;
1700 return ret;
1703 static TLBImplType *TLBImplType_Constructor(UINT n)
1705 TLBImplType *ret;
1707 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1708 if(!ret)
1709 return NULL;
1711 while(n){
1712 list_init(&ret[n-1].custdata_list);
1713 --n;
1716 return ret;
1719 /**********************************************************************
1721 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1723 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1725 return pcx->pos;
1728 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1730 if (where != DO_NOT_SEEK)
1732 where += pcx->oStart;
1733 if (where > pcx->length)
1735 /* FIXME */
1736 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1737 TLB_abort();
1739 pcx->pos = where;
1743 /* read function */
1744 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1746 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1747 pcx->pos, count, pcx->oStart, pcx->length, where);
1749 MSFT_Seek(pcx, where);
1750 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1751 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1752 pcx->pos += count;
1753 return count;
1756 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1757 LONG where )
1759 DWORD ret;
1761 ret = MSFT_Read(buffer, count, pcx, where);
1762 FromLEDWords(buffer, ret);
1764 return ret;
1767 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1768 LONG where )
1770 DWORD ret;
1772 ret = MSFT_Read(buffer, count, pcx, where);
1773 FromLEWords(buffer, ret);
1775 return ret;
1778 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1780 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1781 memset(pGuid,0, sizeof(GUID));
1782 return;
1784 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1785 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1786 pGuid->Data2 = FromLEWord(pGuid->Data2);
1787 pGuid->Data3 = FromLEWord(pGuid->Data3);
1788 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1791 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1793 MSFT_NameIntro niName;
1795 if (offset < 0)
1797 ERR_(typelib)("bad offset %d\n", offset);
1798 return -1;
1801 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1802 pcx->pTblDir->pNametab.offset+offset);
1804 return niName.hreftype;
1807 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1809 char * name;
1810 MSFT_NameIntro niName;
1811 int lengthInChars;
1812 BSTR bstrName = NULL;
1814 if (offset < 0)
1816 ERR_(typelib)("bad offset %d\n", offset);
1817 return NULL;
1819 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1820 pcx->pTblDir->pNametab.offset+offset);
1821 niName.namelen &= 0xFF; /* FIXME: correct ? */
1822 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1823 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1824 name[niName.namelen & 0xff]='\0';
1826 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1827 name, -1, NULL, 0);
1829 /* no invalid characters in string */
1830 if (lengthInChars)
1832 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1834 /* don't check for invalid character since this has been done previously */
1835 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1837 heap_free(name);
1839 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1840 return bstrName;
1843 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1845 char * string;
1846 INT16 length;
1847 int lengthInChars;
1848 BSTR bstr = NULL;
1850 if(offset<0) return NULL;
1851 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1852 if(length <= 0) return 0;
1853 string = heap_alloc_zero(length +1);
1854 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1855 string[length]='\0';
1857 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1858 string, -1, NULL, 0);
1860 /* no invalid characters in string */
1861 if (lengthInChars)
1863 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1865 /* don't check for invalid character since this has been done previously */
1866 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1868 heap_free(string);
1870 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1871 return bstr;
1874 * read a value and fill a VARIANT structure
1876 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1878 int size;
1880 TRACE_(typelib)("\n");
1882 if(offset <0) { /* data are packed in here */
1883 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1884 V_I4(pVar) = offset & 0x3ffffff;
1885 return;
1887 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1888 pcx->pTblDir->pCustData.offset + offset );
1889 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1890 switch (V_VT(pVar)){
1891 case VT_EMPTY: /* FIXME: is this right? */
1892 case VT_NULL: /* FIXME: is this right? */
1893 case VT_I2 : /* this should not happen */
1894 case VT_I4 :
1895 case VT_R4 :
1896 case VT_ERROR :
1897 case VT_BOOL :
1898 case VT_I1 :
1899 case VT_UI1 :
1900 case VT_UI2 :
1901 case VT_UI4 :
1902 case VT_INT :
1903 case VT_UINT :
1904 case VT_VOID : /* FIXME: is this right? */
1905 case VT_HRESULT :
1906 size=4; break;
1907 case VT_R8 :
1908 case VT_CY :
1909 case VT_DATE :
1910 case VT_I8 :
1911 case VT_UI8 :
1912 case VT_DECIMAL : /* FIXME: is this right? */
1913 case VT_FILETIME :
1914 size=8;break;
1915 /* pointer types with known behaviour */
1916 case VT_BSTR :{
1917 char * ptr;
1918 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1919 if(size < 0) {
1920 char next;
1921 DWORD origPos = MSFT_Tell(pcx), nullPos;
1923 do {
1924 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1925 } while (next);
1926 nullPos = MSFT_Tell(pcx);
1927 size = nullPos - origPos;
1928 MSFT_Seek(pcx, origPos);
1930 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1931 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1932 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1933 /* FIXME: do we need a AtoW conversion here? */
1934 V_UNION(pVar, bstrVal[size])='\0';
1935 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1936 heap_free(ptr);
1938 size=-4; break;
1939 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1940 case VT_DISPATCH :
1941 case VT_VARIANT :
1942 case VT_UNKNOWN :
1943 case VT_PTR :
1944 case VT_SAFEARRAY :
1945 case VT_CARRAY :
1946 case VT_USERDEFINED :
1947 case VT_LPSTR :
1948 case VT_LPWSTR :
1949 case VT_BLOB :
1950 case VT_STREAM :
1951 case VT_STORAGE :
1952 case VT_STREAMED_OBJECT :
1953 case VT_STORED_OBJECT :
1954 case VT_BLOB_OBJECT :
1955 case VT_CF :
1956 case VT_CLSID :
1957 default:
1958 size=0;
1959 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1960 V_VT(pVar));
1963 if(size>0) /* (big|small) endian correct? */
1964 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1965 return;
1968 * create a linked list with custom data
1970 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
1972 MSFT_CDGuid entry;
1973 TLBCustData* pNew;
1974 int count=0;
1976 TRACE_(typelib)("\n");
1978 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
1980 while(offset >=0){
1981 count++;
1982 pNew=heap_alloc_zero(sizeof(TLBCustData));
1983 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1984 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1985 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1986 list_add_head(custdata_list, &pNew->entry);
1987 offset = entry.next;
1989 return count;
1992 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1993 ITypeInfoImpl *pTI)
1995 if(type <0)
1996 pTd->vt=type & VT_TYPEMASK;
1997 else
1998 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2000 if(pTd->vt == VT_USERDEFINED)
2001 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
2003 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2006 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
2008 /* resolve referenced type if any */
2009 while (lpTypeDesc)
2011 switch (lpTypeDesc->vt)
2013 case VT_PTR:
2014 lpTypeDesc = lpTypeDesc->u.lptdesc;
2015 break;
2017 case VT_CARRAY:
2018 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
2019 break;
2021 case VT_USERDEFINED:
2022 MSFT_DoRefType(pcx, pTI->pTypeLib,
2023 lpTypeDesc->u.hreftype);
2025 lpTypeDesc = NULL;
2026 break;
2028 default:
2029 lpTypeDesc = NULL;
2034 static void
2035 MSFT_DoFuncs(TLBContext* pcx,
2036 ITypeInfoImpl* pTI,
2037 int cFuncs,
2038 int cVars,
2039 int offset,
2040 TLBFuncDesc** pptfd)
2043 * member information is stored in a data structure at offset
2044 * indicated by the memoffset field of the typeinfo structure
2045 * There are several distinctive parts.
2046 * The first part starts with a field that holds the total length
2047 * of this (first) part excluding this field. Then follow the records,
2048 * for each member there is one record.
2050 * The first entry is always the length of the record (including this
2051 * length word).
2052 * The rest of the record depends on the type of the member. If there is
2053 * a field indicating the member type (function, variable, interface, etc)
2054 * I have not found it yet. At this time we depend on the information
2055 * in the type info and the usual order how things are stored.
2057 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2058 * for each member;
2060 * Third is an equal sized array with file offsets to the name entry
2061 * of each member.
2063 * The fourth and last (?) part is an array with offsets to the records
2064 * in the first part of this file segment.
2067 int infolen, nameoffset, reclength, i;
2068 int recoffset = offset + sizeof(INT);
2070 char *recbuf = heap_alloc(0xffff);
2071 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2072 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2074 TRACE_(typelib)("\n");
2076 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2078 *pptfd = TLBFuncDesc_Constructor(cFuncs);
2079 ptfd = *pptfd;
2080 for ( i = 0; i < cFuncs ; i++ )
2082 int optional;
2084 /* name, eventually add to a hash table */
2085 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2086 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2088 /* nameoffset is sometimes -1 on the second half of a propget/propput
2089 * pair of functions */
2090 if ((nameoffset == -1) && (i > 0))
2091 ptfd->Name = SysAllocString(ptfd_prev->Name);
2092 else
2093 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2095 /* read the function information record */
2096 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2098 reclength &= 0xffff;
2100 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2102 /* size without argument data */
2103 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2105 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2106 ptfd->helpcontext = pFuncRec->HelpContext;
2108 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2109 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2111 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2113 if (pFuncRec->FKCCIC & 0x2000 )
2115 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2116 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2117 ptfd->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2119 else
2120 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2122 else
2123 ptfd->Entry = (BSTR)-1;
2125 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2126 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2128 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2129 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2131 /* fill the FuncDesc Structure */
2132 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2133 offset + infolen + ( i + 1) * sizeof(INT));
2135 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2136 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2137 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2138 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2139 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2140 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2141 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2143 MSFT_GetTdesc(pcx,
2144 pFuncRec->DataType,
2145 &ptfd->funcdesc.elemdescFunc.tdesc,
2146 pTI);
2147 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2149 /* do the parameters/arguments */
2150 if(pFuncRec->nrargs)
2152 int j = 0;
2153 MSFT_ParameterInfo paraminfo;
2155 ptfd->funcdesc.lprgelemdescParam =
2156 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2158 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2160 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2161 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2163 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2165 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2167 MSFT_GetTdesc(pcx,
2168 paraminfo.DataType,
2169 &elemdesc->tdesc,
2170 pTI);
2172 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2174 /* name */
2175 if (paraminfo.oName == -1)
2176 /* this occurs for [propput] or [propget] methods, so
2177 * we should just set the name of the parameter to the
2178 * name of the method. */
2179 ptfd->pParamDesc[j].Name = SysAllocString(ptfd->Name);
2180 else
2181 ptfd->pParamDesc[j].Name =
2182 MSFT_ReadName( pcx, paraminfo.oName );
2183 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(ptfd->pParamDesc[j].Name));
2185 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2187 /* default value */
2188 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2189 (pFuncRec->FKCCIC & 0x1000) )
2191 INT* pInt = (INT *)((char *)pFuncRec +
2192 reclength -
2193 (pFuncRec->nrargs * 4) * sizeof(INT) );
2195 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2197 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2198 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2200 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2201 pInt[j], pcx);
2203 else
2204 elemdesc->u.paramdesc.pparamdescex = NULL;
2206 /* custom info */
2207 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2208 j*sizeof(pFuncRec->oArgCustData[0])) &&
2209 pFuncRec->FKCCIC & 0x80 )
2211 MSFT_CustData(pcx,
2212 pFuncRec->oArgCustData[j],
2213 &ptfd->pParamDesc[j].custdata_list);
2216 /* SEEK value = jump to offset,
2217 * from there jump to the end of record,
2218 * go back by (j-1) arguments
2220 MSFT_ReadLEDWords( &paraminfo ,
2221 sizeof(MSFT_ParameterInfo), pcx,
2222 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2223 * sizeof(MSFT_ParameterInfo)));
2227 /* scode is not used: archaic win16 stuff FIXME: right? */
2228 ptfd->funcdesc.cScodes = 0 ;
2229 ptfd->funcdesc.lprgscode = NULL ;
2231 ptfd_prev = ptfd;
2232 ++ptfd;
2233 recoffset += reclength;
2235 heap_free(recbuf);
2238 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2239 int cVars, int offset, TLBVarDesc ** pptvd)
2241 int infolen, nameoffset, reclength;
2242 char recbuf[256];
2243 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2244 TLBVarDesc *ptvd;
2245 int i;
2246 int recoffset;
2248 TRACE_(typelib)("\n");
2250 ptvd = *pptvd = TLBVarDesc_Constructor(cVars);
2251 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2252 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2253 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2254 recoffset += offset+sizeof(INT);
2255 for(i=0;i<cVars;i++, ++ptvd){
2256 /* name, eventually add to a hash table */
2257 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2258 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2259 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2260 /* read the variable information record */
2261 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2262 reclength &= 0xff;
2263 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2265 /* optional data */
2266 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2267 ptvd->HelpContext = pVarRec->HelpContext;
2269 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2270 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2272 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2273 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2275 /* fill the VarDesc Structure */
2276 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2277 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2278 ptvd->vardesc.varkind = pVarRec->VarKind;
2279 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2280 MSFT_GetTdesc(pcx, pVarRec->DataType,
2281 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2282 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2283 if(pVarRec->VarKind == VAR_CONST ){
2284 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2285 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2286 pVarRec->OffsValue, pcx);
2287 } else
2288 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2289 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2290 recoffset += reclength;
2294 /* fill in data for a hreftype (offset). When the referenced type is contained
2295 * in the typelib, it's just an (file) offset in the type info base dir.
2296 * If comes from import, it's an offset+1 in the ImpInfo table
2297 * */
2298 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2299 int offset)
2301 TLBRefType *ref;
2303 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2305 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2307 if(ref->reference == offset) return;
2310 ref = heap_alloc_zero(sizeof(TLBRefType));
2311 list_add_tail(&pTL->ref_list, &ref->entry);
2313 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2314 /* external typelib */
2315 MSFT_ImpInfo impinfo;
2316 TLBImpLib *pImpLib;
2318 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2320 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2321 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2323 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2324 if(pImpLib->offset==impinfo.oImpFile)
2325 break;
2327 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2328 ref->reference = offset;
2329 ref->pImpTLInfo = pImpLib;
2330 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2331 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2332 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2333 ref->index = TLB_REF_USE_GUID;
2334 } else
2335 ref->index = impinfo.oGuid;
2336 }else{
2337 ERR("Cannot find a reference\n");
2338 ref->reference = -1;
2339 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2341 }else{
2342 /* in this typelib */
2343 ref->index = MSFT_HREFTYPE_INDEX(offset);
2344 ref->reference = offset;
2345 ref->pImpTLInfo = TLB_REF_INTERNAL;
2349 /* process Implemented Interfaces of a com class */
2350 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2351 int offset)
2353 int i;
2354 MSFT_RefRecord refrec;
2355 TLBImplType *pImpl;
2357 TRACE_(typelib)("\n");
2359 pTI->impltypes = TLBImplType_Constructor(count);
2360 pImpl = pTI->impltypes;
2361 for(i=0;i<count;i++){
2362 if(offset<0) break; /* paranoia */
2363 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2364 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2365 pImpl->hRef = refrec.reftype;
2366 pImpl->implflags=refrec.flags;
2367 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2368 offset=refrec.onext;
2369 ++pImpl;
2373 * process a typeinfo record
2375 static ITypeInfoImpl * MSFT_DoTypeInfo(
2376 TLBContext *pcx,
2377 int count,
2378 ITypeLibImpl * pLibInfo)
2380 MSFT_TypeInfoBase tiBase;
2381 ITypeInfoImpl *ptiRet;
2383 TRACE_(typelib)("count=%u\n", count);
2385 ptiRet = ITypeInfoImpl_Constructor();
2386 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2387 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2389 /* this is where we are coming from */
2390 ptiRet->pTypeLib = pLibInfo;
2391 ptiRet->index=count;
2392 /* fill in the typeattr fields */
2394 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2395 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2396 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2397 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2398 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2399 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2400 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2401 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2402 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2403 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2404 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2405 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2406 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2407 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2408 MSFT_GetTdesc(pcx, tiBase.datatype1,
2409 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2411 /* FIXME: */
2412 /* IDLDESC idldescType; *//* never saw this one != zero */
2414 /* name, eventually add to a hash table */
2415 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2416 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2417 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2418 /* help info */
2419 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2420 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2421 ptiRet->dwHelpContext=tiBase.helpcontext;
2423 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2424 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2426 /* note: InfoType's Help file and HelpStringDll come from the containing
2427 * library. Further HelpString and Docstring appear to be the same thing :(
2429 /* functions */
2430 if(ptiRet->TypeAttr.cFuncs >0 )
2431 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2432 ptiRet->TypeAttr.cVars,
2433 tiBase.memoffset, &ptiRet->funcdescs);
2434 /* variables */
2435 if(ptiRet->TypeAttr.cVars >0 )
2436 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2437 ptiRet->TypeAttr.cVars,
2438 tiBase.memoffset, &ptiRet->vardescs);
2439 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2440 switch(ptiRet->TypeAttr.typekind)
2442 case TKIND_COCLASS:
2443 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2444 tiBase.datatype1);
2445 break;
2446 case TKIND_DISPATCH:
2447 /* This is not -1 when the interface is a non-base dual interface or
2448 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2449 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2450 not this interface.
2453 if (tiBase.datatype1 != -1)
2455 ptiRet->impltypes = TLBImplType_Constructor(1);
2456 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2457 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2459 break;
2460 default:
2461 ptiRet->impltypes = TLBImplType_Constructor(1);
2462 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2463 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2464 break;
2467 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2469 TRACE_(typelib)("%s guid: %s kind:%s\n",
2470 debugstr_w(ptiRet->Name),
2471 debugstr_guid(&ptiRet->TypeAttr.guid),
2472 typekind_desc[ptiRet->TypeAttr.typekind]);
2473 if (TRACE_ON(typelib))
2474 dump_TypeInfo(ptiRet);
2476 return ptiRet;
2479 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2480 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2481 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2482 * tradeoff here.
2484 static struct list tlb_cache = LIST_INIT(tlb_cache);
2485 static CRITICAL_SECTION cache_section;
2486 static CRITICAL_SECTION_DEBUG cache_section_debug =
2488 0, 0, &cache_section,
2489 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2490 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2492 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2495 typedef struct TLB_PEFile
2497 IUnknown IUnknown_iface;
2498 LONG refs;
2499 HMODULE dll;
2500 HRSRC typelib_resource;
2501 HGLOBAL typelib_global;
2502 LPVOID typelib_base;
2503 } TLB_PEFile;
2505 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2507 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2510 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2512 if (IsEqualIID(riid, &IID_IUnknown))
2514 *ppv = iface;
2515 IUnknown_AddRef(iface);
2516 return S_OK;
2518 *ppv = NULL;
2519 return E_NOINTERFACE;
2522 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2524 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2525 return InterlockedIncrement(&This->refs);
2528 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2530 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2531 ULONG refs = InterlockedDecrement(&This->refs);
2532 if (!refs)
2534 if (This->typelib_global)
2535 FreeResource(This->typelib_global);
2536 if (This->dll)
2537 FreeLibrary(This->dll);
2538 heap_free(This);
2540 return refs;
2543 static const IUnknownVtbl TLB_PEFile_Vtable =
2545 TLB_PEFile_QueryInterface,
2546 TLB_PEFile_AddRef,
2547 TLB_PEFile_Release
2550 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2552 TLB_PEFile *This;
2553 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2555 This = heap_alloc(sizeof(TLB_PEFile));
2556 if (!This)
2557 return E_OUTOFMEMORY;
2559 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2560 This->refs = 1;
2561 This->dll = NULL;
2562 This->typelib_resource = NULL;
2563 This->typelib_global = NULL;
2564 This->typelib_base = NULL;
2566 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2567 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2569 if (This->dll)
2571 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2572 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2573 if (This->typelib_resource)
2575 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2576 if (This->typelib_global)
2578 This->typelib_base = LockResource(This->typelib_global);
2580 if (This->typelib_base)
2582 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2583 *ppBase = This->typelib_base;
2584 *ppFile = &This->IUnknown_iface;
2585 return S_OK;
2590 TRACE("No TYPELIB resource found\n");
2591 hr = E_FAIL;
2594 TLB_PEFile_Release(&This->IUnknown_iface);
2595 return hr;
2598 typedef struct TLB_NEFile
2600 IUnknown IUnknown_iface;
2601 LONG refs;
2602 LPVOID typelib_base;
2603 } TLB_NEFile;
2605 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2607 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2610 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2612 if (IsEqualIID(riid, &IID_IUnknown))
2614 *ppv = iface;
2615 IUnknown_AddRef(iface);
2616 return S_OK;
2618 *ppv = NULL;
2619 return E_NOINTERFACE;
2622 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2624 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2625 return InterlockedIncrement(&This->refs);
2628 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2630 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2631 ULONG refs = InterlockedDecrement(&This->refs);
2632 if (!refs)
2634 heap_free(This->typelib_base);
2635 heap_free(This);
2637 return refs;
2640 static const IUnknownVtbl TLB_NEFile_Vtable =
2642 TLB_NEFile_QueryInterface,
2643 TLB_NEFile_AddRef,
2644 TLB_NEFile_Release
2647 /***********************************************************************
2648 * read_xx_header [internal]
2650 static int read_xx_header( HFILE lzfd )
2652 IMAGE_DOS_HEADER mzh;
2653 char magic[3];
2655 LZSeek( lzfd, 0, SEEK_SET );
2656 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2657 return 0;
2658 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2659 return 0;
2661 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2662 if ( 2 != LZRead( lzfd, magic, 2 ) )
2663 return 0;
2665 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2667 if ( magic[0] == 'N' && magic[1] == 'E' )
2668 return IMAGE_OS2_SIGNATURE;
2669 if ( magic[0] == 'P' && magic[1] == 'E' )
2670 return IMAGE_NT_SIGNATURE;
2672 magic[2] = '\0';
2673 WARN("Can't handle %s files.\n", magic );
2674 return 0;
2678 /***********************************************************************
2679 * find_ne_resource [internal]
2681 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2682 DWORD *resLen, DWORD *resOff )
2684 IMAGE_OS2_HEADER nehd;
2685 NE_TYPEINFO *typeInfo;
2686 NE_NAMEINFO *nameInfo;
2687 DWORD nehdoffset;
2688 LPBYTE resTab;
2689 DWORD resTabSize;
2690 int count;
2692 /* Read in NE header */
2693 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2694 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2696 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2697 if ( !resTabSize )
2699 TRACE("No resources in NE dll\n" );
2700 return FALSE;
2703 /* Read in resource table */
2704 resTab = heap_alloc( resTabSize );
2705 if ( !resTab ) return FALSE;
2707 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2708 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2710 heap_free( resTab );
2711 return FALSE;
2714 /* Find resource */
2715 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2717 if (!IS_INTRESOURCE(typeid)) /* named type */
2719 BYTE len = strlen( typeid );
2720 while (typeInfo->type_id)
2722 if (!(typeInfo->type_id & 0x8000))
2724 BYTE *p = resTab + typeInfo->type_id;
2725 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2727 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2728 typeInfo->count * sizeof(NE_NAMEINFO));
2731 else /* numeric type id */
2733 WORD id = LOWORD(typeid) | 0x8000;
2734 while (typeInfo->type_id)
2736 if (typeInfo->type_id == id) goto found_type;
2737 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2738 typeInfo->count * sizeof(NE_NAMEINFO));
2741 TRACE("No typeid entry found for %p\n", typeid );
2742 heap_free( resTab );
2743 return FALSE;
2745 found_type:
2746 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2748 if (!IS_INTRESOURCE(resid)) /* named resource */
2750 BYTE len = strlen( resid );
2751 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2753 BYTE *p = resTab + nameInfo->id;
2754 if (nameInfo->id & 0x8000) continue;
2755 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2758 else /* numeric resource id */
2760 WORD id = LOWORD(resid) | 0x8000;
2761 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2762 if (nameInfo->id == id) goto found_name;
2764 TRACE("No resid entry found for %p\n", typeid );
2765 heap_free( resTab );
2766 return FALSE;
2768 found_name:
2769 /* Return resource data */
2770 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2771 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2773 heap_free( resTab );
2774 return TRUE;
2777 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2779 HFILE lzfd = -1;
2780 OFSTRUCT ofs;
2781 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2782 TLB_NEFile *This;
2784 This = heap_alloc(sizeof(TLB_NEFile));
2785 if (!This) return E_OUTOFMEMORY;
2787 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
2788 This->refs = 1;
2789 This->typelib_base = NULL;
2791 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2792 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2794 DWORD reslen, offset;
2795 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2797 This->typelib_base = heap_alloc(reslen);
2798 if( !This->typelib_base )
2799 hr = E_OUTOFMEMORY;
2800 else
2802 LZSeek( lzfd, offset, SEEK_SET );
2803 reslen = LZRead( lzfd, This->typelib_base, reslen );
2804 LZClose( lzfd );
2805 *ppBase = This->typelib_base;
2806 *pdwTLBLength = reslen;
2807 *ppFile = &This->IUnknown_iface;
2808 return S_OK;
2813 if( lzfd >= 0) LZClose( lzfd );
2814 TLB_NEFile_Release(&This->IUnknown_iface);
2815 return hr;
2818 typedef struct TLB_Mapping
2820 IUnknown IUnknown_iface;
2821 LONG refs;
2822 HANDLE file;
2823 HANDLE mapping;
2824 LPVOID typelib_base;
2825 } TLB_Mapping;
2827 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
2829 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
2832 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2834 if (IsEqualIID(riid, &IID_IUnknown))
2836 *ppv = iface;
2837 IUnknown_AddRef(iface);
2838 return S_OK;
2840 *ppv = NULL;
2841 return E_NOINTERFACE;
2844 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2846 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
2847 return InterlockedIncrement(&This->refs);
2850 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2852 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
2853 ULONG refs = InterlockedDecrement(&This->refs);
2854 if (!refs)
2856 if (This->typelib_base)
2857 UnmapViewOfFile(This->typelib_base);
2858 if (This->mapping)
2859 CloseHandle(This->mapping);
2860 if (This->file != INVALID_HANDLE_VALUE)
2861 CloseHandle(This->file);
2862 heap_free(This);
2864 return refs;
2867 static const IUnknownVtbl TLB_Mapping_Vtable =
2869 TLB_Mapping_QueryInterface,
2870 TLB_Mapping_AddRef,
2871 TLB_Mapping_Release
2874 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2876 TLB_Mapping *This;
2878 This = heap_alloc(sizeof(TLB_Mapping));
2879 if (!This)
2880 return E_OUTOFMEMORY;
2882 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
2883 This->refs = 1;
2884 This->file = INVALID_HANDLE_VALUE;
2885 This->mapping = NULL;
2886 This->typelib_base = NULL;
2888 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2889 if (INVALID_HANDLE_VALUE != This->file)
2891 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2892 if (This->mapping)
2894 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2895 if(This->typelib_base)
2897 /* retrieve file size */
2898 *pdwTLBLength = GetFileSize(This->file, NULL);
2899 *ppBase = This->typelib_base;
2900 *ppFile = &This->IUnknown_iface;
2901 return S_OK;
2906 IUnknown_Release(&This->IUnknown_iface);
2907 return TYPE_E_CANTLOADLIBRARY;
2910 /****************************************************************************
2911 * TLB_ReadTypeLib
2913 * find the type of the typelib file and map the typelib resource into
2914 * the memory
2917 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2918 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2920 ITypeLibImpl *entry;
2921 HRESULT ret;
2922 INT index = 1;
2923 LPWSTR index_str, file = (LPWSTR)pszFileName;
2924 LPVOID pBase = NULL;
2925 DWORD dwTLBLength = 0;
2926 IUnknown *pFile = NULL;
2928 *ppTypeLib = NULL;
2930 index_str = strrchrW(pszFileName, '\\');
2931 if(index_str && *++index_str != '\0')
2933 LPWSTR end_ptr;
2934 LONG idx = strtolW(index_str, &end_ptr, 10);
2935 if(*end_ptr == '\0')
2937 int str_len = index_str - pszFileName - 1;
2938 index = idx;
2939 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2940 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2941 file[str_len] = 0;
2945 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2947 if(strchrW(file, '\\'))
2949 lstrcpyW(pszPath, file);
2951 else
2953 int len = GetSystemDirectoryW(pszPath, cchPath);
2954 pszPath[len] = '\\';
2955 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2959 if(file != pszFileName) heap_free(file);
2961 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2963 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2964 EnterCriticalSection(&cache_section);
2965 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
2967 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2969 TRACE("cache hit\n");
2970 *ppTypeLib = &entry->ITypeLib2_iface;
2971 ITypeLib2_AddRef(*ppTypeLib);
2972 LeaveCriticalSection(&cache_section);
2973 return S_OK;
2976 LeaveCriticalSection(&cache_section);
2978 /* now actually load and parse the typelib */
2980 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2981 if (ret == TYPE_E_CANTLOADLIBRARY)
2982 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2983 if (ret == TYPE_E_CANTLOADLIBRARY)
2984 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2985 if (SUCCEEDED(ret))
2987 if (dwTLBLength >= 4)
2989 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2990 if (dwSignature == MSFT_SIGNATURE)
2991 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2992 else if (dwSignature == SLTG_SIGNATURE)
2993 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2994 else
2996 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2997 ret = TYPE_E_CANTLOADLIBRARY;
3000 else
3001 ret = TYPE_E_CANTLOADLIBRARY;
3002 IUnknown_Release(pFile);
3005 if(*ppTypeLib) {
3006 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3008 TRACE("adding to cache\n");
3009 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3010 lstrcpyW(impl->path, pszPath);
3011 /* We should really canonicalise the path here. */
3012 impl->index = index;
3014 /* FIXME: check if it has added already in the meantime */
3015 EnterCriticalSection(&cache_section);
3016 list_add_head(&tlb_cache, &impl->entry);
3017 LeaveCriticalSection(&cache_section);
3018 ret = S_OK;
3020 else
3022 if(ret != E_FAIL)
3023 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3025 ret = TYPE_E_CANTLOADLIBRARY;
3029 return ret;
3032 /*================== ITypeLib(2) Methods ===================================*/
3034 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3036 ITypeLibImpl* pTypeLibImpl;
3038 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3039 if (!pTypeLibImpl) return NULL;
3041 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3042 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3043 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3044 pTypeLibImpl->ref = 1;
3046 list_init(&pTypeLibImpl->implib_list);
3047 list_init(&pTypeLibImpl->custdata_list);
3048 list_init(&pTypeLibImpl->ref_list);
3049 pTypeLibImpl->dispatch_href = -1;
3051 return pTypeLibImpl;
3054 /****************************************************************************
3055 * ITypeLib2_Constructor_MSFT
3057 * loading an MSFT typelib from an in-memory image
3059 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3061 TLBContext cx;
3062 LONG lPSegDir;
3063 MSFT_Header tlbHeader;
3064 MSFT_SegDir tlbSegDir;
3065 ITypeLibImpl * pTypeLibImpl;
3067 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3069 pTypeLibImpl = TypeLibImpl_Constructor();
3070 if (!pTypeLibImpl) return NULL;
3072 /* get pointer to beginning of typelib data */
3073 cx.pos = 0;
3074 cx.oStart=0;
3075 cx.mapping = pLib;
3076 cx.pLibInfo = pTypeLibImpl;
3077 cx.length = dwTLBLength;
3079 /* read header */
3080 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3081 TRACE_(typelib)("header:\n");
3082 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3083 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3084 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3085 return NULL;
3087 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3089 /* there is a small amount of information here until the next important
3090 * part:
3091 * the segment directory . Try to calculate the amount of data */
3092 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3094 /* now read the segment directory */
3095 TRACE("read segment directory (at %d)\n",lPSegDir);
3096 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3097 cx.pTblDir = &tlbSegDir;
3099 /* just check two entries */
3100 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3102 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3103 heap_free(pTypeLibImpl);
3104 return NULL;
3107 /* now fill our internal data */
3108 /* TLIBATTR fields */
3109 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
3111 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
3112 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3113 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
3114 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
3115 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3117 pTypeLibImpl->lcid = tlbHeader.lcid;
3119 /* name, eventually add to a hash table */
3120 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3122 /* help info */
3123 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3124 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3126 if( tlbHeader.varflags & HELPDLLFLAG)
3128 int offset;
3129 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3130 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3133 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3135 /* custom data */
3136 if(tlbHeader.CustomDataOffset >= 0)
3138 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3141 /* fill in type descriptions */
3142 if(tlbSegDir.pTypdescTab.length > 0)
3144 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3145 INT16 td[4];
3146 pTypeLibImpl->ctTypeDesc = cTD;
3147 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3148 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3149 for(i=0; i<cTD; )
3151 /* FIXME: add several sanity checks here */
3152 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3153 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3155 /* FIXME: check safearray */
3156 if(td[3] < 0)
3157 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3158 else
3159 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3161 else if(td[0] == VT_CARRAY)
3163 /* array descr table here */
3164 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3166 else if(td[0] == VT_USERDEFINED)
3168 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3170 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3173 /* second time around to fill the array subscript info */
3174 for(i=0;i<cTD;i++)
3176 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3177 if(tlbSegDir.pArrayDescriptions.offset>0)
3179 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3180 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3182 if(td[1]<0)
3183 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3184 else
3185 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3187 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3189 for(j = 0; j<td[2]; j++)
3191 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3192 sizeof(INT), &cx, DO_NOT_SEEK);
3193 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3194 sizeof(INT), &cx, DO_NOT_SEEK);
3197 else
3199 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3200 ERR("didn't find array description data\n");
3205 /* imported type libs */
3206 if(tlbSegDir.pImpFiles.offset>0)
3208 TLBImpLib *pImpLib;
3209 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3210 UINT16 size;
3212 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3214 char *name;
3216 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3217 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3218 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3220 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3221 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3222 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3223 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3225 size >>= 2;
3226 name = heap_alloc_zero(size+1);
3227 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3228 pImpLib->name = TLB_MultiByteToBSTR(name);
3229 heap_free(name);
3231 MSFT_ReadGuid(&pImpLib->guid, oGuid, &cx);
3232 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3234 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3238 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3239 if(pTypeLibImpl->dispatch_href != -1)
3240 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3242 /* type infos */
3243 if(tlbHeader.nrtypeinfos >= 0 )
3245 ITypeInfoImpl **ppTI;
3246 int i;
3248 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3250 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3252 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3254 ++ppTI;
3255 (pTypeLibImpl->TypeInfoCount)++;
3259 TRACE("(%p)\n", pTypeLibImpl);
3260 return &pTypeLibImpl->ITypeLib2_iface;
3264 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3266 char b[3];
3267 int i;
3268 short s;
3270 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3271 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3272 return FALSE;
3275 guid->Data4[0] = s >> 8;
3276 guid->Data4[1] = s & 0xff;
3278 b[2] = '\0';
3279 for(i = 0; i < 6; i++) {
3280 memcpy(b, str + 24 + 2 * i, 2);
3281 guid->Data4[i + 2] = strtol(b, NULL, 16);
3283 return TRUE;
3286 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3288 WORD bytelen;
3289 DWORD len;
3291 *pBstr = NULL;
3292 bytelen = *(const WORD*)ptr;
3293 if(bytelen == 0xffff) return 2;
3294 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3295 *pBstr = SysAllocStringLen(NULL, len);
3296 if (*pBstr)
3297 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3298 return bytelen + 2;
3301 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3303 WORD bytelen;
3305 *str = NULL;
3306 bytelen = *(const WORD*)ptr;
3307 if(bytelen == 0xffff) return 2;
3308 *str = heap_alloc(bytelen + 1);
3309 memcpy(*str, ptr + 2, bytelen);
3310 (*str)[bytelen] = '\0';
3311 return bytelen + 2;
3314 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3316 char *ptr = pLibBlk;
3317 WORD w;
3319 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3320 FIXME("libblk magic = %04x\n", w);
3321 return 0;
3324 ptr += 6;
3325 if((w = *(WORD*)ptr) != 0xffff) {
3326 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3327 ptr += w;
3329 ptr += 2;
3331 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3333 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3335 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3336 ptr += 4;
3338 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3339 ptr += 2;
3341 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3342 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3343 else
3344 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3345 ptr += 2;
3347 ptr += 4; /* skip res12 */
3349 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3350 ptr += 2;
3352 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3353 ptr += 2;
3355 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3356 ptr += 2;
3358 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3359 ptr += sizeof(GUID);
3361 return ptr - (char*)pLibBlk;
3364 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3365 typedef struct
3367 unsigned int num;
3368 HREFTYPE refs[1];
3369 } sltg_ref_lookup_t;
3371 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3372 HREFTYPE *typelib_ref)
3374 if(table && typeinfo_ref < table->num)
3376 *typelib_ref = table->refs[typeinfo_ref];
3377 return S_OK;
3380 ERR_(typelib)("Unable to find reference\n");
3381 *typelib_ref = -1;
3382 return E_FAIL;
3385 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3387 BOOL done = FALSE;
3389 while(!done) {
3390 if((*pType & 0xe00) == 0xe00) {
3391 pTD->vt = VT_PTR;
3392 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3393 pTD = pTD->u.lptdesc;
3395 switch(*pType & 0x3f) {
3396 case VT_PTR:
3397 pTD->vt = VT_PTR;
3398 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3399 pTD = pTD->u.lptdesc;
3400 break;
3402 case VT_USERDEFINED:
3403 pTD->vt = VT_USERDEFINED;
3404 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3405 done = TRUE;
3406 break;
3408 case VT_CARRAY:
3410 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3411 array */
3413 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3415 pTD->vt = VT_CARRAY;
3416 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3417 pTD->u.lpadesc->cDims = pSA->cDims;
3418 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3419 pSA->cDims * sizeof(SAFEARRAYBOUND));
3421 pTD = &pTD->u.lpadesc->tdescElem;
3422 break;
3425 case VT_SAFEARRAY:
3427 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3428 useful? */
3430 pType++;
3431 pTD->vt = VT_SAFEARRAY;
3432 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3433 pTD = pTD->u.lptdesc;
3434 break;
3436 default:
3437 pTD->vt = *pType & 0x3f;
3438 done = TRUE;
3439 break;
3441 pType++;
3443 return pType;
3446 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3447 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3449 /* Handle [in/out] first */
3450 if((*pType & 0xc000) == 0xc000)
3451 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3452 else if(*pType & 0x8000)
3453 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3454 else if(*pType & 0x4000)
3455 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3456 else
3457 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3459 if(*pType & 0x2000)
3460 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3462 if(*pType & 0x80)
3463 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3465 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3469 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3470 char *pNameTable)
3472 unsigned int ref;
3473 char *name;
3474 TLBRefType *ref_type;
3475 sltg_ref_lookup_t *table;
3476 HREFTYPE typelib_ref;
3478 if(pRef->magic != SLTG_REF_MAGIC) {
3479 FIXME("Ref magic = %x\n", pRef->magic);
3480 return NULL;
3482 name = ( (char*)pRef->names + pRef->number);
3484 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3485 table->num = pRef->number >> 3;
3487 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3489 /* We don't want the first href to be 0 */
3490 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3492 for(ref = 0; ref < pRef->number >> 3; ref++) {
3493 char *refname;
3494 unsigned int lib_offs, type_num;
3496 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3498 name += SLTG_ReadStringA(name, &refname);
3499 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3500 FIXME_(typelib)("Can't sscanf ref\n");
3501 if(lib_offs != 0xffff) {
3502 TLBImpLib *import;
3504 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3505 if(import->offset == lib_offs)
3506 break;
3508 if(&import->entry == &pTL->implib_list) {
3509 char fname[MAX_PATH+1];
3510 int len;
3512 import = heap_alloc_zero(sizeof(*import));
3513 import->offset = lib_offs;
3514 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3515 &import->guid);
3516 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3517 &import->wVersionMajor,
3518 &import->wVersionMinor,
3519 &import->lcid, fname) != 4) {
3520 FIXME_(typelib)("can't sscanf ref %s\n",
3521 pNameTable + lib_offs + 40);
3523 len = strlen(fname);
3524 if(fname[len-1] != '#')
3525 FIXME("fname = %s\n", fname);
3526 fname[len-1] = '\0';
3527 import->name = TLB_MultiByteToBSTR(fname);
3528 list_add_tail(&pTL->implib_list, &import->entry);
3530 ref_type->pImpTLInfo = import;
3532 /* Store a reference to IDispatch */
3533 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid, &IID_StdOle) && type_num == 4)
3534 pTL->dispatch_href = typelib_ref;
3536 } else { /* internal ref */
3537 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3539 ref_type->reference = typelib_ref;
3540 ref_type->index = type_num;
3542 heap_free(refname);
3543 list_add_tail(&pTL->ref_list, &ref_type->entry);
3545 table->refs[ref] = typelib_ref;
3546 typelib_ref += 4;
3548 if((BYTE)*name != SLTG_REF_MAGIC)
3549 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3550 dump_TLBRefType(pTL);
3551 return table;
3554 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3555 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3557 SLTG_ImplInfo *info;
3558 TLBImplType *pImplType;
3559 /* I don't really get this structure, usually it's 0x16 bytes
3560 long, but iuser.tlb contains some that are 0x18 bytes long.
3561 That's ok because we can use the next ptr to jump to the next
3562 one. But how do we know the length of the last one? The WORD
3563 at offs 0x8 might be the clue. For now I'm just assuming that
3564 the last one is the regular 0x16 bytes. */
3566 info = (SLTG_ImplInfo*)pBlk;
3567 while(1){
3568 pTI->TypeAttr.cImplTypes++;
3569 if(info->next == 0xffff)
3570 break;
3571 info = (SLTG_ImplInfo*)(pBlk + info->next);
3574 info = (SLTG_ImplInfo*)pBlk;
3575 pTI->impltypes = TLBImplType_Constructor(pTI->TypeAttr.cImplTypes);
3576 pImplType = pTI->impltypes;
3577 while(1) {
3578 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3579 pImplType->implflags = info->impltypeflags;
3580 ++pImplType;
3582 if(info->next == 0xffff)
3583 break;
3584 if(OneOnly)
3585 FIXME_(typelib)("Interface inheriting more than one interface\n");
3586 info = (SLTG_ImplInfo*)(pBlk + info->next);
3588 info++; /* see comment at top of function */
3589 return (char*)info;
3592 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3593 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3595 TLBVarDesc *pVarDesc;
3596 BSTR bstrPrevName = NULL;
3597 SLTG_Variable *pItem;
3598 unsigned short i;
3599 WORD *pType;
3601 pVarDesc = pTI->vardescs = TLBVarDesc_Constructor(cVars);
3603 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3604 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3606 pVarDesc->vardesc.memid = pItem->memid;
3608 if (pItem->magic != SLTG_VAR_MAGIC &&
3609 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3610 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3611 return;
3614 if (pItem->name == 0xfffe)
3615 pVarDesc->Name = SysAllocString(bstrPrevName);
3616 else
3617 pVarDesc->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3619 TRACE_(typelib)("name: %s\n", debugstr_w(pVarDesc->Name));
3620 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3621 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3623 if(pItem->flags & 0x02)
3624 pType = &pItem->type;
3625 else
3626 pType = (WORD*)(pBlk + pItem->type);
3628 if (pItem->flags & ~0xda)
3629 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3631 SLTG_DoElem(pType, pBlk,
3632 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3634 if (TRACE_ON(typelib)) {
3635 char buf[300];
3636 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3637 TRACE_(typelib)("elemdescVar: %s\n", buf);
3640 if (pItem->flags & 0x40) {
3641 TRACE_(typelib)("VAR_DISPATCH\n");
3642 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3644 else if (pItem->flags & 0x10) {
3645 TRACE_(typelib)("VAR_CONST\n");
3646 pVarDesc->vardesc.varkind = VAR_CONST;
3647 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3648 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3649 if (pItem->flags & 0x08)
3650 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3651 else {
3652 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3654 case VT_LPSTR:
3655 case VT_LPWSTR:
3656 case VT_BSTR:
3658 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3659 BSTR str;
3660 TRACE_(typelib)("len = %u\n", len);
3661 if (len == 0xffff) {
3662 str = NULL;
3663 } else {
3664 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3665 str = SysAllocStringLen(NULL, alloc_len);
3666 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3668 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3669 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3670 break;
3672 case VT_I2:
3673 case VT_UI2:
3674 case VT_I4:
3675 case VT_UI4:
3676 case VT_INT:
3677 case VT_UINT:
3678 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3679 *(INT*)(pBlk + pItem->byte_offs);
3680 break;
3681 default:
3682 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3686 else {
3687 TRACE_(typelib)("VAR_PERINSTANCE\n");
3688 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3689 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3692 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3693 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3695 if (pItem->flags & 0x80)
3696 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3698 bstrPrevName = pVarDesc->Name;
3700 pTI->TypeAttr.cVars = cVars;
3703 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3704 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3706 SLTG_Function *pFunc;
3707 unsigned short i;
3708 TLBFuncDesc *pFuncDesc;
3710 pTI->funcdescs = TLBFuncDesc_Constructor(cFuncs);
3712 pFuncDesc = pTI->funcdescs;
3713 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3714 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3716 int param;
3717 WORD *pType, *pArg;
3719 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3720 case SLTG_FUNCTION_MAGIC:
3721 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3722 break;
3723 case SLTG_DISPATCH_FUNCTION_MAGIC:
3724 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3725 break;
3726 case SLTG_STATIC_FUNCTION_MAGIC:
3727 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
3728 break;
3729 default:
3730 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3731 continue;
3733 pFuncDesc->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3735 pFuncDesc->funcdesc.memid = pFunc->dispid;
3736 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
3737 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
3738 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
3739 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3740 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
3742 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3743 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
3745 if(pFunc->retnextopt & 0x80)
3746 pType = &pFunc->rettype;
3747 else
3748 pType = (WORD*)(pBlk + pFunc->rettype);
3750 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
3752 pFuncDesc->funcdesc.lprgelemdescParam =
3753 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
3754 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
3756 pArg = (WORD*)(pBlk + pFunc->arg_off);
3758 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
3759 char *paramName = pNameTable + *pArg;
3760 BOOL HaveOffs;
3761 /* If arg type follows then paramName points to the 2nd
3762 letter of the name, else the next WORD is an offset to
3763 the arg type and paramName points to the first letter.
3764 So let's take one char off paramName and see if we're
3765 pointing at an alpha-numeric char. However if *pArg is
3766 0xffff or 0xfffe then the param has no name, the former
3767 meaning that the next WORD is the type, the latter
3768 meaning that the next WORD is an offset to the type. */
3770 HaveOffs = FALSE;
3771 if(*pArg == 0xffff)
3772 paramName = NULL;
3773 else if(*pArg == 0xfffe) {
3774 paramName = NULL;
3775 HaveOffs = TRUE;
3777 else if(paramName[-1] && !isalnum(paramName[-1]))
3778 HaveOffs = TRUE;
3780 pArg++;
3782 if(HaveOffs) { /* the next word is an offset to type */
3783 pType = (WORD*)(pBlk + *pArg);
3784 SLTG_DoElem(pType, pBlk,
3785 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3786 pArg++;
3787 } else {
3788 if(paramName)
3789 paramName--;
3790 pArg = SLTG_DoElem(pArg, pBlk,
3791 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3794 /* Are we an optional param ? */
3795 if(pFuncDesc->funcdesc.cParams - param <=
3796 pFuncDesc->funcdesc.cParamsOpt)
3797 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3799 if(paramName) {
3800 pFuncDesc->pParamDesc[param].Name =
3801 TLB_MultiByteToBSTR(paramName);
3802 } else {
3803 pFuncDesc->pParamDesc[param].Name =
3804 SysAllocString(pFuncDesc->Name);
3808 pTI->TypeAttr.cFuncs = cFuncs;
3811 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3812 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3813 SLTG_TypeInfoTail *pTITail)
3815 char *pFirstItem;
3816 sltg_ref_lookup_t *ref_lookup = NULL;
3818 if(pTIHeader->href_table != 0xffffffff) {
3819 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3820 pNameTable);
3823 pFirstItem = pBlk;
3825 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3826 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3828 heap_free(ref_lookup);
3832 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3833 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3834 const SLTG_TypeInfoTail *pTITail)
3836 char *pFirstItem;
3837 sltg_ref_lookup_t *ref_lookup = NULL;
3839 if(pTIHeader->href_table != 0xffffffff) {
3840 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3841 pNameTable);
3844 pFirstItem = pBlk;
3846 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3847 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3850 if (pTITail->funcs_off != 0xffff)
3851 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3853 heap_free(ref_lookup);
3855 if (TRACE_ON(typelib))
3856 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3859 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3860 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3861 const SLTG_TypeInfoTail *pTITail)
3863 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3866 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3867 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3868 const SLTG_TypeInfoTail *pTITail)
3870 WORD *pType;
3871 sltg_ref_lookup_t *ref_lookup = NULL;
3873 if (pTITail->simple_alias) {
3874 /* if simple alias, no more processing required */
3875 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3876 return;
3879 if(pTIHeader->href_table != 0xffffffff) {
3880 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3881 pNameTable);
3884 /* otherwise it is an offset to a type */
3885 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3887 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3889 heap_free(ref_lookup);
3892 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3893 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3894 const SLTG_TypeInfoTail *pTITail)
3896 sltg_ref_lookup_t *ref_lookup = NULL;
3897 if (pTIHeader->href_table != 0xffffffff)
3898 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3899 pNameTable);
3901 if (pTITail->vars_off != 0xffff)
3902 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3904 if (pTITail->funcs_off != 0xffff)
3905 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3907 if (pTITail->impls_off != 0xffff)
3908 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3910 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3911 * of dispinterface functions including the IDispatch ones, so
3912 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3913 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3915 heap_free(ref_lookup);
3916 if (TRACE_ON(typelib))
3917 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3920 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3921 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3922 const SLTG_TypeInfoTail *pTITail)
3924 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3927 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3928 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3929 const SLTG_TypeInfoTail *pTITail)
3931 sltg_ref_lookup_t *ref_lookup = NULL;
3932 if (pTIHeader->href_table != 0xffffffff)
3933 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3934 pNameTable);
3936 if (pTITail->vars_off != 0xffff)
3937 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3939 if (pTITail->funcs_off != 0xffff)
3940 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3941 heap_free(ref_lookup);
3942 if (TRACE_ON(typelib))
3943 dump_TypeInfo(pTI);
3946 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3947 manageable copy of it into this */
3948 typedef struct {
3949 WORD small_no;
3950 char *index_name;
3951 char *other_name;
3952 WORD res1a;
3953 WORD name_offs;
3954 WORD more_bytes;
3955 char *extra;
3956 WORD res20;
3957 DWORD helpcontext;
3958 WORD res26;
3959 GUID uuid;
3960 } SLTG_InternalOtherTypeInfo;
3962 /****************************************************************************
3963 * ITypeLib2_Constructor_SLTG
3965 * loading a SLTG typelib from an in-memory image
3967 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3969 ITypeLibImpl *pTypeLibImpl;
3970 SLTG_Header *pHeader;
3971 SLTG_BlkEntry *pBlkEntry;
3972 SLTG_Magic *pMagic;
3973 SLTG_Index *pIndex;
3974 SLTG_Pad9 *pPad9;
3975 LPVOID pBlk, pFirstBlk;
3976 SLTG_LibBlk *pLibBlk;
3977 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3978 char *pAfterOTIBlks = NULL;
3979 char *pNameTable, *ptr;
3980 int i;
3981 DWORD len, order;
3982 ITypeInfoImpl **ppTypeInfoImpl;
3984 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3987 pTypeLibImpl = TypeLibImpl_Constructor();
3988 if (!pTypeLibImpl) return NULL;
3990 pHeader = pLib;
3992 TRACE_(typelib)("header:\n");
3993 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3994 pHeader->nrOfFileBlks );
3995 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3996 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3997 pHeader->SLTG_magic);
3998 return NULL;
4001 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4002 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4004 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4005 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4007 /* Next we have a magic block */
4008 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4010 /* Let's see if we're still in sync */
4011 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4012 sizeof(SLTG_COMPOBJ_MAGIC))) {
4013 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4014 return NULL;
4016 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4017 sizeof(SLTG_DIR_MAGIC))) {
4018 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4019 return NULL;
4022 pIndex = (SLTG_Index*)(pMagic+1);
4024 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4026 pFirstBlk = pPad9 + 1;
4028 /* We'll set up a ptr to the main library block, which is the last one. */
4030 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4031 pBlkEntry[order].next != 0;
4032 order = pBlkEntry[order].next - 1, i++) {
4033 pBlk = (char*)pBlk + pBlkEntry[order].len;
4035 pLibBlk = pBlk;
4037 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4039 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4040 interspersed */
4042 len += 0x40;
4044 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4046 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4049 ptr = (char*)pLibBlk + len;
4051 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4052 WORD w, extra;
4053 len = 0;
4055 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4057 w = *(WORD*)(ptr + 2);
4058 if(w != 0xffff) {
4059 len += w;
4060 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4061 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4062 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4064 w = *(WORD*)(ptr + 4 + len);
4065 if(w != 0xffff) {
4066 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4067 len += w;
4068 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4069 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4070 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4072 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4073 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4074 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4075 if(extra) {
4076 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4077 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4078 len += extra;
4080 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4081 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4082 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4083 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4084 len += sizeof(SLTG_OtherTypeInfo);
4085 ptr += len;
4088 pAfterOTIBlks = ptr;
4090 /* Skip this WORD and get the next DWORD */
4091 len = *(DWORD*)(pAfterOTIBlks + 2);
4093 /* Now add this to pLibBLk look at what we're pointing at and
4094 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4095 dust and we should be pointing at the beginning of the name
4096 table */
4098 pNameTable = (char*)pLibBlk + len;
4100 switch(*(WORD*)pNameTable) {
4101 case 0xffff:
4102 break;
4103 case 0x0200:
4104 pNameTable += 0x20;
4105 break;
4106 default:
4107 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4108 break;
4111 pNameTable += 0x216;
4113 pNameTable += 2;
4115 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4117 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
4120 /* Hopefully we now have enough ptrs set up to actually read in
4121 some TypeInfos. It's not clear which order to do them in, so
4122 I'll just follow the links along the BlkEntry chain and read
4123 them in the order in which they are in the file */
4125 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4126 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4128 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4129 pBlkEntry[order].next != 0;
4130 order = pBlkEntry[order].next - 1, i++) {
4132 SLTG_TypeInfoHeader *pTIHeader;
4133 SLTG_TypeInfoTail *pTITail;
4134 SLTG_MemberHeader *pMemHeader;
4136 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4137 FIXME_(typelib)("Index strings don't match\n");
4138 heap_free(pOtherTypeInfoBlks);
4139 return NULL;
4142 pTIHeader = pBlk;
4143 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4144 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4145 heap_free(pOtherTypeInfoBlks);
4146 return NULL;
4148 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4149 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4150 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4152 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4153 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4154 (*ppTypeInfoImpl)->index = i;
4155 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
4156 pOtherTypeInfoBlks[i].name_offs +
4157 pNameTable);
4158 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4159 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
4160 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
4161 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
4162 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
4163 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
4164 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4166 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4167 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4169 if((pTIHeader->typeflags1 & 7) != 2)
4170 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4171 if(pTIHeader->typeflags3 != 2)
4172 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4174 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4175 debugstr_w((*ppTypeInfoImpl)->Name),
4176 typekind_desc[pTIHeader->typekind],
4177 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4178 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4180 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4182 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4184 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4185 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4186 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4188 switch(pTIHeader->typekind) {
4189 case TKIND_ENUM:
4190 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4191 pTIHeader, pTITail);
4192 break;
4194 case TKIND_RECORD:
4195 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4196 pTIHeader, pTITail);
4197 break;
4199 case TKIND_INTERFACE:
4200 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4201 pTIHeader, pTITail);
4202 break;
4204 case TKIND_COCLASS:
4205 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4206 pTIHeader, pTITail);
4207 break;
4209 case TKIND_ALIAS:
4210 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4211 pTIHeader, pTITail);
4212 break;
4214 case TKIND_DISPATCH:
4215 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4216 pTIHeader, pTITail);
4217 break;
4219 case TKIND_MODULE:
4220 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4221 pTIHeader, pTITail);
4222 break;
4224 default:
4225 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4226 break;
4230 /* could get cFuncs, cVars and cImplTypes from here
4231 but we've already set those */
4232 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4233 X(06);
4234 X(16);
4235 X(18);
4236 X(1a);
4237 X(1e);
4238 X(24);
4239 X(26);
4240 X(2a);
4241 X(2c);
4242 X(2e);
4243 X(30);
4244 X(32);
4245 X(34);
4246 #undef X
4247 ++ppTypeInfoImpl;
4248 pBlk = (char*)pBlk + pBlkEntry[order].len;
4251 if(i != pTypeLibImpl->TypeInfoCount) {
4252 FIXME("Somehow processed %d TypeInfos\n", i);
4253 heap_free(pOtherTypeInfoBlks);
4254 return NULL;
4257 heap_free(pOtherTypeInfoBlks);
4258 return &pTypeLibImpl->ITypeLib2_iface;
4261 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4263 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4265 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4267 if(IsEqualIID(riid, &IID_IUnknown) ||
4268 IsEqualIID(riid,&IID_ITypeLib)||
4269 IsEqualIID(riid,&IID_ITypeLib2))
4271 *ppv = &This->ITypeLib2_iface;
4273 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4274 IsEqualIID(riid, &IID_ICreateTypeLib2))
4276 *ppv = &This->ICreateTypeLib2_iface;
4278 else
4280 *ppv = NULL;
4281 TRACE("-- Interface: E_NOINTERFACE\n");
4282 return E_NOINTERFACE;
4285 IUnknown_AddRef((IUnknown*)*ppv);
4286 return S_OK;
4289 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4291 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4292 ULONG ref = InterlockedIncrement(&This->ref);
4294 TRACE("(%p) ref=%u\n", This, ref);
4296 return ref;
4299 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4301 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4302 ULONG ref = InterlockedDecrement(&This->ref);
4304 TRACE("(%p) ref=%u\n",This, ref);
4306 if (!ref)
4308 TLBImpLib *pImpLib, *pImpLibNext;
4309 TLBRefType *ref_type;
4310 void *cursor2;
4311 int i;
4313 /* remove cache entry */
4314 if(This->path)
4316 TRACE("removing from cache list\n");
4317 EnterCriticalSection(&cache_section);
4318 if(This->entry.next)
4319 list_remove(&This->entry);
4320 LeaveCriticalSection(&cache_section);
4321 heap_free(This->path);
4323 TRACE(" destroying ITypeLib(%p)\n",This);
4325 SysFreeString(This->Name);
4326 This->Name = NULL;
4328 SysFreeString(This->DocString);
4329 This->DocString = NULL;
4331 SysFreeString(This->HelpFile);
4332 This->HelpFile = NULL;
4334 SysFreeString(This->HelpStringDll);
4335 This->HelpStringDll = NULL;
4337 TLB_FreeCustData(&This->custdata_list);
4339 for (i = 0; i < This->ctTypeDesc; i++)
4340 if (This->pTypeDesc[i].vt == VT_CARRAY)
4341 heap_free(This->pTypeDesc[i].u.lpadesc);
4343 heap_free(This->pTypeDesc);
4345 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4347 if (pImpLib->pImpTypeLib)
4348 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4349 SysFreeString(pImpLib->name);
4351 list_remove(&pImpLib->entry);
4352 heap_free(pImpLib);
4355 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4357 list_remove(&ref_type->entry);
4358 heap_free(ref_type);
4361 for (i = 0; i < This->TypeInfoCount; ++i)
4362 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4363 heap_free(This->typeinfos);
4364 heap_free(This);
4365 return 0;
4368 return ref;
4371 /* ITypeLib::GetTypeInfoCount
4373 * Returns the number of type descriptions in the type library
4375 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4377 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4378 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4379 return This->TypeInfoCount;
4382 /* ITypeLib::GetTypeInfo
4384 * retrieves the specified type description in the library.
4386 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4387 ITypeLib2 *iface,
4388 UINT index,
4389 ITypeInfo **ppTInfo)
4391 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4393 TRACE("%p %u %p\n", This, index, ppTInfo);
4395 if(!ppTInfo)
4396 return E_INVALIDARG;
4398 if(index >= This->TypeInfoCount)
4399 return TYPE_E_ELEMENTNOTFOUND;
4401 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4402 ITypeInfo_AddRef(*ppTInfo);
4404 return S_OK;
4408 /* ITypeLibs::GetTypeInfoType
4410 * Retrieves the type of a type description.
4412 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4413 ITypeLib2 *iface,
4414 UINT index,
4415 TYPEKIND *pTKind)
4417 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4419 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4421 if(!pTKind)
4422 return E_INVALIDARG;
4424 if(index >= This->TypeInfoCount)
4425 return TYPE_E_ELEMENTNOTFOUND;
4427 *pTKind = This->typeinfos[index]->TypeAttr.typekind;
4429 return S_OK;
4432 /* ITypeLib::GetTypeInfoOfGuid
4434 * Retrieves the type description that corresponds to the specified GUID.
4437 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4438 ITypeLib2 *iface,
4439 REFGUID guid,
4440 ITypeInfo **ppTInfo)
4442 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4443 int i;
4445 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4447 for(i = 0; i < This->TypeInfoCount; ++i){
4448 if(IsEqualIID(&This->typeinfos[i]->TypeAttr.guid, guid)){
4449 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4450 ITypeInfo_AddRef(*ppTInfo);
4451 return S_OK;
4455 return TYPE_E_ELEMENTNOTFOUND;
4458 /* ITypeLib::GetLibAttr
4460 * Retrieves the structure that contains the library's attributes.
4463 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4464 ITypeLib2 *iface,
4465 LPTLIBATTR *attr)
4467 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4469 TRACE("(%p, %p)\n", This, attr);
4471 if (!attr) return E_INVALIDARG;
4473 *attr = heap_alloc(sizeof(**attr));
4474 if (!*attr) return E_OUTOFMEMORY;
4476 **attr = This->LibAttr;
4477 return S_OK;
4480 /* ITypeLib::GetTypeComp
4482 * Enables a client compiler to bind to a library's types, variables,
4483 * constants, and global functions.
4486 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4487 ITypeLib2 *iface,
4488 ITypeComp **ppTComp)
4490 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4492 TRACE("(%p)->(%p)\n",This,ppTComp);
4493 *ppTComp = &This->ITypeComp_iface;
4494 ITypeComp_AddRef(*ppTComp);
4496 return S_OK;
4499 /* ITypeLib::GetDocumentation
4501 * Retrieves the library's documentation string, the complete Help file name
4502 * and path, and the context identifier for the library Help topic in the Help
4503 * file.
4505 * On a successful return all non-null BSTR pointers will have been set,
4506 * possibly to NULL.
4508 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4509 ITypeLib2 *iface,
4510 INT index,
4511 BSTR *pBstrName,
4512 BSTR *pBstrDocString,
4513 DWORD *pdwHelpContext,
4514 BSTR *pBstrHelpFile)
4516 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4517 HRESULT result = E_INVALIDARG;
4518 ITypeInfo *pTInfo;
4520 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4521 This, index,
4522 pBstrName, pBstrDocString,
4523 pdwHelpContext, pBstrHelpFile);
4525 if(index<0)
4527 /* documentation for the typelib */
4528 if(pBstrName)
4530 if (This->Name)
4532 if(!(*pBstrName = SysAllocString(This->Name)))
4533 goto memerr1;
4535 else
4536 *pBstrName = NULL;
4538 if(pBstrDocString)
4540 if (This->DocString)
4542 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4543 goto memerr2;
4545 else if (This->Name)
4547 if(!(*pBstrDocString = SysAllocString(This->Name)))
4548 goto memerr2;
4550 else
4551 *pBstrDocString = NULL;
4553 if(pdwHelpContext)
4555 *pdwHelpContext = This->dwHelpContext;
4557 if(pBstrHelpFile)
4559 if (This->HelpFile)
4561 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4562 goto memerr3;
4564 else
4565 *pBstrHelpFile = NULL;
4568 result = S_OK;
4570 else
4572 /* for a typeinfo */
4573 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4575 if(SUCCEEDED(result))
4577 result = ITypeInfo_GetDocumentation(pTInfo,
4578 MEMBERID_NIL,
4579 pBstrName,
4580 pBstrDocString,
4581 pdwHelpContext, pBstrHelpFile);
4583 ITypeInfo_Release(pTInfo);
4586 return result;
4587 memerr3:
4588 if (pBstrDocString) SysFreeString (*pBstrDocString);
4589 memerr2:
4590 if (pBstrName) SysFreeString (*pBstrName);
4591 memerr1:
4592 return STG_E_INSUFFICIENTMEMORY;
4595 /* ITypeLib::IsName
4597 * Indicates whether a passed-in string contains the name of a type or member
4598 * described in the library.
4601 static HRESULT WINAPI ITypeLib2_fnIsName(
4602 ITypeLib2 *iface,
4603 LPOLESTR szNameBuf,
4604 ULONG lHashVal,
4605 BOOL *pfName)
4607 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4608 int tic;
4609 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
4611 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4612 pfName);
4614 *pfName=TRUE;
4615 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4616 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4617 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4618 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4619 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4620 int pc;
4622 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4623 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++)
4624 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name, nNameBufLen))
4625 goto ITypeLib2_fnIsName_exit;
4627 for(vrc = 0; vrc < pTInfo->TypeAttr.cVars; ++vrc){
4628 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4629 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4633 *pfName=FALSE;
4635 ITypeLib2_fnIsName_exit:
4636 TRACE("(%p)slow! search for %s: %s found!\n", This,
4637 debugstr_w(szNameBuf), *pfName?"NOT":"");
4639 return S_OK;
4642 /* ITypeLib::FindName
4644 * Finds occurrences of a type description in a type library. This may be used
4645 * to quickly verify that a name exists in a type library.
4648 static HRESULT WINAPI ITypeLib2_fnFindName(
4649 ITypeLib2 *iface,
4650 LPOLESTR name,
4651 ULONG hash,
4652 ITypeInfo **ppTInfo,
4653 MEMBERID *memid,
4654 UINT16 *found)
4656 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4657 int tic;
4658 UINT count = 0;
4659 UINT len;
4661 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4663 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4664 return E_INVALIDARG;
4666 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4667 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4668 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4669 TLBVarDesc *var;
4670 UINT fdc;
4672 if(!memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4673 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4674 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4675 int pc;
4677 if(!memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4678 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4679 if(!memcmp(name, func->pParamDesc[pc].Name, len))
4680 goto ITypeLib2_fnFindName_exit;
4684 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->TypeAttr.cVars, name);
4685 if (var)
4686 goto ITypeLib2_fnFindName_exit;
4688 continue;
4689 ITypeLib2_fnFindName_exit:
4690 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4691 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4692 count++;
4694 TRACE("found %d typeinfos\n", count);
4696 *found = count;
4698 return S_OK;
4701 /* ITypeLib::ReleaseTLibAttr
4703 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4706 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4707 ITypeLib2 *iface,
4708 TLIBATTR *pTLibAttr)
4710 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4711 TRACE("(%p)->(%p)\n", This, pTLibAttr);
4712 heap_free(pTLibAttr);
4715 /* ITypeLib2::GetCustData
4717 * gets the custom data
4719 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4720 ITypeLib2 * iface,
4721 REFGUID guid,
4722 VARIANT *pVarVal)
4724 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4725 TLBCustData *pCData;
4727 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
4729 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
4730 if(!pCData)
4731 return TYPE_E_ELEMENTNOTFOUND;
4733 VariantInit(pVarVal);
4734 VariantCopy(pVarVal, &pCData->data);
4736 return S_OK;
4739 /* ITypeLib2::GetLibStatistics
4741 * Returns statistics about a type library that are required for efficient
4742 * sizing of hash tables.
4745 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4746 ITypeLib2 * iface,
4747 ULONG *pcUniqueNames,
4748 ULONG *pcchUniqueNames)
4750 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4752 FIXME("(%p): stub!\n", This);
4754 if(pcUniqueNames) *pcUniqueNames=1;
4755 if(pcchUniqueNames) *pcchUniqueNames=1;
4756 return S_OK;
4759 /* ITypeLib2::GetDocumentation2
4761 * Retrieves the library's documentation string, the complete Help file name
4762 * and path, the localization context to use, and the context ID for the
4763 * library Help topic in the Help file.
4766 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4767 ITypeLib2 * iface,
4768 INT index,
4769 LCID lcid,
4770 BSTR *pbstrHelpString,
4771 DWORD *pdwHelpStringContext,
4772 BSTR *pbstrHelpStringDll)
4774 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4775 HRESULT result;
4776 ITypeInfo *pTInfo;
4778 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4780 /* the help string should be obtained from the helpstringdll,
4781 * using the _DLLGetDocumentation function, based on the supplied
4782 * lcid. Nice to do sometime...
4784 if(index<0)
4786 /* documentation for the typelib */
4787 if(pbstrHelpString)
4788 *pbstrHelpString=SysAllocString(This->DocString);
4789 if(pdwHelpStringContext)
4790 *pdwHelpStringContext=This->dwHelpContext;
4791 if(pbstrHelpStringDll)
4792 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4794 result = S_OK;
4796 else
4798 /* for a typeinfo */
4799 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4801 if(SUCCEEDED(result))
4803 ITypeInfo2 * pTInfo2;
4804 result = ITypeInfo_QueryInterface(pTInfo,
4805 &IID_ITypeInfo2,
4806 (LPVOID*) &pTInfo2);
4808 if(SUCCEEDED(result))
4810 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4811 MEMBERID_NIL,
4812 lcid,
4813 pbstrHelpString,
4814 pdwHelpStringContext,
4815 pbstrHelpStringDll);
4817 ITypeInfo2_Release(pTInfo2);
4820 ITypeInfo_Release(pTInfo);
4823 return result;
4826 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
4828 TLBCustData *pCData;
4829 unsigned int ct;
4830 CUSTDATAITEM *cdi;
4832 ct = list_count(custdata_list);
4834 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
4835 if(!pCustData->prgCustData)
4836 return E_OUTOFMEMORY;
4838 pCustData->cCustData = ct;
4840 cdi = pCustData->prgCustData;
4841 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
4842 cdi->guid = pCData->guid;
4843 VariantCopy(&cdi->varValue, &pCData->data);
4844 ++cdi;
4847 return S_OK;
4851 /* ITypeLib2::GetAllCustData
4853 * Gets all custom data items for the library.
4856 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4857 ITypeLib2 * iface,
4858 CUSTDATA *pCustData)
4860 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4861 TRACE("(%p)->(%p)\n", This, pCustData);
4862 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
4865 static const ITypeLib2Vtbl tlbvt = {
4866 ITypeLib2_fnQueryInterface,
4867 ITypeLib2_fnAddRef,
4868 ITypeLib2_fnRelease,
4869 ITypeLib2_fnGetTypeInfoCount,
4870 ITypeLib2_fnGetTypeInfo,
4871 ITypeLib2_fnGetTypeInfoType,
4872 ITypeLib2_fnGetTypeInfoOfGuid,
4873 ITypeLib2_fnGetLibAttr,
4874 ITypeLib2_fnGetTypeComp,
4875 ITypeLib2_fnGetDocumentation,
4876 ITypeLib2_fnIsName,
4877 ITypeLib2_fnFindName,
4878 ITypeLib2_fnReleaseTLibAttr,
4880 ITypeLib2_fnGetCustData,
4881 ITypeLib2_fnGetLibStatistics,
4882 ITypeLib2_fnGetDocumentation2,
4883 ITypeLib2_fnGetAllCustData
4887 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4889 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4891 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
4894 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4896 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4898 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
4901 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4903 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4905 return ITypeLib2_Release(&This->ITypeLib2_iface);
4908 static HRESULT WINAPI ITypeLibComp_fnBind(
4909 ITypeComp * iface,
4910 OLECHAR * szName,
4911 ULONG lHash,
4912 WORD wFlags,
4913 ITypeInfo ** ppTInfo,
4914 DESCKIND * pDescKind,
4915 BINDPTR * pBindPtr)
4917 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4918 int typemismatch=0, i;
4920 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4922 *pDescKind = DESCKIND_NONE;
4923 pBindPtr->lptcomp = NULL;
4924 *ppTInfo = NULL;
4926 for(i = 0; i < This->TypeInfoCount; ++i){
4927 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4928 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4930 /* FIXME: check wFlags here? */
4931 /* FIXME: we should use a hash table to look this info up using lHash
4932 * instead of an O(n) search */
4933 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4934 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4936 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4938 *pDescKind = DESCKIND_TYPECOMP;
4939 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
4940 ITypeComp_AddRef(pBindPtr->lptcomp);
4941 TRACE("module or enum: %s\n", debugstr_w(szName));
4942 return S_OK;
4946 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4947 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4949 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
4950 HRESULT hr;
4952 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4953 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4955 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4956 return S_OK;
4958 else if (hr == TYPE_E_TYPEMISMATCH)
4959 typemismatch = 1;
4962 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4963 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4965 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
4966 HRESULT hr;
4967 ITypeInfo *subtypeinfo;
4968 BINDPTR subbindptr;
4969 DESCKIND subdesckind;
4971 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4972 &subtypeinfo, &subdesckind, &subbindptr);
4973 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4975 TYPEDESC tdesc_appobject;
4976 const VARDESC vardesc_appobject =
4978 -2, /* memid */
4979 NULL, /* lpstrSchema */
4981 0 /* oInst */
4984 /* ELEMDESC */
4986 /* TYPEDESC */
4988 &tdesc_appobject
4990 VT_PTR
4993 0, /* wVarFlags */
4994 VAR_STATIC /* varkind */
4997 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4998 tdesc_appobject.vt = VT_USERDEFINED;
5000 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5002 /* cleanup things filled in by Bind call so we can put our
5003 * application object data in there instead */
5004 switch (subdesckind)
5006 case DESCKIND_FUNCDESC:
5007 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5008 break;
5009 case DESCKIND_VARDESC:
5010 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5011 break;
5012 default:
5013 break;
5015 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5017 if (pTypeInfo->hreftype == -1)
5018 FIXME("no hreftype for interface %p\n", pTypeInfo);
5020 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5021 if (FAILED(hr))
5022 return hr;
5024 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5025 *ppTInfo = (ITypeInfo *)pTypeInfo;
5026 ITypeInfo_AddRef(*ppTInfo);
5027 return S_OK;
5029 else if (hr == TYPE_E_TYPEMISMATCH)
5030 typemismatch = 1;
5034 if (typemismatch)
5036 TRACE("type mismatch %s\n", debugstr_w(szName));
5037 return TYPE_E_TYPEMISMATCH;
5039 else
5041 TRACE("name not found %s\n", debugstr_w(szName));
5042 return S_OK;
5046 static HRESULT WINAPI ITypeLibComp_fnBindType(
5047 ITypeComp * iface,
5048 OLECHAR * szName,
5049 ULONG lHash,
5050 ITypeInfo ** ppTInfo,
5051 ITypeComp ** ppTComp)
5053 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5054 int i;
5056 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5058 if(!szName || !ppTInfo || !ppTComp)
5059 return E_INVALIDARG;
5061 for(i = 0; i < This->TypeInfoCount; ++i)
5063 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5064 /* FIXME: should use lHash to do the search */
5065 if (pTypeInfo->Name && !strcmpiW(pTypeInfo->Name, szName))
5067 TRACE("returning %p\n", pTypeInfo);
5068 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5069 ITypeInfo_AddRef(*ppTInfo);
5070 *ppTComp = &pTypeInfo->ITypeComp_iface;
5071 ITypeComp_AddRef(*ppTComp);
5072 return S_OK;
5076 TRACE("not found\n");
5077 *ppTInfo = NULL;
5078 *ppTComp = NULL;
5079 return S_OK;
5082 static const ITypeCompVtbl tlbtcvt =
5085 ITypeLibComp_fnQueryInterface,
5086 ITypeLibComp_fnAddRef,
5087 ITypeLibComp_fnRelease,
5089 ITypeLibComp_fnBind,
5090 ITypeLibComp_fnBindType
5093 /*================== ITypeInfo(2) Methods ===================================*/
5094 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5096 ITypeInfoImpl *pTypeInfoImpl;
5098 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5099 if (pTypeInfoImpl)
5101 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5102 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5103 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5104 pTypeInfoImpl->ref = 0;
5105 pTypeInfoImpl->hreftype = -1;
5106 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
5107 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
5108 list_init(&pTypeInfoImpl->custdata_list);
5110 TRACE("(%p)\n", pTypeInfoImpl);
5111 return pTypeInfoImpl;
5114 /* ITypeInfo::QueryInterface
5116 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5117 ITypeInfo2 *iface,
5118 REFIID riid,
5119 VOID **ppvObject)
5121 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5123 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5125 *ppvObject=NULL;
5126 if(IsEqualIID(riid, &IID_IUnknown) ||
5127 IsEqualIID(riid,&IID_ITypeInfo)||
5128 IsEqualIID(riid,&IID_ITypeInfo2))
5129 *ppvObject = This;
5130 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5131 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5132 *ppvObject = &This->ICreateTypeInfo2_iface;
5134 if(*ppvObject){
5135 ITypeInfo2_AddRef(iface);
5136 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5137 return S_OK;
5139 TRACE("-- Interface: E_NOINTERFACE\n");
5140 return E_NOINTERFACE;
5143 /* ITypeInfo::AddRef
5145 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5147 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5148 ULONG ref = InterlockedIncrement(&This->ref);
5150 TRACE("(%p)->ref is %u\n",This, ref);
5152 if (ref == 1 /* incremented from 0 */)
5153 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5155 return ref;
5158 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5160 UINT i;
5162 TRACE("destroying ITypeInfo(%p)\n",This);
5164 SysFreeString(This->Name);
5165 This->Name = NULL;
5167 SysFreeString(This->DocString);
5168 This->DocString = NULL;
5170 SysFreeString(This->DllName);
5171 This->DllName = NULL;
5173 for (i = 0; i < This->TypeAttr.cFuncs; ++i)
5175 int j;
5176 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5177 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5179 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5180 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5182 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5183 heap_free(elemdesc->u.paramdesc.pparamdescex);
5185 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5186 SysFreeString(pFInfo->pParamDesc[j].Name);
5188 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5189 heap_free(pFInfo->pParamDesc);
5190 TLB_FreeCustData(&pFInfo->custdata_list);
5191 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5192 SysFreeString(pFInfo->Entry);
5193 SysFreeString(pFInfo->HelpString);
5194 SysFreeString(pFInfo->Name);
5196 heap_free(This->funcdescs);
5198 for(i = 0; i < This->TypeAttr.cVars; ++i)
5200 TLBVarDesc *pVInfo = &This->vardescs[i];
5201 if (pVInfo->vardesc.varkind == VAR_CONST)
5203 VariantClear(pVInfo->vardesc.u.lpvarValue);
5204 heap_free(pVInfo->vardesc.u.lpvarValue);
5206 TLB_FreeCustData(&pVInfo->custdata_list);
5207 SysFreeString(pVInfo->Name);
5208 SysFreeString(pVInfo->HelpString);
5210 heap_free(This->vardescs);
5212 if(This->impltypes){
5213 for (i = 0; i < This->TypeAttr.cImplTypes; ++i){
5214 TLBImplType *pImpl = &This->impltypes[i];
5215 TLB_FreeCustData(&pImpl->custdata_list);
5217 heap_free(This->impltypes);
5220 TLB_FreeCustData(&This->custdata_list);
5222 heap_free(This);
5225 /* ITypeInfo::Release
5227 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5229 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5230 ULONG ref = InterlockedDecrement(&This->ref);
5232 TRACE("(%p)->(%u)\n",This, ref);
5234 if (!ref)
5236 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5237 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5238 if (not_attached_to_typelib)
5239 heap_free(This);
5240 /* otherwise This will be freed when typelib is freed */
5243 return ref;
5246 /* ITypeInfo::GetTypeAttr
5248 * Retrieves a TYPEATTR structure that contains the attributes of the type
5249 * description.
5252 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5253 LPTYPEATTR *ppTypeAttr)
5255 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5256 SIZE_T size;
5258 TRACE("(%p)\n",This);
5260 size = sizeof(**ppTypeAttr);
5261 if (This->TypeAttr.typekind == TKIND_ALIAS)
5262 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5264 *ppTypeAttr = heap_alloc(size);
5265 if (!*ppTypeAttr)
5266 return E_OUTOFMEMORY;
5268 **ppTypeAttr = This->TypeAttr;
5270 if (This->TypeAttr.typekind == TKIND_ALIAS)
5271 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5272 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5274 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5275 /* This should include all the inherited funcs */
5276 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5277 /* This is always the size of IDispatch's vtbl */
5278 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5279 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5281 return S_OK;
5284 /* ITypeInfo::GetTypeComp
5286 * Retrieves the ITypeComp interface for the type description, which enables a
5287 * client compiler to bind to the type description's members.
5290 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5291 ITypeComp * *ppTComp)
5293 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5295 TRACE("(%p)->(%p)\n", This, ppTComp);
5297 *ppTComp = &This->ITypeComp_iface;
5298 ITypeComp_AddRef(*ppTComp);
5299 return S_OK;
5302 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5304 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5305 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5306 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5307 return size;
5310 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5312 *dest = *src;
5313 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5314 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5316 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5317 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5318 *buffer += sizeof(PARAMDESCEX);
5319 *pparamdescex_dest = *pparamdescex_src;
5320 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5321 VariantInit(&pparamdescex_dest->varDefaultValue);
5322 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5323 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5325 else
5326 dest->u.paramdesc.pparamdescex = NULL;
5327 return S_OK;
5330 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5332 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5333 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5336 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5338 FUNCDESC *dest;
5339 char *buffer;
5340 SIZE_T size = sizeof(*src);
5341 SHORT i;
5342 HRESULT hr;
5344 size += sizeof(*src->lprgscode) * src->cScodes;
5345 size += TLB_SizeElemDesc(&src->elemdescFunc);
5346 for (i = 0; i < src->cParams; i++)
5348 size += sizeof(ELEMDESC);
5349 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5352 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5353 if (!dest) return E_OUTOFMEMORY;
5355 *dest = *src;
5356 if (dispinterface) /* overwrite funckind */
5357 dest->funckind = FUNC_DISPATCH;
5358 buffer = (char *)(dest + 1);
5360 if (dest->cScodes) {
5361 dest->lprgscode = (SCODE *)buffer;
5362 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5363 buffer += sizeof(*src->lprgscode) * src->cScodes;
5364 } else
5365 dest->lprgscode = NULL;
5367 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5368 if (FAILED(hr))
5370 SysFreeString((BSTR)dest);
5371 return hr;
5374 if (dest->cParams) {
5375 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5376 buffer += sizeof(ELEMDESC) * src->cParams;
5377 for (i = 0; i < src->cParams; i++)
5379 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5380 if (FAILED(hr))
5381 break;
5383 if (FAILED(hr))
5385 /* undo the above actions */
5386 for (i = i - 1; i >= 0; i--)
5387 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5388 TLB_FreeElemDesc(&dest->elemdescFunc);
5389 SysFreeString((BSTR)dest);
5390 return hr;
5392 } else
5393 dest->lprgelemdescParam = NULL;
5395 /* special treatment for dispinterfaces: this makes functions appear
5396 * to return their [retval] value when it is really returning an
5397 * HRESULT */
5398 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5400 if (dest->cParams &&
5401 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5403 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5404 if (elemdesc->tdesc.vt != VT_PTR)
5406 ERR("elemdesc should have started with VT_PTR instead of:\n");
5407 if (ERR_ON(ole))
5408 dump_ELEMDESC(elemdesc);
5409 return E_UNEXPECTED;
5412 /* copy last parameter to the return value. we are using a flat
5413 * buffer so there is no danger of leaking memory in
5414 * elemdescFunc */
5415 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5417 /* remove the last parameter */
5418 dest->cParams--;
5420 else
5421 /* otherwise this function is made to appear to have no return
5422 * value */
5423 dest->elemdescFunc.tdesc.vt = VT_VOID;
5427 *dest_ptr = dest;
5428 return S_OK;
5431 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5433 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5435 if (index >= This->TypeAttr.cFuncs)
5436 return TYPE_E_ELEMENTNOTFOUND;
5438 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5439 return S_OK;
5442 /* internal function to make the inherited interfaces' methods appear
5443 * part of the interface */
5444 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5445 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5447 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5448 HRESULT hr;
5449 UINT implemented_funcs = 0;
5451 if (funcs)
5452 *funcs = 0;
5453 else
5454 *hrefoffset = DISPATCH_HREF_OFFSET;
5456 if(This->impltypes)
5458 ITypeInfo *pSubTypeInfo;
5459 UINT sub_funcs;
5461 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5462 if (FAILED(hr))
5463 return hr;
5465 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5466 index,
5467 ppFuncDesc,
5468 &sub_funcs, hrefoffset);
5469 implemented_funcs += sub_funcs;
5470 ITypeInfo_Release(pSubTypeInfo);
5471 if (SUCCEEDED(hr))
5472 return hr;
5473 *hrefoffset += DISPATCH_HREF_OFFSET;
5476 if (funcs)
5477 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5478 else
5479 *hrefoffset = 0;
5481 if (index < implemented_funcs)
5482 return E_INVALIDARG;
5483 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5484 ppFuncDesc);
5487 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5489 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5490 while (TRUE)
5492 switch (pTypeDesc->vt)
5494 case VT_USERDEFINED:
5495 pTypeDesc->u.hreftype += hrefoffset;
5496 return;
5497 case VT_PTR:
5498 case VT_SAFEARRAY:
5499 pTypeDesc = pTypeDesc->u.lptdesc;
5500 break;
5501 case VT_CARRAY:
5502 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5503 break;
5504 default:
5505 return;
5510 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5512 SHORT i;
5513 for (i = 0; i < pFuncDesc->cParams; i++)
5514 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5515 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5518 /* ITypeInfo::GetFuncDesc
5520 * Retrieves the FUNCDESC structure that contains information about a
5521 * specified function.
5524 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5525 LPFUNCDESC *ppFuncDesc)
5527 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5528 const FUNCDESC *internal_funcdesc;
5529 HRESULT hr;
5530 UINT hrefoffset = 0;
5532 TRACE("(%p) index %d\n", This, index);
5534 if (!ppFuncDesc)
5535 return E_INVALIDARG;
5537 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5538 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5539 &internal_funcdesc, NULL,
5540 &hrefoffset);
5541 else
5542 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5543 &internal_funcdesc);
5544 if (FAILED(hr))
5546 WARN("description for function %d not found\n", index);
5547 return hr;
5550 hr = TLB_AllocAndInitFuncDesc(
5551 internal_funcdesc,
5552 ppFuncDesc,
5553 This->TypeAttr.typekind == TKIND_DISPATCH);
5555 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5556 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5558 TRACE("-- 0x%08x\n", hr);
5559 return hr;
5562 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5564 VARDESC *dest;
5565 char *buffer;
5566 SIZE_T size = sizeof(*src);
5567 HRESULT hr;
5569 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5570 if (src->varkind == VAR_CONST)
5571 size += sizeof(VARIANT);
5572 size += TLB_SizeElemDesc(&src->elemdescVar);
5574 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5575 if (!dest) return E_OUTOFMEMORY;
5577 *dest = *src;
5578 buffer = (char *)(dest + 1);
5579 if (src->lpstrSchema)
5581 int len;
5582 dest->lpstrSchema = (LPOLESTR)buffer;
5583 len = strlenW(src->lpstrSchema);
5584 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5585 buffer += (len + 1) * sizeof(WCHAR);
5588 if (src->varkind == VAR_CONST)
5590 HRESULT hr;
5592 dest->u.lpvarValue = (VARIANT *)buffer;
5593 *dest->u.lpvarValue = *src->u.lpvarValue;
5594 buffer += sizeof(VARIANT);
5595 VariantInit(dest->u.lpvarValue);
5596 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5597 if (FAILED(hr))
5599 SysFreeString((BSTR)dest);
5600 return hr;
5603 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5604 if (FAILED(hr))
5606 if (src->varkind == VAR_CONST)
5607 VariantClear(dest->u.lpvarValue);
5608 SysFreeString((BSTR)dest);
5609 return hr;
5611 *dest_ptr = dest;
5612 return S_OK;
5615 /* ITypeInfo::GetVarDesc
5617 * Retrieves a VARDESC structure that describes the specified variable.
5620 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5621 LPVARDESC *ppVarDesc)
5623 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5624 const TLBVarDesc *pVDesc = &This->vardescs[index];
5626 TRACE("(%p) index %d\n", This, index);
5628 if(index >= This->TypeAttr.cVars)
5629 return TYPE_E_ELEMENTNOTFOUND;
5631 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5634 /* ITypeInfo_GetNames
5636 * Retrieves the variable with the specified member ID (or the name of the
5637 * property or method and its parameters) that correspond to the specified
5638 * function ID.
5640 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5641 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5643 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5644 const TLBFuncDesc *pFDesc;
5645 const TLBVarDesc *pVDesc;
5646 int i;
5647 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5648 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
5649 if(pFDesc)
5651 /* function found, now return function and parameter names */
5652 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5654 if(!i)
5655 *rgBstrNames=SysAllocString(pFDesc->Name);
5656 else
5657 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5659 *pcNames=i;
5661 else
5663 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
5664 if(pVDesc)
5666 *rgBstrNames=SysAllocString(pVDesc->Name);
5667 *pcNames=1;
5669 else
5671 if(This->impltypes &&
5672 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5673 /* recursive search */
5674 ITypeInfo *pTInfo;
5675 HRESULT result;
5676 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5677 if(SUCCEEDED(result))
5679 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5680 ITypeInfo_Release(pTInfo);
5681 return result;
5683 WARN("Could not search inherited interface!\n");
5685 else
5687 WARN("no names found\n");
5689 *pcNames=0;
5690 return TYPE_E_ELEMENTNOTFOUND;
5693 return S_OK;
5697 /* ITypeInfo::GetRefTypeOfImplType
5699 * If a type description describes a COM class, it retrieves the type
5700 * description of the implemented interface types. For an interface,
5701 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5702 * if any exist.
5705 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5706 ITypeInfo2 *iface,
5707 UINT index,
5708 HREFTYPE *pRefType)
5710 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5711 HRESULT hr = S_OK;
5713 TRACE("(%p) index %d\n", This, index);
5714 if (TRACE_ON(ole)) dump_TypeInfo(This);
5716 if(index==(UINT)-1)
5718 /* only valid on dual interfaces;
5719 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5721 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5723 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5725 *pRefType = -1;
5727 else
5729 hr = TYPE_E_ELEMENTNOTFOUND;
5732 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5734 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5735 *pRefType = This->pTypeLib->dispatch_href;
5737 else
5739 if(index >= This->TypeAttr.cImplTypes)
5740 hr = TYPE_E_ELEMENTNOTFOUND;
5741 else
5742 *pRefType = This->impltypes[index].hRef;
5745 if(TRACE_ON(ole))
5747 if(SUCCEEDED(hr))
5748 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5749 else
5750 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5753 return hr;
5756 /* ITypeInfo::GetImplTypeFlags
5758 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5759 * or base interface in a type description.
5761 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5762 UINT index, INT *pImplTypeFlags)
5764 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5766 TRACE("(%p) index %d\n", This, index);
5768 if(!pImplTypeFlags)
5769 return E_INVALIDARG;
5771 if(This->TypeAttr.typekind == TKIND_DISPATCH && index == 0){
5772 *pImplTypeFlags = 0;
5773 return S_OK;
5776 if(index >= This->TypeAttr.cImplTypes)
5777 return TYPE_E_ELEMENTNOTFOUND;
5779 *pImplTypeFlags = This->impltypes[index].implflags;
5781 return S_OK;
5784 /* GetIDsOfNames
5785 * Maps between member names and member IDs, and parameter names and
5786 * parameter IDs.
5788 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5789 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5791 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5792 const TLBVarDesc *pVDesc;
5793 HRESULT ret=S_OK;
5794 UINT i, fdc;
5796 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5797 cNames);
5799 /* init out parameters in case of failure */
5800 for (i = 0; i < cNames; i++)
5801 pMemId[i] = MEMBERID_NIL;
5803 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc) {
5804 int j;
5805 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
5806 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5807 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5808 for(i=1; i < cNames; i++){
5809 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5810 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5811 break;
5812 if( j<pFDesc->funcdesc.cParams)
5813 pMemId[i]=j;
5814 else
5815 ret=DISP_E_UNKNOWNNAME;
5817 TRACE("-- 0x%08x\n", ret);
5818 return ret;
5821 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, *rgszNames);
5822 if(pVDesc){
5823 if(cNames)
5824 *pMemId = pVDesc->vardesc.memid;
5825 return ret;
5827 /* not found, see if it can be found in an inherited interface */
5828 if(This->impltypes) {
5829 /* recursive search */
5830 ITypeInfo *pTInfo;
5831 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5832 if(SUCCEEDED(ret)){
5833 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5834 ITypeInfo_Release(pTInfo);
5835 return ret;
5837 WARN("Could not search inherited interface!\n");
5838 } else
5839 WARN("no names found\n");
5840 return DISP_E_UNKNOWNNAME;
5844 #ifdef __i386__
5846 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5847 __ASM_GLOBAL_FUNC( call_method,
5848 "pushl %ebp\n\t"
5849 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5850 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5851 "movl %esp,%ebp\n\t"
5852 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5853 "pushl %esi\n\t"
5854 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5855 "pushl %edi\n\t"
5856 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5857 "movl 12(%ebp),%edx\n\t"
5858 "movl %esp,%edi\n\t"
5859 "shll $2,%edx\n\t"
5860 "jz 1f\n\t"
5861 "subl %edx,%edi\n\t"
5862 "andl $~15,%edi\n\t"
5863 "movl %edi,%esp\n\t"
5864 "movl 12(%ebp),%ecx\n\t"
5865 "movl 16(%ebp),%esi\n\t"
5866 "cld\n\t"
5867 "rep; movsl\n"
5868 "1:\tcall *8(%ebp)\n\t"
5869 "subl %esp,%edi\n\t"
5870 "movl 20(%ebp),%ecx\n\t"
5871 "movl %edi,(%ecx)\n\t"
5872 "leal -8(%ebp),%esp\n\t"
5873 "popl %edi\n\t"
5874 __ASM_CFI(".cfi_same_value %edi\n\t")
5875 "popl %esi\n\t"
5876 __ASM_CFI(".cfi_same_value %esi\n\t")
5877 "popl %ebp\n\t"
5878 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5879 __ASM_CFI(".cfi_same_value %ebp\n\t")
5880 "ret" )
5882 /* same function but returning floating point */
5883 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5885 /* ITypeInfo::Invoke
5887 * Invokes a method, or accesses a property of an object, that implements the
5888 * interface described by the type description.
5890 DWORD
5891 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5892 DWORD res;
5893 int stack_offset;
5895 if (TRACE_ON(ole)) {
5896 int i;
5897 TRACE("Calling %p(",func);
5898 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5899 if (nrargs > 30) TRACE("...");
5900 TRACE(")\n");
5903 switch (callconv) {
5904 case CC_STDCALL:
5905 case CC_CDECL:
5906 res = call_method( func, nrargs, args, &stack_offset );
5907 break;
5908 default:
5909 FIXME("unsupported calling convention %d\n",callconv);
5910 res = -1;
5911 break;
5913 TRACE("returns %08x\n",res);
5914 return res;
5917 #elif defined(__x86_64__)
5919 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5920 __ASM_GLOBAL_FUNC( call_method,
5921 "pushq %rbp\n\t"
5922 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5923 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5924 "movq %rsp,%rbp\n\t"
5925 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5926 "pushq %rsi\n\t"
5927 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5928 "pushq %rdi\n\t"
5929 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5930 "movq %rcx,%rax\n\t"
5931 "movq $4,%rcx\n\t"
5932 "cmp %rcx,%rdx\n\t"
5933 "cmovgq %rdx,%rcx\n\t"
5934 "leaq 0(,%rcx,8),%rdx\n\t"
5935 "subq %rdx,%rsp\n\t"
5936 "andq $~15,%rsp\n\t"
5937 "movq %rsp,%rdi\n\t"
5938 "movq %r8,%rsi\n\t"
5939 "rep; movsq\n\t"
5940 "movq 0(%rsp),%rcx\n\t"
5941 "movq 8(%rsp),%rdx\n\t"
5942 "movq 16(%rsp),%r8\n\t"
5943 "movq 24(%rsp),%r9\n\t"
5944 "movq %rcx,%xmm0\n\t"
5945 "movq %rdx,%xmm1\n\t"
5946 "movq %r8,%xmm2\n\t"
5947 "movq %r9,%xmm3\n\t"
5948 "callq *%rax\n\t"
5949 "leaq -16(%rbp),%rsp\n\t"
5950 "popq %rdi\n\t"
5951 __ASM_CFI(".cfi_same_value %rdi\n\t")
5952 "popq %rsi\n\t"
5953 __ASM_CFI(".cfi_same_value %rsi\n\t")
5954 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5955 "popq %rbp\n\t"
5956 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5957 __ASM_CFI(".cfi_same_value %rbp\n\t")
5958 "ret")
5960 /* same function but returning floating point */
5961 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5963 #endif /* __x86_64__ */
5965 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5967 HRESULT hr = S_OK;
5968 ITypeInfo *tinfo2 = NULL;
5969 TYPEATTR *tattr = NULL;
5971 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5972 if (hr)
5974 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5975 "hr = 0x%08x\n",
5976 tdesc->u.hreftype, hr);
5977 return hr;
5979 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5980 if (hr)
5982 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5983 ITypeInfo_Release(tinfo2);
5984 return hr;
5987 switch (tattr->typekind)
5989 case TKIND_ENUM:
5990 *vt |= VT_I4;
5991 break;
5993 case TKIND_ALIAS:
5994 tdesc = &tattr->tdescAlias;
5995 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5996 break;
5998 case TKIND_INTERFACE:
5999 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6000 *vt |= VT_DISPATCH;
6001 else
6002 *vt |= VT_UNKNOWN;
6003 break;
6005 case TKIND_DISPATCH:
6006 *vt |= VT_DISPATCH;
6007 break;
6009 case TKIND_COCLASS:
6010 *vt |= VT_DISPATCH;
6011 break;
6013 case TKIND_RECORD:
6014 FIXME("TKIND_RECORD unhandled.\n");
6015 hr = E_NOTIMPL;
6016 break;
6018 case TKIND_UNION:
6019 FIXME("TKIND_UNION unhandled.\n");
6020 hr = E_NOTIMPL;
6021 break;
6023 default:
6024 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6025 hr = E_NOTIMPL;
6026 break;
6028 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6029 ITypeInfo_Release(tinfo2);
6030 return hr;
6033 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6035 HRESULT hr = S_OK;
6037 /* enforce only one level of pointer indirection */
6038 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6040 tdesc = tdesc->u.lptdesc;
6042 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6043 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6044 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6045 if ((tdesc->vt == VT_USERDEFINED) ||
6046 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6048 VARTYPE vt_userdefined = 0;
6049 const TYPEDESC *tdesc_userdefined = tdesc;
6050 if (tdesc->vt == VT_PTR)
6052 vt_userdefined = VT_BYREF;
6053 tdesc_userdefined = tdesc->u.lptdesc;
6055 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6056 if ((hr == S_OK) &&
6057 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6058 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6060 *vt |= vt_userdefined;
6061 return S_OK;
6064 *vt = VT_BYREF;
6067 switch (tdesc->vt)
6069 case VT_HRESULT:
6070 *vt |= VT_ERROR;
6071 break;
6072 case VT_USERDEFINED:
6073 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6074 break;
6075 case VT_VOID:
6076 case VT_CARRAY:
6077 case VT_PTR:
6078 case VT_LPSTR:
6079 case VT_LPWSTR:
6080 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6081 hr = DISP_E_BADVARTYPE;
6082 break;
6083 case VT_SAFEARRAY:
6084 *vt |= VT_ARRAY;
6085 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6086 break;
6087 case VT_INT:
6088 *vt |= VT_I4;
6089 break;
6090 case VT_UINT:
6091 *vt |= VT_UI4;
6092 break;
6093 default:
6094 *vt |= tdesc->vt;
6095 break;
6097 return hr;
6100 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6102 ITypeInfo *tinfo2;
6103 TYPEATTR *tattr;
6104 HRESULT hres;
6106 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6107 if(FAILED(hres))
6108 return hres;
6110 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6111 if(FAILED(hres)) {
6112 ITypeInfo_Release(tinfo2);
6113 return hres;
6116 switch(tattr->typekind) {
6117 case TKIND_ALIAS:
6118 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6119 break;
6121 case TKIND_INTERFACE:
6122 case TKIND_DISPATCH:
6123 *guid = tattr->guid;
6124 break;
6126 default:
6127 ERR("Unexpected typekind %d\n", tattr->typekind);
6128 hres = E_UNEXPECTED;
6131 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6132 ITypeInfo_Release(tinfo2);
6133 return hres;
6136 /***********************************************************************
6137 * DispCallFunc (OLEAUT32.@)
6139 * Invokes a function of the specified calling convention, passing the
6140 * specified arguments and returns the result.
6142 * PARAMS
6143 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6144 * oVft [I] The offset in the vtable. See notes.
6145 * cc [I] Calling convention of the function to call.
6146 * vtReturn [I] The return type of the function.
6147 * cActuals [I] Number of parameters.
6148 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6149 * prgpvarg [I] The arguments to pass.
6150 * pvargResult [O] The return value of the function. Can be NULL.
6152 * RETURNS
6153 * Success: S_OK.
6154 * Failure: HRESULT code.
6156 * NOTES
6157 * The HRESULT return value of this function is not affected by the return
6158 * value of the user supplied function, which is returned in pvargResult.
6160 * If pvInstance is NULL then a non-object function is to be called and oVft
6161 * is the address of the function to call.
6163 * The cc parameter can be one of the following values:
6164 *|CC_FASTCALL
6165 *|CC_CDECL
6166 *|CC_PASCAL
6167 *|CC_STDCALL
6168 *|CC_FPFASTCALL
6169 *|CC_SYSCALL
6170 *|CC_MPWCDECL
6171 *|CC_MPWPASCAL
6174 HRESULT WINAPI
6175 DispCallFunc(
6176 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6177 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6179 #ifdef __i386__
6180 int argspos, stack_offset;
6181 void *func;
6182 UINT i;
6183 DWORD *args;
6185 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6186 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6187 pvargResult, V_VT(pvargResult));
6189 if (cc != CC_STDCALL && cc != CC_CDECL)
6191 FIXME("unsupported calling convention %d\n",cc);
6192 return E_INVALIDARG;
6195 /* maximum size for an argument is sizeof(VARIANT) */
6196 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6198 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6199 argspos = 1;
6200 if (pvInstance)
6202 const FARPROC *vtable = *(FARPROC **)pvInstance;
6203 func = vtable[oVft/sizeof(void *)];
6204 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6206 else func = (void *)oVft;
6208 for (i = 0; i < cActuals; i++)
6210 VARIANT *arg = prgpvarg[i];
6212 switch (prgvt[i])
6214 case VT_EMPTY:
6215 break;
6216 case VT_I8:
6217 case VT_UI8:
6218 case VT_R8:
6219 case VT_DATE:
6220 case VT_CY:
6221 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6222 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6223 break;
6224 case VT_DECIMAL:
6225 case VT_VARIANT:
6226 memcpy( &args[argspos], arg, sizeof(*arg) );
6227 argspos += sizeof(*arg) / sizeof(DWORD);
6228 break;
6229 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6230 args[argspos++] = V_BOOL(arg);
6231 break;
6232 default:
6233 args[argspos++] = V_UI4(arg);
6234 break;
6236 TRACE("arg %u: type %d\n",i,prgvt[i]);
6237 dump_Variant(arg);
6240 switch (vtReturn)
6242 case VT_EMPTY:
6243 call_method( func, argspos - 1, args + 1, &stack_offset );
6244 break;
6245 case VT_R4:
6246 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6247 break;
6248 case VT_R8:
6249 case VT_DATE:
6250 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6251 break;
6252 case VT_DECIMAL:
6253 case VT_VARIANT:
6254 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6255 call_method( func, argspos, args, &stack_offset );
6256 break;
6257 case VT_I8:
6258 case VT_UI8:
6259 case VT_CY:
6260 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6261 break;
6262 case VT_HRESULT:
6263 WARN("invalid return type %u\n", vtReturn);
6264 heap_free( args );
6265 return E_INVALIDARG;
6266 default:
6267 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6268 break;
6270 heap_free( args );
6271 if (stack_offset && cc == CC_STDCALL)
6273 WARN( "stack pointer off by %d\n", stack_offset );
6274 return DISP_E_BADCALLEE;
6276 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6277 TRACE("retval: "); dump_Variant(pvargResult);
6278 return S_OK;
6280 #elif defined(__x86_64__)
6281 int argspos;
6282 UINT i;
6283 DWORD_PTR *args;
6284 void *func;
6286 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6287 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6288 pvargResult, V_VT(pvargResult));
6290 if (cc != CC_STDCALL && cc != CC_CDECL)
6292 FIXME("unsupported calling convention %d\n",cc);
6293 return E_INVALIDARG;
6296 /* maximum size for an argument is sizeof(DWORD_PTR) */
6297 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6299 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6300 argspos = 1;
6301 if (pvInstance)
6303 const FARPROC *vtable = *(FARPROC **)pvInstance;
6304 func = vtable[oVft/sizeof(void *)];
6305 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6307 else func = (void *)oVft;
6309 for (i = 0; i < cActuals; i++)
6311 VARIANT *arg = prgpvarg[i];
6313 switch (prgvt[i])
6315 case VT_DECIMAL:
6316 case VT_VARIANT:
6317 args[argspos++] = (ULONG_PTR)arg;
6318 break;
6319 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6320 args[argspos++] = V_BOOL(arg);
6321 break;
6322 default:
6323 args[argspos++] = V_UI8(arg);
6324 break;
6326 TRACE("arg %u: type %d\n",i,prgvt[i]);
6327 dump_Variant(arg);
6330 switch (vtReturn)
6332 case VT_R4:
6333 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6334 break;
6335 case VT_R8:
6336 case VT_DATE:
6337 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6338 break;
6339 case VT_DECIMAL:
6340 case VT_VARIANT:
6341 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6342 call_method( func, argspos, args );
6343 break;
6344 case VT_HRESULT:
6345 WARN("invalid return type %u\n", vtReturn);
6346 heap_free( args );
6347 return E_INVALIDARG;
6348 default:
6349 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6350 break;
6352 heap_free( args );
6353 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6354 TRACE("retval: "); dump_Variant(pvargResult);
6355 return S_OK;
6357 #else
6358 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6359 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6360 return E_NOTIMPL;
6361 #endif
6364 static inline BOOL func_restricted( const FUNCDESC *desc )
6366 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6369 #define INVBUF_ELEMENT_SIZE \
6370 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6371 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6372 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6373 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6374 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6375 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6376 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6377 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6379 static HRESULT WINAPI ITypeInfo_fnInvoke(
6380 ITypeInfo2 *iface,
6381 VOID *pIUnk,
6382 MEMBERID memid,
6383 UINT16 wFlags,
6384 DISPPARAMS *pDispParams,
6385 VARIANT *pVarResult,
6386 EXCEPINFO *pExcepInfo,
6387 UINT *pArgErr)
6389 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6390 int i;
6391 unsigned int var_index;
6392 TYPEKIND type_kind;
6393 HRESULT hres;
6394 const TLBFuncDesc *pFuncInfo;
6395 UINT fdc;
6397 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6398 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6401 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6402 return DISP_E_MEMBERNOTFOUND;
6404 if (!pDispParams)
6406 ERR("NULL pDispParams not allowed\n");
6407 return E_INVALIDARG;
6410 dump_DispParms(pDispParams);
6412 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6414 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6415 pDispParams->cNamedArgs, pDispParams->cArgs);
6416 return E_INVALIDARG;
6419 /* we do this instead of using GetFuncDesc since it will return a fake
6420 * FUNCDESC for dispinterfaces and we want the real function description */
6421 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
6422 pFuncInfo = &This->funcdescs[fdc];
6423 if ((memid == pFuncInfo->funcdesc.memid) &&
6424 (wFlags & pFuncInfo->funcdesc.invkind) &&
6425 !func_restricted( &pFuncInfo->funcdesc ))
6426 break;
6429 if (fdc < This->TypeAttr.cFuncs) {
6430 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6432 if (TRACE_ON(ole))
6434 TRACE("invoking:\n");
6435 dump_TLBFuncDescOne(pFuncInfo);
6438 switch (func_desc->funckind) {
6439 case FUNC_PUREVIRTUAL:
6440 case FUNC_VIRTUAL: {
6441 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6442 VARIANT varresult;
6443 VARIANT retval; /* pointer for storing byref retvals in */
6444 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6445 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6446 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6447 UINT cNamedArgs = pDispParams->cNamedArgs;
6448 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6449 UINT vargs_converted=0;
6451 hres = S_OK;
6453 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6455 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6457 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6458 hres = DISP_E_PARAMNOTFOUND;
6459 goto func_fail;
6463 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6465 ERR("functions with the vararg attribute do not support named arguments\n");
6466 hres = DISP_E_NONAMEDARGS;
6467 goto func_fail;
6470 for (i = 0; i < func_desc->cParams; i++)
6472 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6473 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6474 if (FAILED(hres))
6475 goto func_fail;
6478 TRACE("changing args\n");
6479 for (i = 0; i < func_desc->cParams; i++)
6481 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6482 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6483 VARIANTARG *src_arg;
6485 if (wParamFlags & PARAMFLAG_FLCID)
6487 VARIANTARG *arg;
6488 arg = prgpvarg[i] = &rgvarg[i];
6489 V_VT(arg) = VT_I4;
6490 V_I4(arg) = This->pTypeLib->lcid;
6491 continue;
6494 src_arg = NULL;
6496 if (cNamedArgs)
6498 USHORT j;
6499 for (j = 0; j < cNamedArgs; j++)
6500 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6502 src_arg = &pDispParams->rgvarg[j];
6503 break;
6507 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6509 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6510 vargs_converted++;
6513 if (wParamFlags & PARAMFLAG_FRETVAL)
6515 /* under most conditions the caller is not allowed to
6516 * pass in a dispparam arg in the index of what would be
6517 * the retval parameter. however, there is an exception
6518 * where the extra parameter is used in an extra
6519 * IDispatch::Invoke below */
6520 if ((i < pDispParams->cArgs) &&
6521 ((func_desc->cParams != 1) || !pVarResult ||
6522 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6524 hres = DISP_E_BADPARAMCOUNT;
6525 break;
6528 /* note: this check is placed so that if the caller passes
6529 * in a VARIANTARG for the retval we just ignore it, like
6530 * native does */
6531 if (i == func_desc->cParams - 1)
6533 VARIANTARG *arg;
6534 arg = prgpvarg[i] = &rgvarg[i];
6535 memset(arg, 0, sizeof(*arg));
6536 V_VT(arg) = rgvt[i];
6537 memset(&retval, 0, sizeof(retval));
6538 V_BYREF(arg) = &retval;
6540 else
6542 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6543 hres = E_UNEXPECTED;
6544 break;
6547 else if (src_arg)
6549 dump_Variant(src_arg);
6551 if(rgvt[i]!=V_VT(src_arg))
6553 if (rgvt[i] == VT_VARIANT)
6554 hres = VariantCopy(&rgvarg[i], src_arg);
6555 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6557 if (rgvt[i] == V_VT(src_arg))
6558 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6559 else
6561 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6562 if (wParamFlags & PARAMFLAG_FIN)
6563 hres = VariantCopy(&missing_arg[i], src_arg);
6564 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6566 V_VT(&rgvarg[i]) = rgvt[i];
6568 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6570 SAFEARRAY *a;
6571 SAFEARRAYBOUND bound;
6572 VARIANT *v;
6573 LONG j;
6574 bound.lLbound = 0;
6575 bound.cElements = pDispParams->cArgs-i;
6576 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6578 ERR("SafeArrayCreate failed\n");
6579 break;
6581 hres = SafeArrayAccessData(a, (LPVOID)&v);
6582 if (hres != S_OK)
6584 ERR("SafeArrayAccessData failed with %x\n", hres);
6585 SafeArrayDestroy(a);
6586 break;
6588 for (j = 0; j < bound.cElements; j++)
6589 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6590 hres = SafeArrayUnaccessData(a);
6591 if (hres != S_OK)
6593 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6594 SafeArrayDestroy(a);
6595 break;
6597 V_ARRAY(&rgvarg[i]) = a;
6598 V_VT(&rgvarg[i]) = rgvt[i];
6600 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6602 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6603 if (wParamFlags & PARAMFLAG_FIN)
6604 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6605 else
6606 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6607 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6608 V_VT(&rgvarg[i]) = rgvt[i];
6610 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6612 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6613 V_VT(&rgvarg[i]) = rgvt[i];
6615 else
6617 /* FIXME: this doesn't work for VT_BYREF arguments if
6618 * they are not the same type as in the paramdesc */
6619 V_VT(&rgvarg[i]) = V_VT(src_arg);
6620 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6621 V_VT(&rgvarg[i]) = rgvt[i];
6624 if (FAILED(hres))
6626 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6627 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6628 debugstr_VT(src_arg), debugstr_VF(src_arg));
6629 break;
6631 prgpvarg[i] = &rgvarg[i];
6633 else
6635 prgpvarg[i] = src_arg;
6638 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6639 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6640 && V_UNKNOWN(prgpvarg[i])) {
6641 IUnknown *userdefined_iface;
6642 GUID guid;
6644 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6645 if(FAILED(hres))
6646 break;
6648 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6649 if(FAILED(hres)) {
6650 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6651 break;
6654 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6655 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6658 else if (wParamFlags & PARAMFLAG_FOPT)
6660 VARIANTARG *arg;
6661 arg = prgpvarg[i] = &rgvarg[i];
6662 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6664 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6665 if (FAILED(hres))
6666 break;
6668 else
6670 VARIANTARG *missing_arg;
6671 /* if the function wants a pointer to a variant then
6672 * set that up, otherwise just pass the VT_ERROR in
6673 * the argument by value */
6674 if (rgvt[i] & VT_BYREF)
6676 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6677 V_VT(arg) = VT_VARIANT | VT_BYREF;
6678 V_VARIANTREF(arg) = missing_arg;
6680 else
6681 missing_arg = arg;
6682 V_VT(missing_arg) = VT_ERROR;
6683 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6686 else
6688 hres = DISP_E_BADPARAMCOUNT;
6689 break;
6692 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6694 /* VT_VOID is a special case for return types, so it is not
6695 * handled in the general function */
6696 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6697 V_VT(&varresult) = VT_EMPTY;
6698 else
6700 V_VT(&varresult) = 0;
6701 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6702 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6705 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6706 V_VT(&varresult), func_desc->cParams, rgvt,
6707 prgpvarg, &varresult);
6709 vargs_converted = 0;
6711 for (i = 0; i < func_desc->cParams; i++)
6713 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6714 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6716 if (wParamFlags & PARAMFLAG_FLCID)
6717 continue;
6718 else if (wParamFlags & PARAMFLAG_FRETVAL)
6720 if (TRACE_ON(ole))
6722 TRACE("[retval] value: ");
6723 dump_Variant(prgpvarg[i]);
6726 if (pVarResult)
6728 VariantInit(pVarResult);
6729 /* deref return value */
6730 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6733 VARIANT_ClearInd(prgpvarg[i]);
6735 else if (vargs_converted < pDispParams->cArgs)
6737 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6738 if (wParamFlags & PARAMFLAG_FOUT)
6740 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6742 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6744 if (FAILED(hres))
6746 ERR("failed to convert param %d to vt %d\n", i,
6747 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6748 break;
6752 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6753 func_desc->cParamsOpt < 0 &&
6754 i == func_desc->cParams-1)
6756 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6757 LONG j, ubound;
6758 VARIANT *v;
6759 hres = SafeArrayGetUBound(a, 1, &ubound);
6760 if (hres != S_OK)
6762 ERR("SafeArrayGetUBound failed with %x\n", hres);
6763 break;
6765 hres = SafeArrayAccessData(a, (LPVOID)&v);
6766 if (hres != S_OK)
6768 ERR("SafeArrayAccessData failed with %x\n", hres);
6769 break;
6771 for (j = 0; j <= ubound; j++)
6772 VariantClear(&v[j]);
6773 hres = SafeArrayUnaccessData(a);
6774 if (hres != S_OK)
6776 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6777 break;
6780 VariantClear(&rgvarg[i]);
6781 vargs_converted++;
6783 else if (wParamFlags & PARAMFLAG_FOPT)
6785 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6786 VariantClear(&rgvarg[i]);
6789 VariantClear(&missing_arg[i]);
6792 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6794 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6795 hres = DISP_E_EXCEPTION;
6796 if (pExcepInfo)
6798 IErrorInfo *pErrorInfo;
6799 pExcepInfo->scode = V_ERROR(&varresult);
6800 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6802 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6803 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6804 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6805 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6807 IErrorInfo_Release(pErrorInfo);
6811 if (V_VT(&varresult) != VT_ERROR)
6813 TRACE("varresult value: ");
6814 dump_Variant(&varresult);
6816 if (pVarResult)
6818 VariantClear(pVarResult);
6819 *pVarResult = varresult;
6821 else
6822 VariantClear(&varresult);
6825 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6826 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6827 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6828 (pDispParams->cArgs != 0))
6830 if (V_VT(pVarResult) == VT_DISPATCH)
6832 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6833 /* Note: not VariantClear; we still need the dispatch
6834 * pointer to be valid */
6835 VariantInit(pVarResult);
6836 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6837 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6838 pDispParams, pVarResult, pExcepInfo, pArgErr);
6839 IDispatch_Release(pDispatch);
6841 else
6843 VariantClear(pVarResult);
6844 hres = DISP_E_NOTACOLLECTION;
6848 func_fail:
6849 heap_free(buffer);
6850 break;
6852 case FUNC_DISPATCH: {
6853 IDispatch *disp;
6855 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6856 if (SUCCEEDED(hres)) {
6857 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6858 hres = IDispatch_Invoke(
6859 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6860 pVarResult,pExcepInfo,pArgErr
6862 if (FAILED(hres))
6863 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6864 IDispatch_Release(disp);
6865 } else
6866 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6867 break;
6869 default:
6870 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6871 hres = E_FAIL;
6872 break;
6875 TRACE("-- 0x%08x\n", hres);
6876 return hres;
6878 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6879 VARDESC *var_desc;
6881 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6882 if(FAILED(hres)) return hres;
6884 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6885 dump_VARDESC(var_desc);
6886 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6887 return E_NOTIMPL;
6890 /* not found, look for it in inherited interfaces */
6891 ITypeInfo2_GetTypeKind(iface, &type_kind);
6892 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6893 if(This->impltypes) {
6894 /* recursive search */
6895 ITypeInfo *pTInfo;
6896 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6897 if(SUCCEEDED(hres)){
6898 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6899 ITypeInfo_Release(pTInfo);
6900 return hres;
6902 WARN("Could not search inherited interface!\n");
6905 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6906 return DISP_E_MEMBERNOTFOUND;
6909 /* ITypeInfo::GetDocumentation
6911 * Retrieves the documentation string, the complete Help file name and path,
6912 * and the context ID for the Help topic for a specified type description.
6914 * (Can be tested by the Visual Basic Editor in Word for instance.)
6916 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6917 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6918 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6920 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6921 const TLBFuncDesc *pFDesc;
6922 const TLBVarDesc *pVDesc;
6923 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6924 " HelpContext(%p) HelpFile(%p)\n",
6925 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6926 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6927 if(pBstrName)
6928 *pBstrName=SysAllocString(This->Name);
6929 if(pBstrDocString)
6930 *pBstrDocString=SysAllocString(This->DocString);
6931 if(pdwHelpContext)
6932 *pdwHelpContext=This->dwHelpContext;
6933 if(pBstrHelpFile)
6934 *pBstrHelpFile=SysAllocString(This->pTypeLib->HelpFile);
6935 return S_OK;
6936 }else {/* for a member */
6937 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6938 if(pFDesc){
6939 if(pBstrName)
6940 *pBstrName = SysAllocString(pFDesc->Name);
6941 if(pBstrDocString)
6942 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6943 if(pdwHelpContext)
6944 *pdwHelpContext=pFDesc->helpcontext;
6945 return S_OK;
6947 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
6948 if(pVDesc){
6949 if(pBstrName)
6950 *pBstrName = SysAllocString(pVDesc->Name);
6951 if(pBstrDocString)
6952 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6953 if(pdwHelpContext)
6954 *pdwHelpContext=pVDesc->HelpContext;
6955 if(pBstrHelpFile)
6956 *pBstrHelpFile = SysAllocString(This->pTypeLib->HelpFile);
6957 return S_OK;
6961 if(This->impltypes &&
6962 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6963 /* recursive search */
6964 ITypeInfo *pTInfo;
6965 HRESULT result;
6966 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6967 if(SUCCEEDED(result)) {
6968 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6969 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6970 ITypeInfo_Release(pTInfo);
6971 return result;
6973 WARN("Could not search inherited interface!\n");
6976 WARN("member %d not found\n", memid);
6977 return TYPE_E_ELEMENTNOTFOUND;
6980 /* ITypeInfo::GetDllEntry
6982 * Retrieves a description or specification of an entry point for a function
6983 * in a DLL.
6985 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6986 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6987 WORD *pwOrdinal)
6989 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6990 const TLBFuncDesc *pFDesc;
6992 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6994 if (pBstrDllName) *pBstrDllName = NULL;
6995 if (pBstrName) *pBstrName = NULL;
6996 if (pwOrdinal) *pwOrdinal = 0;
6998 if (This->TypeAttr.typekind != TKIND_MODULE)
6999 return TYPE_E_BADMODULEKIND;
7001 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7002 if(pFDesc){
7003 dump_TypeInfo(This);
7004 if (TRACE_ON(ole))
7005 dump_TLBFuncDescOne(pFDesc);
7007 if (pBstrDllName)
7008 *pBstrDllName = SysAllocString(This->DllName);
7010 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7011 if (pBstrName)
7012 *pBstrName = SysAllocString(pFDesc->Entry);
7013 if (pwOrdinal)
7014 *pwOrdinal = -1;
7015 return S_OK;
7017 if (pBstrName)
7018 *pBstrName = NULL;
7019 if (pwOrdinal)
7020 *pwOrdinal = LOWORD(pFDesc->Entry);
7021 return S_OK;
7023 return TYPE_E_ELEMENTNOTFOUND;
7026 /* internal function to make the inherited interfaces' methods appear
7027 * part of the interface */
7028 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7029 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7031 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7032 HRESULT hr;
7034 TRACE("%p, 0x%x\n", iface, *hRefType);
7036 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7038 ITypeInfo *pSubTypeInfo;
7040 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7041 if (FAILED(hr))
7042 return hr;
7044 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7045 hRefType, ppTInfo);
7046 ITypeInfo_Release(pSubTypeInfo);
7047 if (SUCCEEDED(hr))
7048 return hr;
7050 *hRefType -= DISPATCH_HREF_OFFSET;
7052 if (!(*hRefType & DISPATCH_HREF_MASK))
7053 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7054 else
7055 return E_FAIL;
7058 /* ITypeInfo::GetRefTypeInfo
7060 * If a type description references other type descriptions, it retrieves
7061 * the referenced type descriptions.
7063 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7064 ITypeInfo2 *iface,
7065 HREFTYPE hRefType,
7066 ITypeInfo **ppTInfo)
7068 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7069 HRESULT result = E_FAIL;
7071 if(!ppTInfo)
7072 return E_INVALIDARG;
7074 if ((This->hreftype != -1) && (This->hreftype == hRefType))
7076 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
7077 ITypeInfo_AddRef(*ppTInfo);
7078 result = S_OK;
7080 else if (hRefType == -1 &&
7081 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
7082 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
7084 /* when we meet a DUAL dispinterface, we must create the interface
7085 * version of it.
7087 ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
7090 /* the interface version contains the same information as the dispinterface
7091 * copy the contents of the structs.
7093 *pTypeInfoImpl = *This;
7094 pTypeInfoImpl->ref = 0;
7096 /* change the type to interface */
7097 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
7099 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
7101 /* the AddRef implicitly adds a reference to the parent typelib, which
7102 * stops the copied data from being destroyed until the new typeinfo's
7103 * refcount goes to zero, but we need to signal to the new instance to
7104 * not free its data structures when it is destroyed */
7105 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7107 ITypeInfo_AddRef(*ppTInfo);
7109 result = S_OK;
7111 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
7112 (This->TypeAttr.typekind == TKIND_DISPATCH))
7114 HREFTYPE href_dispatch = hRefType;
7115 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7116 } else {
7117 TLBRefType *ref_type;
7118 UINT i;
7120 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7122 if (This->pTypeLib->typeinfos[i]->hreftype == hRefType)
7124 result = S_OK;
7125 *ppTInfo = (ITypeInfo*)This->pTypeLib->typeinfos[i];
7126 ITypeInfo_AddRef(*ppTInfo);
7127 goto end;
7131 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7133 if(ref_type->reference == hRefType)
7134 break;
7136 if(&ref_type->entry == &This->pTypeLib->ref_list)
7138 FIXME("Can't find pRefType for ref %x\n", hRefType);
7139 goto end;
7141 if(hRefType != -1) {
7142 ITypeLib *pTLib = NULL;
7144 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7145 UINT Index;
7146 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7147 } else {
7148 if(ref_type->pImpTLInfo->pImpTypeLib) {
7149 TRACE("typeinfo in imported typelib that is already loaded\n");
7150 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7151 ITypeLib_AddRef(pTLib);
7152 result = S_OK;
7153 } else {
7154 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7155 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
7156 ref_type->pImpTLInfo->wVersionMajor,
7157 ref_type->pImpTLInfo->wVersionMinor,
7158 ref_type->pImpTLInfo->lcid,
7159 &pTLib);
7161 if(FAILED(result)) {
7162 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
7163 result=LoadTypeLib(libnam, &pTLib);
7164 SysFreeString(libnam);
7166 if(SUCCEEDED(result)) {
7167 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7168 ITypeLib_AddRef(pTLib);
7172 if(SUCCEEDED(result)) {
7173 if(ref_type->index == TLB_REF_USE_GUID)
7174 result = ITypeLib_GetTypeInfoOfGuid(pTLib, &ref_type->guid, ppTInfo);
7175 else
7176 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7178 if (pTLib != NULL)
7179 ITypeLib_Release(pTLib);
7183 end:
7184 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7185 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7186 return result;
7189 /* ITypeInfo::AddressOfMember
7191 * Retrieves the addresses of static functions or variables, such as those
7192 * defined in a DLL.
7194 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7195 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7197 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7198 HRESULT hr;
7199 BSTR dll, entry;
7200 WORD ordinal;
7201 HMODULE module;
7203 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7205 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7206 if (FAILED(hr))
7207 return hr;
7209 module = LoadLibraryW(dll);
7210 if (!module)
7212 ERR("couldn't load %s\n", debugstr_w(dll));
7213 SysFreeString(dll);
7214 SysFreeString(entry);
7215 return STG_E_FILENOTFOUND;
7217 /* FIXME: store library somewhere where we can free it */
7219 if (entry)
7221 LPSTR entryA;
7222 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7223 entryA = heap_alloc(len);
7224 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7226 *ppv = GetProcAddress(module, entryA);
7227 if (!*ppv)
7228 ERR("function not found %s\n", debugstr_a(entryA));
7230 heap_free(entryA);
7232 else
7234 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7235 if (!*ppv)
7236 ERR("function not found %d\n", ordinal);
7239 SysFreeString(dll);
7240 SysFreeString(entry);
7242 if (!*ppv)
7243 return TYPE_E_DLLFUNCTIONNOTFOUND;
7245 return S_OK;
7248 /* ITypeInfo::CreateInstance
7250 * Creates a new instance of a type that describes a component object class
7251 * (coclass).
7253 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7254 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7256 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7257 HRESULT hr;
7258 TYPEATTR *pTA;
7260 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7262 *ppvObj = NULL;
7264 if(pOuterUnk)
7266 WARN("Not able to aggregate\n");
7267 return CLASS_E_NOAGGREGATION;
7270 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7271 if(FAILED(hr)) return hr;
7273 if(pTA->typekind != TKIND_COCLASS)
7275 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7276 hr = E_INVALIDARG;
7277 goto end;
7280 hr = S_FALSE;
7281 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7283 IUnknown *pUnk;
7284 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7285 TRACE("GetActiveObject rets %08x\n", hr);
7286 if(hr == S_OK)
7288 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7289 IUnknown_Release(pUnk);
7293 if(hr != S_OK)
7294 hr = CoCreateInstance(&pTA->guid, NULL,
7295 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7296 riid, ppvObj);
7298 end:
7299 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7300 return hr;
7303 /* ITypeInfo::GetMops
7305 * Retrieves marshalling information.
7307 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7308 BSTR *pBstrMops)
7310 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7311 FIXME("(%p %d) stub!\n", This, memid);
7312 *pBstrMops = NULL;
7313 return S_OK;
7316 /* ITypeInfo::GetContainingTypeLib
7318 * Retrieves the containing type library and the index of the type description
7319 * within that type library.
7321 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7322 ITypeLib * *ppTLib, UINT *pIndex)
7324 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7326 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7327 if (pIndex) {
7328 *pIndex=This->index;
7329 TRACE("returning pIndex=%d\n", *pIndex);
7332 if (ppTLib) {
7333 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7334 ITypeLib_AddRef(*ppTLib);
7335 TRACE("returning ppTLib=%p\n", *ppTLib);
7338 return S_OK;
7341 /* ITypeInfo::ReleaseTypeAttr
7343 * Releases a TYPEATTR previously returned by GetTypeAttr.
7346 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7347 TYPEATTR* pTypeAttr)
7349 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7350 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7351 heap_free(pTypeAttr);
7354 /* ITypeInfo::ReleaseFuncDesc
7356 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7358 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7359 ITypeInfo2 *iface,
7360 FUNCDESC *pFuncDesc)
7362 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7363 SHORT i;
7365 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7367 for (i = 0; i < pFuncDesc->cParams; i++)
7368 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7369 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7371 SysFreeString((BSTR)pFuncDesc);
7374 /* ITypeInfo::ReleaseVarDesc
7376 * Releases a VARDESC previously returned by GetVarDesc.
7378 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7379 VARDESC *pVarDesc)
7381 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7382 TRACE("(%p)->(%p)\n", This, pVarDesc);
7384 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7385 if (pVarDesc->varkind == VAR_CONST)
7386 VariantClear(pVarDesc->u.lpvarValue);
7387 SysFreeString((BSTR)pVarDesc);
7390 /* ITypeInfo2::GetTypeKind
7392 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7395 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7396 TYPEKIND *pTypeKind)
7398 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7399 *pTypeKind=This->TypeAttr.typekind;
7400 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7401 return S_OK;
7404 /* ITypeInfo2::GetTypeFlags
7406 * Returns the type flags without any allocations. This returns a DWORD type
7407 * flag, which expands the type flags without growing the TYPEATTR (type
7408 * attribute).
7411 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7413 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7414 *pTypeFlags=This->TypeAttr.wTypeFlags;
7415 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7416 return S_OK;
7419 /* ITypeInfo2::GetFuncIndexOfMemId
7420 * Binds to a specific member based on a known DISPID, where the member name
7421 * is not known (for example, when binding to a default member).
7424 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7425 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7427 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7428 UINT fdc;
7429 HRESULT result;
7431 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7432 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7433 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7434 break;
7436 if(fdc < This->TypeAttr.cFuncs) {
7437 *pFuncIndex = fdc;
7438 result = S_OK;
7439 } else
7440 result = TYPE_E_ELEMENTNOTFOUND;
7442 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7443 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7444 return result;
7447 /* TypeInfo2::GetVarIndexOfMemId
7449 * Binds to a specific member based on a known DISPID, where the member name
7450 * is not known (for example, when binding to a default member).
7453 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7454 MEMBERID memid, UINT *pVarIndex)
7456 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7457 TLBVarDesc *pVarInfo;
7459 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7461 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7462 if(!pVarInfo)
7463 return TYPE_E_ELEMENTNOTFOUND;
7465 *pVarIndex = (pVarInfo - This->vardescs);
7467 return S_OK;
7470 /* ITypeInfo2::GetCustData
7472 * Gets the custom data
7474 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7475 ITypeInfo2 * iface,
7476 REFGUID guid,
7477 VARIANT *pVarVal)
7479 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7480 TLBCustData *pCData;
7482 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7484 if(!guid || !pVarVal)
7485 return E_INVALIDARG;
7487 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7489 VariantInit( pVarVal);
7490 if (pCData)
7491 VariantCopy( pVarVal, &pCData->data);
7492 else
7493 VariantClear( pVarVal );
7494 return S_OK;
7497 /* ITypeInfo2::GetFuncCustData
7499 * Gets the custom data
7501 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7502 ITypeInfo2 * iface,
7503 UINT index,
7504 REFGUID guid,
7505 VARIANT *pVarVal)
7507 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7508 TLBCustData *pCData;
7509 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7511 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7513 if(index >= This->TypeAttr.cFuncs)
7514 return TYPE_E_ELEMENTNOTFOUND;
7516 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7517 if(!pCData)
7518 return TYPE_E_ELEMENTNOTFOUND;
7520 VariantInit(pVarVal);
7521 VariantCopy(pVarVal, &pCData->data);
7523 return S_OK;
7526 /* ITypeInfo2::GetParamCustData
7528 * Gets the custom data
7530 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7531 ITypeInfo2 * iface,
7532 UINT indexFunc,
7533 UINT indexParam,
7534 REFGUID guid,
7535 VARIANT *pVarVal)
7537 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7538 TLBCustData *pCData;
7539 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7541 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7542 debugstr_guid(guid), pVarVal);
7544 if(indexFunc >= This->TypeAttr.cFuncs)
7545 return TYPE_E_ELEMENTNOTFOUND;
7547 if(indexParam >= pFDesc->funcdesc.cParams)
7548 return TYPE_E_ELEMENTNOTFOUND;
7550 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7551 if(!pCData)
7552 return TYPE_E_ELEMENTNOTFOUND;
7554 VariantInit(pVarVal);
7555 VariantCopy(pVarVal, &pCData->data);
7557 return S_OK;
7560 /* ITypeInfo2::GetVarCustData
7562 * Gets the custom data
7564 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7565 ITypeInfo2 * iface,
7566 UINT index,
7567 REFGUID guid,
7568 VARIANT *pVarVal)
7570 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7571 TLBCustData *pCData;
7572 TLBVarDesc *pVDesc = &This->vardescs[index];
7574 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7576 if(index >= This->TypeAttr.cVars)
7577 return TYPE_E_ELEMENTNOTFOUND;
7579 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7580 if(!pCData)
7581 return TYPE_E_ELEMENTNOTFOUND;
7583 VariantInit(pVarVal);
7584 VariantCopy(pVarVal, &pCData->data);
7586 return S_OK;
7589 /* ITypeInfo2::GetImplCustData
7591 * Gets the custom data
7593 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7594 ITypeInfo2 * iface,
7595 UINT index,
7596 REFGUID guid,
7597 VARIANT *pVarVal)
7599 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7600 TLBCustData *pCData;
7601 TLBImplType *pRDesc = &This->impltypes[index];
7603 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7605 if(index >= This->TypeAttr.cImplTypes)
7606 return TYPE_E_ELEMENTNOTFOUND;
7608 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7609 if(!pCData)
7610 return TYPE_E_ELEMENTNOTFOUND;
7612 VariantInit(pVarVal);
7613 VariantCopy(pVarVal, &pCData->data);
7615 return S_OK;
7618 /* ITypeInfo2::GetDocumentation2
7620 * Retrieves the documentation string, the complete Help file name and path,
7621 * the localization context to use, and the context ID for the library Help
7622 * topic in the Help file.
7625 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7626 ITypeInfo2 * iface,
7627 MEMBERID memid,
7628 LCID lcid,
7629 BSTR *pbstrHelpString,
7630 DWORD *pdwHelpStringContext,
7631 BSTR *pbstrHelpStringDll)
7633 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7634 const TLBFuncDesc *pFDesc;
7635 const TLBVarDesc *pVDesc;
7636 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7637 "HelpStringContext(%p) HelpStringDll(%p)\n",
7638 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7639 pbstrHelpStringDll );
7640 /* the help string should be obtained from the helpstringdll,
7641 * using the _DLLGetDocumentation function, based on the supplied
7642 * lcid. Nice to do sometime...
7644 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7645 if(pbstrHelpString)
7646 *pbstrHelpString=SysAllocString(This->Name);
7647 if(pdwHelpStringContext)
7648 *pdwHelpStringContext=This->dwHelpStringContext;
7649 if(pbstrHelpStringDll)
7650 *pbstrHelpStringDll=
7651 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7652 return S_OK;
7653 }else {/* for a member */
7654 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7655 if(pFDesc){
7656 if(pbstrHelpString)
7657 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7658 if(pdwHelpStringContext)
7659 *pdwHelpStringContext=pFDesc->HelpStringContext;
7660 if(pbstrHelpStringDll)
7661 *pbstrHelpStringDll=
7662 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7663 return S_OK;
7665 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7666 if(pVDesc){
7667 if(pbstrHelpString)
7668 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7669 if(pdwHelpStringContext)
7670 *pdwHelpStringContext=pVDesc->HelpStringContext;
7671 if(pbstrHelpStringDll)
7672 *pbstrHelpStringDll=
7673 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7674 return S_OK;
7677 return TYPE_E_ELEMENTNOTFOUND;
7680 /* ITypeInfo2::GetAllCustData
7682 * Gets all custom data items for the Type info.
7685 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7686 ITypeInfo2 * iface,
7687 CUSTDATA *pCustData)
7689 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7691 TRACE("%p %p\n", This, pCustData);
7693 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
7696 /* ITypeInfo2::GetAllFuncCustData
7698 * Gets all custom data items for the specified Function
7701 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7702 ITypeInfo2 * iface,
7703 UINT index,
7704 CUSTDATA *pCustData)
7706 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7707 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7709 TRACE("%p %u %p\n", This, index, pCustData);
7711 if(index >= This->TypeAttr.cFuncs)
7712 return TYPE_E_ELEMENTNOTFOUND;
7714 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
7717 /* ITypeInfo2::GetAllParamCustData
7719 * Gets all custom data items for the Functions
7722 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7723 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7725 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7726 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7728 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
7730 if(indexFunc >= This->TypeAttr.cFuncs)
7731 return TYPE_E_ELEMENTNOTFOUND;
7733 if(indexParam >= pFDesc->funcdesc.cParams)
7734 return TYPE_E_ELEMENTNOTFOUND;
7736 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
7739 /* ITypeInfo2::GetAllVarCustData
7741 * Gets all custom data items for the specified Variable
7744 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7745 UINT index, CUSTDATA *pCustData)
7747 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7748 TLBVarDesc * pVDesc = &This->vardescs[index];
7750 TRACE("%p %u %p\n", This, index, pCustData);
7752 if(index >= This->TypeAttr.cVars)
7753 return TYPE_E_ELEMENTNOTFOUND;
7755 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
7758 /* ITypeInfo2::GetAllImplCustData
7760 * Gets all custom data items for the specified implementation type
7763 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7764 ITypeInfo2 * iface,
7765 UINT index,
7766 CUSTDATA *pCustData)
7768 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7769 TLBImplType *pRDesc = &This->impltypes[index];
7771 TRACE("%p %u %p\n", This, index, pCustData);
7773 if(index >= This->TypeAttr.cImplTypes)
7774 return TYPE_E_ELEMENTNOTFOUND;
7776 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
7779 static const ITypeInfo2Vtbl tinfvt =
7782 ITypeInfo_fnQueryInterface,
7783 ITypeInfo_fnAddRef,
7784 ITypeInfo_fnRelease,
7786 ITypeInfo_fnGetTypeAttr,
7787 ITypeInfo_fnGetTypeComp,
7788 ITypeInfo_fnGetFuncDesc,
7789 ITypeInfo_fnGetVarDesc,
7790 ITypeInfo_fnGetNames,
7791 ITypeInfo_fnGetRefTypeOfImplType,
7792 ITypeInfo_fnGetImplTypeFlags,
7793 ITypeInfo_fnGetIDsOfNames,
7794 ITypeInfo_fnInvoke,
7795 ITypeInfo_fnGetDocumentation,
7796 ITypeInfo_fnGetDllEntry,
7797 ITypeInfo_fnGetRefTypeInfo,
7798 ITypeInfo_fnAddressOfMember,
7799 ITypeInfo_fnCreateInstance,
7800 ITypeInfo_fnGetMops,
7801 ITypeInfo_fnGetContainingTypeLib,
7802 ITypeInfo_fnReleaseTypeAttr,
7803 ITypeInfo_fnReleaseFuncDesc,
7804 ITypeInfo_fnReleaseVarDesc,
7806 ITypeInfo2_fnGetTypeKind,
7807 ITypeInfo2_fnGetTypeFlags,
7808 ITypeInfo2_fnGetFuncIndexOfMemId,
7809 ITypeInfo2_fnGetVarIndexOfMemId,
7810 ITypeInfo2_fnGetCustData,
7811 ITypeInfo2_fnGetFuncCustData,
7812 ITypeInfo2_fnGetParamCustData,
7813 ITypeInfo2_fnGetVarCustData,
7814 ITypeInfo2_fnGetImplTypeCustData,
7815 ITypeInfo2_fnGetDocumentation2,
7816 ITypeInfo2_fnGetAllCustData,
7817 ITypeInfo2_fnGetAllFuncCustData,
7818 ITypeInfo2_fnGetAllParamCustData,
7819 ITypeInfo2_fnGetAllVarCustData,
7820 ITypeInfo2_fnGetAllImplTypeCustData,
7823 /******************************************************************************
7824 * CreateDispTypeInfo [OLEAUT32.31]
7826 * Build type information for an object so it can be called through an
7827 * IDispatch interface.
7829 * RETURNS
7830 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7831 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7833 * NOTES
7834 * This call allows an objects methods to be accessed through IDispatch, by
7835 * building an ITypeInfo object that IDispatch can use to call through.
7837 HRESULT WINAPI CreateDispTypeInfo(
7838 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7839 LCID lcid, /* [I] Locale Id */
7840 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7842 ITypeInfoImpl *pTIClass, *pTIIface;
7843 ITypeLibImpl *pTypeLibImpl;
7844 unsigned int param, func;
7845 TLBFuncDesc *pFuncDesc;
7846 TLBRefType *ref;
7848 TRACE("\n");
7849 pTypeLibImpl = TypeLibImpl_Constructor();
7850 if (!pTypeLibImpl) return E_FAIL;
7852 pTypeLibImpl->TypeInfoCount = 2;
7853 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
7855 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
7856 pTIIface->pTypeLib = pTypeLibImpl;
7857 pTIIface->index = 0;
7858 pTIIface->Name = NULL;
7859 pTIIface->dwHelpContext = -1;
7860 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7861 pTIIface->TypeAttr.lcid = lcid;
7862 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7863 pTIIface->TypeAttr.wMajorVerNum = 0;
7864 pTIIface->TypeAttr.wMinorVerNum = 0;
7865 pTIIface->TypeAttr.cbAlignment = 2;
7866 pTIIface->TypeAttr.cbSizeInstance = -1;
7867 pTIIface->TypeAttr.cbSizeVft = -1;
7868 pTIIface->TypeAttr.cFuncs = 0;
7869 pTIIface->TypeAttr.cImplTypes = 0;
7870 pTIIface->TypeAttr.cVars = 0;
7871 pTIIface->TypeAttr.wTypeFlags = 0;
7873 pTIIface->funcdescs = TLBFuncDesc_Constructor(pidata->cMembers);
7874 pFuncDesc = pTIIface->funcdescs;
7875 for(func = 0; func < pidata->cMembers; func++) {
7876 METHODDATA *md = pidata->pmethdata + func;
7877 pFuncDesc->Name = SysAllocString(md->szName);
7878 pFuncDesc->funcdesc.memid = md->dispid;
7879 pFuncDesc->funcdesc.lprgscode = NULL;
7880 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
7881 pFuncDesc->funcdesc.invkind = md->wFlags;
7882 pFuncDesc->funcdesc.callconv = md->cc;
7883 pFuncDesc->funcdesc.cParams = md->cArgs;
7884 pFuncDesc->funcdesc.cParamsOpt = 0;
7885 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
7886 pFuncDesc->funcdesc.cScodes = 0;
7887 pFuncDesc->funcdesc.wFuncFlags = 0;
7888 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7889 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7890 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7891 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7892 md->cArgs * sizeof(ELEMDESC));
7893 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
7894 for(param = 0; param < md->cArgs; param++) {
7895 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7896 pFuncDesc->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7898 pFuncDesc->helpcontext = 0;
7899 pFuncDesc->HelpStringContext = 0;
7900 pFuncDesc->HelpString = NULL;
7901 pFuncDesc->Entry = NULL;
7902 list_init(&pFuncDesc->custdata_list);
7903 pTIIface->TypeAttr.cFuncs++;
7904 ++pFuncDesc;
7907 dump_TypeInfo(pTIIface);
7909 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
7910 pTIClass->pTypeLib = pTypeLibImpl;
7911 pTIClass->index = 1;
7912 pTIClass->Name = NULL;
7913 pTIClass->dwHelpContext = -1;
7914 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7915 pTIClass->TypeAttr.lcid = lcid;
7916 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7917 pTIClass->TypeAttr.wMajorVerNum = 0;
7918 pTIClass->TypeAttr.wMinorVerNum = 0;
7919 pTIClass->TypeAttr.cbAlignment = 2;
7920 pTIClass->TypeAttr.cbSizeInstance = -1;
7921 pTIClass->TypeAttr.cbSizeVft = -1;
7922 pTIClass->TypeAttr.cFuncs = 0;
7923 pTIClass->TypeAttr.cImplTypes = 1;
7924 pTIClass->TypeAttr.cVars = 0;
7925 pTIClass->TypeAttr.wTypeFlags = 0;
7927 pTIClass->impltypes = TLBImplType_Constructor(1);
7929 ref = heap_alloc_zero(sizeof(*ref));
7930 ref->pImpTLInfo = TLB_REF_INTERNAL;
7931 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7933 dump_TypeInfo(pTIClass);
7935 *pptinfo = (ITypeInfo*)pTIClass;
7937 ITypeInfo_AddRef(*pptinfo);
7938 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
7940 return S_OK;
7944 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7946 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7948 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7951 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7953 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7955 return ITypeInfo_AddRef((ITypeInfo *)This);
7958 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7960 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7962 return ITypeInfo_Release((ITypeInfo *)This);
7965 static HRESULT WINAPI ITypeComp_fnBind(
7966 ITypeComp * iface,
7967 OLECHAR * szName,
7968 ULONG lHash,
7969 WORD wFlags,
7970 ITypeInfo ** ppTInfo,
7971 DESCKIND * pDescKind,
7972 BINDPTR * pBindPtr)
7974 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7975 const TLBFuncDesc *pFDesc;
7976 const TLBVarDesc *pVDesc;
7977 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7978 UINT fdc;
7980 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7982 *pDescKind = DESCKIND_NONE;
7983 pBindPtr->lpfuncdesc = NULL;
7984 *ppTInfo = NULL;
7986 for(fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7987 pFDesc = &This->funcdescs[fdc];
7988 if (!strcmpiW(pFDesc->Name, szName)) {
7989 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7990 break;
7991 else
7992 /* name found, but wrong flags */
7993 hr = TYPE_E_TYPEMISMATCH;
7997 if (fdc < This->TypeAttr.cFuncs)
7999 HRESULT hr = TLB_AllocAndInitFuncDesc(
8000 &pFDesc->funcdesc,
8001 &pBindPtr->lpfuncdesc,
8002 This->TypeAttr.typekind == TKIND_DISPATCH);
8003 if (FAILED(hr))
8004 return hr;
8005 *pDescKind = DESCKIND_FUNCDESC;
8006 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8007 ITypeInfo_AddRef(*ppTInfo);
8008 return S_OK;
8009 } else {
8010 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, szName);
8011 if(pVDesc){
8012 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8013 if (FAILED(hr))
8014 return hr;
8015 *pDescKind = DESCKIND_VARDESC;
8016 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8017 ITypeInfo_AddRef(*ppTInfo);
8018 return S_OK;
8021 /* FIXME: search each inherited interface, not just the first */
8022 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8023 /* recursive search */
8024 ITypeInfo *pTInfo;
8025 ITypeComp *pTComp;
8026 HRESULT hr;
8027 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8028 if (SUCCEEDED(hr))
8030 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8031 ITypeInfo_Release(pTInfo);
8033 if (SUCCEEDED(hr))
8035 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8036 ITypeComp_Release(pTComp);
8037 return hr;
8039 WARN("Could not search inherited interface!\n");
8041 if (hr == DISP_E_MEMBERNOTFOUND)
8042 hr = S_OK;
8043 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8044 return hr;
8047 static HRESULT WINAPI ITypeComp_fnBindType(
8048 ITypeComp * iface,
8049 OLECHAR * szName,
8050 ULONG lHash,
8051 ITypeInfo ** ppTInfo,
8052 ITypeComp ** ppTComp)
8054 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8056 /* strange behaviour (does nothing) but like the
8057 * original */
8059 if (!ppTInfo || !ppTComp)
8060 return E_POINTER;
8062 *ppTInfo = NULL;
8063 *ppTComp = NULL;
8065 return S_OK;
8068 static const ITypeCompVtbl tcompvt =
8071 ITypeComp_fnQueryInterface,
8072 ITypeComp_fnAddRef,
8073 ITypeComp_fnRelease,
8075 ITypeComp_fnBind,
8076 ITypeComp_fnBindType
8079 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8080 REFIID riid, void **object)
8082 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8084 return ITypeLib2_QueryInterface((ITypeLib2*)This, riid, object);
8087 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8089 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8091 return ITypeLib2_AddRef((ITypeLib2*)This);
8094 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8096 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8098 return ITypeLib2_Release((ITypeLib2*)This);
8101 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8102 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8104 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8105 FIXME("%p %s %d %p - stub\n", This, wine_dbgstr_w(name), kind, ctinfo);
8106 return E_NOTIMPL;
8109 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8110 LPOLESTR name)
8112 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8114 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8116 if (!name)
8117 return E_INVALIDARG;
8119 SysFreeString(This->Name);
8120 This->Name = SysAllocString(name);
8122 return S_OK;
8125 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8126 WORD majorVerNum, WORD minorVerNum)
8128 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8130 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8132 This->LibAttr.wMajorVerNum = majorVerNum;
8133 This->LibAttr.wMinorVerNum = minorVerNum;
8135 return S_OK;
8138 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8139 REFGUID guid)
8141 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8143 TRACE("%p %s\n", This, debugstr_guid(guid));
8145 memcpy(&This->LibAttr.guid, guid, sizeof(GUID));
8147 return S_OK;
8150 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8151 LPOLESTR doc)
8153 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8155 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8157 if (!doc)
8158 return E_INVALIDARG;
8160 SysFreeString(This->DocString);
8161 This->DocString = SysAllocString(doc);
8163 return S_OK;
8166 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8167 LPOLESTR helpFileName)
8169 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8171 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8173 if (!helpFileName)
8174 return E_INVALIDARG;
8176 SysFreeString(This->HelpFile);
8177 This->HelpFile = SysAllocString(helpFileName);
8179 return S_OK;
8182 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8183 DWORD helpContext)
8185 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8187 TRACE("%p %d\n", This, helpContext);
8189 This->dwHelpContext = helpContext;
8191 return S_OK;
8194 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8195 LCID lcid)
8197 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8199 TRACE("%p %x\n", This, lcid);
8201 This->LibAttr.lcid = lcid;
8203 return S_OK;
8206 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8207 UINT libFlags)
8209 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8211 TRACE("%p %x\n", This, libFlags);
8213 This->LibAttr.wLibFlags = libFlags;
8215 return S_OK;
8218 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
8220 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8221 FIXME("%p - stub\n", This);
8222 return E_NOTIMPL;
8225 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
8226 LPOLESTR name)
8228 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8229 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
8230 return E_NOTIMPL;
8233 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
8234 REFGUID guid, VARIANT *varVal)
8236 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8237 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
8238 return E_NOTIMPL;
8241 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
8242 ULONG helpStringContext)
8244 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8245 FIXME("%p %u - stub\n", This, helpStringContext);
8246 return E_NOTIMPL;
8249 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
8250 LPOLESTR filename)
8252 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8253 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
8255 if (!filename)
8256 return E_INVALIDARG;
8258 SysFreeString(This->HelpStringDll);
8259 This->HelpStringDll = SysAllocString(filename);
8261 return S_OK;
8264 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
8265 ICreateTypeLib2_fnQueryInterface,
8266 ICreateTypeLib2_fnAddRef,
8267 ICreateTypeLib2_fnRelease,
8268 ICreateTypeLib2_fnCreateTypeInfo,
8269 ICreateTypeLib2_fnSetName,
8270 ICreateTypeLib2_fnSetVersion,
8271 ICreateTypeLib2_fnSetGuid,
8272 ICreateTypeLib2_fnSetDocString,
8273 ICreateTypeLib2_fnSetHelpFileName,
8274 ICreateTypeLib2_fnSetHelpContext,
8275 ICreateTypeLib2_fnSetLcid,
8276 ICreateTypeLib2_fnSetLibFlags,
8277 ICreateTypeLib2_fnSaveAllChanges,
8278 ICreateTypeLib2_fnDeleteTypeInfo,
8279 ICreateTypeLib2_fnSetCustData,
8280 ICreateTypeLib2_fnSetHelpStringContext,
8281 ICreateTypeLib2_fnSetHelpStringDll
8284 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
8285 REFIID riid, void **object)
8287 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8289 return ITypeInfo2_QueryInterface((ITypeInfo2*)This, riid, object);
8292 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
8294 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8296 return ITypeInfo2_AddRef((ITypeInfo2*)This);
8299 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
8301 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8303 return ITypeInfo2_Release((ITypeInfo2*)This);
8306 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
8307 REFGUID guid)
8309 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8310 FIXME("%p %s - stub\n", This, debugstr_guid(guid));
8311 return E_NOTIMPL;
8314 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
8315 UINT typeFlags)
8317 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8318 FIXME("%p %x - stub\n", This, typeFlags);
8319 return E_NOTIMPL;
8322 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
8323 LPOLESTR strDoc)
8325 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8326 FIXME("%p %s - stub\n", This, wine_dbgstr_w(strDoc));
8327 return E_NOTIMPL;
8330 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
8331 DWORD helpContext)
8333 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8334 FIXME("%p %d - stub\n", This, helpContext);
8335 return E_NOTIMPL;
8338 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
8339 WORD majorVerNum, WORD minorVerNum)
8341 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8342 FIXME("%p %d %d - stub\n", This, majorVerNum, minorVerNum);
8343 return E_NOTIMPL;
8346 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
8347 ITypeInfo *typeInfo, HREFTYPE *refType)
8349 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8350 FIXME("%p %p %p - stub\n", This, typeInfo, refType);
8351 return E_NOTIMPL;
8354 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
8355 UINT index, FUNCDESC *funcDesc)
8357 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8358 FIXME("%p %u %p - stub\n", This, index, funcDesc);
8359 return E_NOTIMPL;
8362 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
8363 UINT index, HREFTYPE refType)
8365 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8366 FIXME("%p %u %d - stub\n", This, index, refType);
8367 return E_NOTIMPL;
8370 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
8371 UINT index, INT implTypeFlags)
8373 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8374 FIXME("%p %u %x - stub\n", This, index, implTypeFlags);
8375 return E_NOTIMPL;
8378 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
8379 WORD alignment)
8381 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8382 FIXME("%p %d - stub\n", This, alignment);
8383 return E_NOTIMPL;
8386 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
8387 LPOLESTR schema)
8389 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8390 FIXME("%p %s - stub\n", This, wine_dbgstr_w(schema));
8391 return E_NOTIMPL;
8394 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
8395 UINT index, VARDESC *varDesc)
8397 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8398 FIXME("%p %u %p - stub\n", This, index, varDesc);
8399 return E_NOTIMPL;
8402 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
8403 UINT index, LPOLESTR *names, UINT numNames)
8405 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8406 FIXME("%p %u %p %u - stub\n", This, index, names, numNames);
8407 return E_NOTIMPL;
8410 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
8411 UINT index, LPOLESTR name)
8413 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8414 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(name));
8415 return E_NOTIMPL;
8418 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
8419 TYPEDESC *tdescAlias)
8421 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8422 FIXME("%p %p - stub\n", This, tdescAlias);
8423 return E_NOTIMPL;
8426 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
8427 UINT index, LPOLESTR dllName, LPOLESTR procName)
8429 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8430 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
8431 return E_NOTIMPL;
8434 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
8435 UINT index, LPOLESTR docString)
8437 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8438 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
8439 return E_NOTIMPL;
8442 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
8443 UINT index, LPOLESTR docString)
8445 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8446 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
8447 return E_NOTIMPL;
8450 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
8451 UINT index, DWORD helpContext)
8453 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8454 FIXME("%p %u %d - stub\n", This, index, helpContext);
8455 return E_NOTIMPL;
8458 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
8459 UINT index, DWORD helpContext)
8461 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8462 FIXME("%p %u %d - stub\n", This, index, helpContext);
8463 return E_NOTIMPL;
8466 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
8467 UINT index, BSTR bstrMops)
8469 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8470 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
8471 return E_NOTIMPL;
8474 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
8475 IDLDESC *idlDesc)
8477 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8478 FIXME("%p %p - stub\n", This, idlDesc);
8479 return E_NOTIMPL;
8482 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
8484 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8485 FIXME("%p - stub\n", This);
8486 return E_NOTIMPL;
8489 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
8490 UINT index)
8492 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8493 FIXME("%p %u - stub\n", This, index);
8494 return E_NOTIMPL;
8497 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
8498 MEMBERID memid, INVOKEKIND invKind)
8500 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8501 FIXME("%p %x %d - stub\n", This, memid, invKind);
8502 return E_NOTIMPL;
8505 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
8506 UINT index)
8508 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8509 FIXME("%p %u - stub\n", This, index);
8510 return E_NOTIMPL;
8513 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
8514 MEMBERID memid)
8516 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8517 FIXME("%p %x - stub\n", This, memid);
8518 return E_NOTIMPL;
8521 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
8522 UINT index)
8524 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8525 FIXME("%p %u - stub\n", This, index);
8526 return E_NOTIMPL;
8529 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
8530 REFGUID guid, VARIANT *varVal)
8532 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8533 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
8534 return E_NOTIMPL;
8537 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
8538 UINT index, REFGUID guid, VARIANT *varVal)
8540 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8541 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
8542 return E_NOTIMPL;
8545 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
8546 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
8548 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8549 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
8550 return E_NOTIMPL;
8553 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
8554 UINT index, REFGUID guid, VARIANT *varVal)
8556 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8557 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
8558 return E_NOTIMPL;
8561 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
8562 UINT index, REFGUID guid, VARIANT *varVal)
8564 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8565 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
8566 return E_NOTIMPL;
8569 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
8570 ULONG helpStringContext)
8572 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8573 FIXME("%p %u - stub\n", This, helpStringContext);
8574 return E_NOTIMPL;
8577 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
8578 UINT index, ULONG helpStringContext)
8580 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8581 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
8582 return E_NOTIMPL;
8585 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
8586 UINT index, ULONG helpStringContext)
8588 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8589 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
8590 return E_NOTIMPL;
8593 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
8595 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8596 FIXME("%p - stub\n", This);
8597 return E_NOTIMPL;
8600 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
8601 LPOLESTR name)
8603 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8604 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
8605 return E_NOTIMPL;
8608 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
8609 ICreateTypeInfo2_fnQueryInterface,
8610 ICreateTypeInfo2_fnAddRef,
8611 ICreateTypeInfo2_fnRelease,
8612 ICreateTypeInfo2_fnSetGuid,
8613 ICreateTypeInfo2_fnSetTypeFlags,
8614 ICreateTypeInfo2_fnSetDocString,
8615 ICreateTypeInfo2_fnSetHelpContext,
8616 ICreateTypeInfo2_fnSetVersion,
8617 ICreateTypeInfo2_fnAddRefTypeInfo,
8618 ICreateTypeInfo2_fnAddFuncDesc,
8619 ICreateTypeInfo2_fnAddImplType,
8620 ICreateTypeInfo2_fnSetImplTypeFlags,
8621 ICreateTypeInfo2_fnSetAlignment,
8622 ICreateTypeInfo2_fnSetSchema,
8623 ICreateTypeInfo2_fnAddVarDesc,
8624 ICreateTypeInfo2_fnSetFuncAndParamNames,
8625 ICreateTypeInfo2_fnSetVarName,
8626 ICreateTypeInfo2_fnSetTypeDescAlias,
8627 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
8628 ICreateTypeInfo2_fnSetFuncDocString,
8629 ICreateTypeInfo2_fnSetVarDocString,
8630 ICreateTypeInfo2_fnSetFuncHelpContext,
8631 ICreateTypeInfo2_fnSetVarHelpContext,
8632 ICreateTypeInfo2_fnSetMops,
8633 ICreateTypeInfo2_fnSetTypeIdldesc,
8634 ICreateTypeInfo2_fnLayOut,
8635 ICreateTypeInfo2_fnDeleteFuncDesc,
8636 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
8637 ICreateTypeInfo2_fnDeleteVarDesc,
8638 ICreateTypeInfo2_fnDeleteVarDescByMemId,
8639 ICreateTypeInfo2_fnDeleteImplType,
8640 ICreateTypeInfo2_fnSetCustData,
8641 ICreateTypeInfo2_fnSetFuncCustData,
8642 ICreateTypeInfo2_fnSetParamCustData,
8643 ICreateTypeInfo2_fnSetVarCustData,
8644 ICreateTypeInfo2_fnSetImplTypeCustData,
8645 ICreateTypeInfo2_fnSetHelpStringContext,
8646 ICreateTypeInfo2_fnSetFuncHelpStringContext,
8647 ICreateTypeInfo2_fnSetVarHelpStringContext,
8648 ICreateTypeInfo2_fnInvalidate,
8649 ICreateTypeInfo2_fnSetName