oleaut32: Pull TLIBATTR struct contents out.
[wine.git] / dlls / oleaut32 / typelib.c
blobe28f2c15ca61442b3c0eefad2f4aa3daad19f513
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 typedef struct tagTLBString {
986 BSTR str;
987 UINT offset;
988 struct list entry;
989 } TLBString;
991 /* internal ITypeLib data */
992 typedef struct tagITypeLibImpl
994 ITypeLib2 ITypeLib2_iface;
995 ITypeComp ITypeComp_iface;
996 ICreateTypeLib2 ICreateTypeLib2_iface;
997 LONG ref;
998 GUID guid;
999 LCID lcid;
1000 SYSKIND syskind;
1001 WORD ver_major;
1002 WORD ver_minor;
1003 WORD libflags;
1004 LCID set_lcid;
1006 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1007 * exported to the application as a UNICODE string.
1009 struct list string_list;
1010 struct list name_list;
1012 const TLBString *Name;
1013 const TLBString *DocString;
1014 const TLBString *HelpFile;
1015 const TLBString *HelpStringDll;
1016 DWORD dwHelpContext;
1017 int TypeInfoCount; /* nr of typeinfo's in librarry */
1018 struct tagITypeInfoImpl **typeinfos;
1019 struct list custdata_list;
1020 struct list implib_list;
1021 int ctTypeDesc; /* number of items in type desc array */
1022 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1023 library. Only used while reading MSFT
1024 typelibs */
1025 struct list ref_list; /* list of ref types in this typelib */
1026 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1029 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1030 struct list entry;
1031 WCHAR *path;
1032 INT index;
1033 } ITypeLibImpl;
1035 static const ITypeLib2Vtbl tlbvt;
1036 static const ITypeCompVtbl tlbtcvt;
1037 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1039 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1041 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1044 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1046 return impl_from_ITypeLib2((ITypeLib2*)iface);
1049 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1051 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1054 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1056 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1059 /* ITypeLib methods */
1060 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1061 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1063 /*======================= ITypeInfo implementation =======================*/
1065 /* data for referenced types */
1066 typedef struct tagTLBRefType
1068 INT index; /* Type index for internal ref or for external ref
1069 it the format is SLTG. -2 indicates to
1070 use guid */
1072 TYPEKIND tkind;
1073 GUID guid; /* guid of the referenced type */
1074 /* if index == TLB_REF_USE_GUID */
1076 HREFTYPE reference; /* The href of this ref */
1077 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1078 TLB_REF_INTERNAL for internal refs
1079 TLB_REF_NOT_FOUND for broken refs */
1081 struct list entry;
1082 } TLBRefType;
1084 #define TLB_REF_USE_GUID -2
1086 #define TLB_REF_INTERNAL (void*)-2
1087 #define TLB_REF_NOT_FOUND (void*)-1
1089 /* internal Parameter data */
1090 typedef struct tagTLBParDesc
1092 const TLBString *Name;
1093 struct list custdata_list;
1094 } TLBParDesc;
1096 /* internal Function data */
1097 typedef struct tagTLBFuncDesc
1099 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1100 const TLBString *Name; /* the name of this function */
1101 TLBParDesc *pParamDesc; /* array with param names and custom data */
1102 int helpcontext;
1103 int HelpStringContext;
1104 const TLBString *HelpString;
1105 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1106 struct list custdata_list;
1107 } TLBFuncDesc;
1109 /* internal Variable data */
1110 typedef struct tagTLBVarDesc
1112 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1113 const TLBString *Name; /* the name of this variable */
1114 int HelpContext;
1115 int HelpStringContext;
1116 const TLBString *HelpString;
1117 struct list custdata_list;
1118 } TLBVarDesc;
1120 /* internal implemented interface data */
1121 typedef struct tagTLBImplType
1123 HREFTYPE hRef; /* hRef of interface */
1124 int implflags; /* IMPLFLAG_*s */
1125 struct list custdata_list;
1126 } TLBImplType;
1128 /* internal TypeInfo data */
1129 typedef struct tagITypeInfoImpl
1131 ITypeInfo2 ITypeInfo2_iface;
1132 ITypeComp ITypeComp_iface;
1133 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1134 LONG ref;
1135 BOOL not_attached_to_typelib;
1136 BOOL needs_layout;
1137 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1138 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1139 int index; /* index in this typelib; */
1140 HREFTYPE hreftype; /* hreftype for app object binding */
1141 /* type libs seem to store the doc strings in ascii
1142 * so why should we do it in unicode?
1144 const TLBString *Name;
1145 const TLBString *DocString;
1146 const TLBString *DllName;
1147 const TLBString *Schema;
1148 DWORD dwHelpContext;
1149 DWORD dwHelpStringContext;
1151 /* functions */
1152 TLBFuncDesc *funcdescs;
1154 /* variables */
1155 TLBVarDesc *vardescs;
1157 /* Implemented Interfaces */
1158 TLBImplType *impltypes;
1160 struct list custdata_list;
1161 } ITypeInfoImpl;
1163 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1165 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1168 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1170 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1173 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1175 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1178 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1180 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1183 static const ITypeInfo2Vtbl tinfvt;
1184 static const ITypeCompVtbl tcompvt;
1185 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1187 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1188 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1190 typedef struct tagTLBContext
1192 unsigned int oStart; /* start of TLB in file */
1193 unsigned int pos; /* current pos */
1194 unsigned int length; /* total length */
1195 void *mapping; /* memory mapping */
1196 MSFT_SegDir * pTblDir;
1197 ITypeLibImpl* pLibInfo;
1198 } TLBContext;
1201 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1203 static inline BSTR TLB_get_bstr(const TLBString *str)
1205 return str != NULL ? str->str : NULL;
1208 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1210 if(!str)
1211 return 1;
1212 return memcmp(left, str->str, len);
1216 debug
1218 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1219 if (pTD->vt & VT_RESERVED)
1220 szVarType += strlen(strcpy(szVarType, "reserved | "));
1221 if (pTD->vt & VT_BYREF)
1222 szVarType += strlen(strcpy(szVarType, "ref to "));
1223 if (pTD->vt & VT_ARRAY)
1224 szVarType += strlen(strcpy(szVarType, "array of "));
1225 if (pTD->vt & VT_VECTOR)
1226 szVarType += strlen(strcpy(szVarType, "vector of "));
1227 switch(pTD->vt & VT_TYPEMASK) {
1228 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1229 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1230 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1231 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1232 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1233 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1234 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1235 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1236 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1237 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1238 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1239 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1240 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1241 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1242 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1243 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1244 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1245 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1246 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1247 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1248 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1249 pTD->u.hreftype); break;
1250 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1251 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1252 case VT_PTR: sprintf(szVarType, "ptr to ");
1253 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1254 break;
1255 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1256 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1257 break;
1258 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1259 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1260 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1261 break;
1263 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1267 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1268 char buf[200];
1269 USHORT flags = edesc->u.paramdesc.wParamFlags;
1270 dump_TypeDesc(&edesc->tdesc,buf);
1271 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1272 MESSAGE("\t\tu.paramdesc.wParamFlags");
1273 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1274 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1275 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1276 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1277 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1278 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1279 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1280 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1281 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1283 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1284 int i;
1285 MESSAGE("memid is %08x\n",funcdesc->memid);
1286 for (i=0;i<funcdesc->cParams;i++) {
1287 MESSAGE("Param %d:\n",i);
1288 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1290 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1291 switch (funcdesc->funckind) {
1292 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1293 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1294 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1295 case FUNC_STATIC: MESSAGE("static");break;
1296 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1297 default: MESSAGE("unknown");break;
1299 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1300 switch (funcdesc->invkind) {
1301 case INVOKE_FUNC: MESSAGE("func");break;
1302 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1303 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1304 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1306 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1307 switch (funcdesc->callconv) {
1308 case CC_CDECL: MESSAGE("cdecl");break;
1309 case CC_PASCAL: MESSAGE("pascal");break;
1310 case CC_STDCALL: MESSAGE("stdcall");break;
1311 case CC_SYSCALL: MESSAGE("syscall");break;
1312 default:break;
1314 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1315 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1316 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1318 MESSAGE("\telemdescFunc (return value type):\n");
1319 dump_ELEMDESC(&funcdesc->elemdescFunc);
1322 static const char * const typekind_desc[] =
1324 "TKIND_ENUM",
1325 "TKIND_RECORD",
1326 "TKIND_MODULE",
1327 "TKIND_INTERFACE",
1328 "TKIND_DISPATCH",
1329 "TKIND_COCLASS",
1330 "TKIND_ALIAS",
1331 "TKIND_UNION",
1332 "TKIND_MAX"
1335 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1337 int i;
1338 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1339 for (i=0;i<pfd->funcdesc.cParams;i++)
1340 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1343 dump_FUNCDESC(&(pfd->funcdesc));
1345 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1346 if(pfd->Entry == NULL)
1347 MESSAGE("\tentry: (null)\n");
1348 else if(pfd->Entry == (void*)-1)
1349 MESSAGE("\tentry: invalid\n");
1350 else if(IS_INTRESOURCE(pfd->Entry))
1351 MESSAGE("\tentry: %p\n", pfd->Entry);
1352 else
1353 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1355 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1357 while (n)
1359 dump_TLBFuncDescOne(pfd);
1360 ++pfd;
1361 --n;
1364 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1366 while (n)
1368 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1369 ++pvd;
1370 --n;
1374 static void dump_TLBImpLib(const TLBImpLib *import)
1376 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1377 debugstr_w(import->name));
1378 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1379 import->wVersionMinor, import->lcid, import->offset);
1382 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1384 TLBRefType *ref;
1386 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1388 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1389 if(ref->index == -1)
1390 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1391 else
1392 TRACE_(typelib)("type no: %d\n", ref->index);
1394 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1396 TRACE_(typelib)("in lib\n");
1397 dump_TLBImpLib(ref->pImpTLInfo);
1402 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1404 if(!impl)
1405 return;
1406 while (n) {
1407 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1408 impl->hRef, impl->implflags);
1409 ++impl;
1410 --n;
1414 static void dump_Variant(const VARIANT * pvar)
1416 SYSTEMTIME st;
1418 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1420 if (pvar)
1422 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1423 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1425 TRACE(",%p", V_BYREF(pvar));
1427 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1429 TRACE(",%p", V_ARRAY(pvar));
1431 else switch (V_TYPE(pvar))
1433 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1434 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1435 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1436 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1437 case VT_INT:
1438 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1439 case VT_UINT:
1440 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1441 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1442 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1443 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1444 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1445 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1446 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1447 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1448 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1449 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1450 V_CY(pvar).s.Lo); break;
1451 case VT_DATE:
1452 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1453 TRACE(",<invalid>");
1454 else
1455 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1456 st.wHour, st.wMinute, st.wSecond);
1457 break;
1458 case VT_ERROR:
1459 case VT_VOID:
1460 case VT_USERDEFINED:
1461 case VT_EMPTY:
1462 case VT_NULL: break;
1463 default: TRACE(",?"); break;
1466 TRACE("}\n");
1469 static void dump_DispParms(const DISPPARAMS * pdp)
1471 unsigned int index;
1473 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1475 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1477 TRACE("named args:\n");
1478 for (index = 0; index < pdp->cNamedArgs; index++)
1479 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1482 if (pdp->cArgs && pdp->rgvarg)
1484 TRACE("args:\n");
1485 for (index = 0; index < pdp->cArgs; index++)
1486 dump_Variant( &pdp->rgvarg[index] );
1490 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1492 TRACE("%p ref=%u\n", pty, pty->ref);
1493 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1494 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1495 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1496 TRACE("fct:%u var:%u impl:%u\n",
1497 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1498 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1499 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1500 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1501 if (TRACE_ON(ole))
1502 dump_TLBFuncDesc(pty->funcdescs, pty->TypeAttr.cFuncs);
1503 dump_TLBVarDesc(pty->vardescs, pty->TypeAttr.cVars);
1504 dump_TLBImplType(pty->impltypes, pty->TypeAttr.cImplTypes);
1507 static void dump_VARDESC(const VARDESC *v)
1509 MESSAGE("memid %d\n",v->memid);
1510 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1511 MESSAGE("oInst %d\n",v->u.oInst);
1512 dump_ELEMDESC(&(v->elemdescVar));
1513 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1514 MESSAGE("varkind %d\n",v->varkind);
1517 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1519 /* VT_LPWSTR is largest type that, may appear in type description */
1520 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1521 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1522 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1523 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1524 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1525 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1526 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1527 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1530 static void TLB_abort(void)
1532 DebugBreak();
1535 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1537 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1538 if (!ret) ERR("cannot allocate memory\n");
1539 return ret;
1542 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1544 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1545 if (!ret) ERR("cannot allocate memory\n");
1546 return ret;
1549 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1551 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1554 void heap_free(void *ptr)
1556 HeapFree(GetProcessHeap(), 0, ptr);
1559 /* returns the size required for a deep copy of a typedesc into a
1560 * flat buffer */
1561 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1563 SIZE_T size = 0;
1565 if (alloc_initial_space)
1566 size += sizeof(TYPEDESC);
1568 switch (tdesc->vt)
1570 case VT_PTR:
1571 case VT_SAFEARRAY:
1572 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1573 break;
1574 case VT_CARRAY:
1575 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1576 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1577 break;
1579 return size;
1582 /* deep copy a typedesc into a flat buffer */
1583 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1585 if (!dest)
1587 dest = buffer;
1588 buffer = (char *)buffer + sizeof(TYPEDESC);
1591 *dest = *src;
1593 switch (src->vt)
1595 case VT_PTR:
1596 case VT_SAFEARRAY:
1597 dest->u.lptdesc = buffer;
1598 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1599 break;
1600 case VT_CARRAY:
1601 dest->u.lpadesc = buffer;
1602 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1603 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1604 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1605 break;
1607 return buffer;
1610 /* free custom data allocated by MSFT_CustData */
1611 static inline void TLB_FreeCustData(struct list *custdata_list)
1613 TLBCustData *cd, *cdn;
1614 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1616 list_remove(&cd->entry);
1617 VariantClear(&cd->data);
1618 heap_free(cd);
1622 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1624 DWORD len;
1625 BSTR ret;
1627 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1628 ret = SysAllocStringLen(NULL, len - 1);
1629 if (!ret) return ret;
1630 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1631 return ret;
1634 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1635 UINT n, MEMBERID memid)
1637 while(n){
1638 if(funcdescs->funcdesc.memid == memid)
1639 return funcdescs;
1640 ++funcdescs;
1641 --n;
1643 return NULL;
1646 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1647 UINT n, const OLECHAR *name)
1649 while(n){
1650 if(!lstrcmpiW(TLB_get_bstr(funcdescs->Name), name))
1651 return funcdescs;
1652 ++funcdescs;
1653 --n;
1655 return NULL;
1658 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1659 UINT n, MEMBERID memid)
1661 while(n){
1662 if(vardescs->vardesc.memid == memid)
1663 return vardescs;
1664 ++vardescs;
1665 --n;
1667 return NULL;
1670 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1671 UINT n, const OLECHAR *name)
1673 while(n){
1674 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1675 return vardescs;
1676 ++vardescs;
1677 --n;
1679 return NULL;
1682 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1684 TLBCustData *cust_data;
1685 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1686 if(IsEqualIID(&cust_data->guid, guid))
1687 return cust_data;
1688 return NULL;
1691 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1692 UINT n, const OLECHAR *name)
1694 while(n){
1695 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1696 return *typeinfos;
1697 ++typeinfos;
1698 --n;
1700 return NULL;
1703 static TLBVarDesc *TLBVarDesc_Constructor(UINT n)
1705 TLBVarDesc *ret;
1707 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1708 if(!ret)
1709 return NULL;
1711 while(n){
1712 list_init(&ret[n-1].custdata_list);
1713 --n;
1716 return ret;
1719 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1721 TLBParDesc *ret;
1723 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1724 if(!ret)
1725 return NULL;
1727 while(n){
1728 list_init(&ret[n-1].custdata_list);
1729 --n;
1732 return ret;
1735 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1737 list_init(&func_desc->custdata_list);
1740 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1742 TLBFuncDesc *ret;
1744 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1745 if(!ret)
1746 return NULL;
1748 while(n){
1749 TLBFuncDesc_Constructor(&ret[n-1]);
1750 --n;
1753 return ret;
1756 static void TLBImplType_Constructor(TLBImplType *impl)
1758 list_init(&impl->custdata_list);
1761 static TLBImplType *TLBImplType_Alloc(UINT n)
1763 TLBImplType *ret;
1765 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1766 if(!ret)
1767 return NULL;
1769 while(n){
1770 TLBImplType_Constructor(&ret[n-1]);
1771 --n;
1774 return ret;
1777 static HRESULT TLB_set_custdata(struct list *custdata_list, REFGUID guid, VARIANT *var)
1779 TLBCustData *cust_data;
1781 switch(V_VT(var)){
1782 case VT_I4:
1783 case VT_R4:
1784 case VT_UI4:
1785 case VT_INT:
1786 case VT_UINT:
1787 case VT_HRESULT:
1788 case VT_BSTR:
1789 break;
1790 default:
1791 return DISP_E_BADVARTYPE;
1794 cust_data = TLB_get_custdata_by_guid(custdata_list, guid);
1796 if (!cust_data) {
1797 cust_data = heap_alloc(sizeof(TLBCustData));
1798 if (!cust_data)
1799 return E_OUTOFMEMORY;
1801 cust_data->guid = *guid;
1802 VariantInit(&cust_data->data);
1804 list_add_tail(custdata_list, &cust_data->entry);
1805 }else
1806 VariantClear(&cust_data->data);
1808 return VariantCopy(&cust_data->data, var);
1811 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1813 TLBString *str;
1815 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1816 if (strcmpW(str->str, new_str) == 0)
1817 return str;
1820 str = heap_alloc(sizeof(TLBString));
1821 if (!str)
1822 return NULL;
1824 str->str = SysAllocString(new_str);
1825 if (!str->str) {
1826 heap_free(str);
1827 return NULL;
1830 list_add_tail(string_list, &str->entry);
1832 return str;
1835 /**********************************************************************
1837 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1839 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1841 return pcx->pos;
1844 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1846 if (where != DO_NOT_SEEK)
1848 where += pcx->oStart;
1849 if (where > pcx->length)
1851 /* FIXME */
1852 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1853 TLB_abort();
1855 pcx->pos = where;
1859 /* read function */
1860 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1862 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1863 pcx->pos, count, pcx->oStart, pcx->length, where);
1865 MSFT_Seek(pcx, where);
1866 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1867 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1868 pcx->pos += count;
1869 return count;
1872 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1873 LONG where )
1875 DWORD ret;
1877 ret = MSFT_Read(buffer, count, pcx, where);
1878 FromLEDWords(buffer, ret);
1880 return ret;
1883 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1884 LONG where )
1886 DWORD ret;
1888 ret = MSFT_Read(buffer, count, pcx, where);
1889 FromLEWords(buffer, ret);
1891 return ret;
1894 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1896 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1897 memset(pGuid,0, sizeof(GUID));
1898 return;
1900 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1901 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1902 pGuid->Data2 = FromLEWord(pGuid->Data2);
1903 pGuid->Data3 = FromLEWord(pGuid->Data3);
1904 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1907 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1909 MSFT_NameIntro niName;
1911 if (offset < 0)
1913 ERR_(typelib)("bad offset %d\n", offset);
1914 return -1;
1917 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1918 pcx->pTblDir->pNametab.offset+offset);
1920 return niName.hreftype;
1923 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
1925 char *string;
1926 MSFT_NameIntro intro;
1927 INT16 len_piece;
1928 int offs = 0, lengthInChars;
1930 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
1931 while (1) {
1932 TLBString *tlbstr;
1934 if (offs >= pcx->pTblDir->pNametab.length)
1935 return S_OK;
1937 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
1938 intro.namelen &= 0xFF;
1939 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
1940 if(len_piece % 4)
1941 len_piece = (len_piece + 4) & ~0x3;
1942 if(len_piece < 8)
1943 len_piece = 8;
1945 string = heap_alloc(len_piece + 1);
1946 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
1947 string[intro.namelen] = '\0';
1949 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1950 string, -1, NULL, 0);
1951 if (!lengthInChars) {
1952 heap_free(string);
1953 return E_UNEXPECTED;
1956 tlbstr = heap_alloc(sizeof(TLBString));
1958 tlbstr->offset = offs;
1959 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1960 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
1962 heap_free(string);
1964 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
1966 offs += len_piece;
1970 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
1972 TLBString *tlbstr;
1974 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
1975 if (tlbstr->offset == offset) {
1976 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
1977 return tlbstr;
1981 return NULL;
1984 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
1986 TLBString *tlbstr;
1988 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
1989 if (tlbstr->offset == offset) {
1990 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
1991 return tlbstr;
1995 return NULL;
1999 * read a value and fill a VARIANT structure
2001 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2003 int size;
2005 TRACE_(typelib)("\n");
2007 if(offset <0) { /* data are packed in here */
2008 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2009 V_I4(pVar) = offset & 0x3ffffff;
2010 return;
2012 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2013 pcx->pTblDir->pCustData.offset + offset );
2014 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2015 switch (V_VT(pVar)){
2016 case VT_EMPTY: /* FIXME: is this right? */
2017 case VT_NULL: /* FIXME: is this right? */
2018 case VT_I2 : /* this should not happen */
2019 case VT_I4 :
2020 case VT_R4 :
2021 case VT_ERROR :
2022 case VT_BOOL :
2023 case VT_I1 :
2024 case VT_UI1 :
2025 case VT_UI2 :
2026 case VT_UI4 :
2027 case VT_INT :
2028 case VT_UINT :
2029 case VT_VOID : /* FIXME: is this right? */
2030 case VT_HRESULT :
2031 size=4; break;
2032 case VT_R8 :
2033 case VT_CY :
2034 case VT_DATE :
2035 case VT_I8 :
2036 case VT_UI8 :
2037 case VT_DECIMAL : /* FIXME: is this right? */
2038 case VT_FILETIME :
2039 size=8;break;
2040 /* pointer types with known behaviour */
2041 case VT_BSTR :{
2042 char * ptr;
2043 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2044 if(size < 0) {
2045 char next;
2046 DWORD origPos = MSFT_Tell(pcx), nullPos;
2048 do {
2049 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
2050 } while (next);
2051 nullPos = MSFT_Tell(pcx);
2052 size = nullPos - origPos;
2053 MSFT_Seek(pcx, origPos);
2055 ptr = heap_alloc_zero(size);/* allocate temp buffer */
2056 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
2057 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2058 /* FIXME: do we need a AtoW conversion here? */
2059 V_UNION(pVar, bstrVal[size])='\0';
2060 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2061 heap_free(ptr);
2063 size=-4; break;
2064 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2065 case VT_DISPATCH :
2066 case VT_VARIANT :
2067 case VT_UNKNOWN :
2068 case VT_PTR :
2069 case VT_SAFEARRAY :
2070 case VT_CARRAY :
2071 case VT_USERDEFINED :
2072 case VT_LPSTR :
2073 case VT_LPWSTR :
2074 case VT_BLOB :
2075 case VT_STREAM :
2076 case VT_STORAGE :
2077 case VT_STREAMED_OBJECT :
2078 case VT_STORED_OBJECT :
2079 case VT_BLOB_OBJECT :
2080 case VT_CF :
2081 case VT_CLSID :
2082 default:
2083 size=0;
2084 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2085 V_VT(pVar));
2088 if(size>0) /* (big|small) endian correct? */
2089 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2090 return;
2093 * create a linked list with custom data
2095 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2097 MSFT_CDGuid entry;
2098 TLBCustData* pNew;
2099 int count=0;
2101 TRACE_(typelib)("\n");
2103 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2105 while(offset >=0){
2106 count++;
2107 pNew=heap_alloc_zero(sizeof(TLBCustData));
2108 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2109 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
2110 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2111 list_add_head(custdata_list, &pNew->entry);
2112 offset = entry.next;
2114 return count;
2117 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
2118 ITypeInfoImpl *pTI)
2120 if(type <0)
2121 pTd->vt=type & VT_TYPEMASK;
2122 else
2123 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2125 if(pTd->vt == VT_USERDEFINED)
2126 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
2128 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2131 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
2133 /* resolve referenced type if any */
2134 while (lpTypeDesc)
2136 switch (lpTypeDesc->vt)
2138 case VT_PTR:
2139 lpTypeDesc = lpTypeDesc->u.lptdesc;
2140 break;
2142 case VT_CARRAY:
2143 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
2144 break;
2146 case VT_USERDEFINED:
2147 MSFT_DoRefType(pcx, pTI->pTypeLib,
2148 lpTypeDesc->u.hreftype);
2150 lpTypeDesc = NULL;
2151 break;
2153 default:
2154 lpTypeDesc = NULL;
2159 static void
2160 MSFT_DoFuncs(TLBContext* pcx,
2161 ITypeInfoImpl* pTI,
2162 int cFuncs,
2163 int cVars,
2164 int offset,
2165 TLBFuncDesc** pptfd)
2168 * member information is stored in a data structure at offset
2169 * indicated by the memoffset field of the typeinfo structure
2170 * There are several distinctive parts.
2171 * The first part starts with a field that holds the total length
2172 * of this (first) part excluding this field. Then follow the records,
2173 * for each member there is one record.
2175 * The first entry is always the length of the record (including this
2176 * length word).
2177 * The rest of the record depends on the type of the member. If there is
2178 * a field indicating the member type (function, variable, interface, etc)
2179 * I have not found it yet. At this time we depend on the information
2180 * in the type info and the usual order how things are stored.
2182 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2183 * for each member;
2185 * Third is an equal sized array with file offsets to the name entry
2186 * of each member.
2188 * The fourth and last (?) part is an array with offsets to the records
2189 * in the first part of this file segment.
2192 int infolen, nameoffset, reclength, i;
2193 int recoffset = offset + sizeof(INT);
2195 char *recbuf = heap_alloc(0xffff);
2196 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2197 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2199 TRACE_(typelib)("\n");
2201 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2203 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2204 ptfd = *pptfd;
2205 for ( i = 0; i < cFuncs ; i++ )
2207 int optional;
2209 /* name, eventually add to a hash table */
2210 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2211 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2213 /* nameoffset is sometimes -1 on the second half of a propget/propput
2214 * pair of functions */
2215 if ((nameoffset == -1) && (i > 0))
2216 ptfd->Name = ptfd_prev->Name;
2217 else
2218 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2220 /* read the function information record */
2221 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2223 reclength &= 0xffff;
2225 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2227 /* size without argument data */
2228 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2230 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2231 ptfd->helpcontext = pFuncRec->HelpContext;
2233 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2234 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2236 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2238 if (pFuncRec->FKCCIC & 0x2000 )
2240 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2241 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2242 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2244 else
2245 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2247 else
2248 ptfd->Entry = (TLBString*)-1;
2250 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2251 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2253 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2254 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2256 /* fill the FuncDesc Structure */
2257 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2258 offset + infolen + ( i + 1) * sizeof(INT));
2260 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2261 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2262 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2263 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2264 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2265 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2266 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2268 MSFT_GetTdesc(pcx,
2269 pFuncRec->DataType,
2270 &ptfd->funcdesc.elemdescFunc.tdesc,
2271 pTI);
2272 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2274 /* do the parameters/arguments */
2275 if(pFuncRec->nrargs)
2277 int j = 0;
2278 MSFT_ParameterInfo paraminfo;
2280 ptfd->funcdesc.lprgelemdescParam =
2281 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2283 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2285 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2286 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2288 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2290 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2292 MSFT_GetTdesc(pcx,
2293 paraminfo.DataType,
2294 &elemdesc->tdesc,
2295 pTI);
2297 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2299 /* name */
2300 if (paraminfo.oName == -1)
2301 /* this occurs for [propput] or [propget] methods, so
2302 * we should just set the name of the parameter to the
2303 * name of the method. */
2304 ptfd->pParamDesc[j].Name = ptfd->Name;
2305 else
2306 ptfd->pParamDesc[j].Name =
2307 MSFT_ReadName( pcx, paraminfo.oName );
2308 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2310 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2312 /* default value */
2313 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2314 (pFuncRec->FKCCIC & 0x1000) )
2316 INT* pInt = (INT *)((char *)pFuncRec +
2317 reclength -
2318 (pFuncRec->nrargs * 4) * sizeof(INT) );
2320 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2322 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2323 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2325 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2326 pInt[j], pcx);
2328 else
2329 elemdesc->u.paramdesc.pparamdescex = NULL;
2331 /* custom info */
2332 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2333 j*sizeof(pFuncRec->oArgCustData[0])) &&
2334 pFuncRec->FKCCIC & 0x80 )
2336 MSFT_CustData(pcx,
2337 pFuncRec->oArgCustData[j],
2338 &ptfd->pParamDesc[j].custdata_list);
2341 /* SEEK value = jump to offset,
2342 * from there jump to the end of record,
2343 * go back by (j-1) arguments
2345 MSFT_ReadLEDWords( &paraminfo ,
2346 sizeof(MSFT_ParameterInfo), pcx,
2347 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2348 * sizeof(MSFT_ParameterInfo)));
2352 /* scode is not used: archaic win16 stuff FIXME: right? */
2353 ptfd->funcdesc.cScodes = 0 ;
2354 ptfd->funcdesc.lprgscode = NULL ;
2356 ptfd_prev = ptfd;
2357 ++ptfd;
2358 recoffset += reclength;
2360 heap_free(recbuf);
2363 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2364 int cVars, int offset, TLBVarDesc ** pptvd)
2366 int infolen, nameoffset, reclength;
2367 char recbuf[256];
2368 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2369 TLBVarDesc *ptvd;
2370 int i;
2371 int recoffset;
2373 TRACE_(typelib)("\n");
2375 ptvd = *pptvd = TLBVarDesc_Constructor(cVars);
2376 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2377 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2378 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2379 recoffset += offset+sizeof(INT);
2380 for(i=0;i<cVars;i++, ++ptvd){
2381 /* name, eventually add to a hash table */
2382 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2383 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2384 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2385 /* read the variable information record */
2386 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2387 reclength &= 0xff;
2388 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2390 /* optional data */
2391 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2392 ptvd->HelpContext = pVarRec->HelpContext;
2394 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2395 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2397 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2398 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2400 /* fill the VarDesc Structure */
2401 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2402 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2403 ptvd->vardesc.varkind = pVarRec->VarKind;
2404 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2405 MSFT_GetTdesc(pcx, pVarRec->DataType,
2406 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2407 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2408 if(pVarRec->VarKind == VAR_CONST ){
2409 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2410 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2411 pVarRec->OffsValue, pcx);
2412 } else
2413 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2414 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2415 recoffset += reclength;
2419 /* fill in data for a hreftype (offset). When the referenced type is contained
2420 * in the typelib, it's just an (file) offset in the type info base dir.
2421 * If comes from import, it's an offset+1 in the ImpInfo table
2422 * */
2423 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2424 int offset)
2426 TLBRefType *ref;
2428 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2430 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2432 if(ref->reference == offset) return;
2435 ref = heap_alloc_zero(sizeof(TLBRefType));
2436 list_add_tail(&pTL->ref_list, &ref->entry);
2438 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2439 /* external typelib */
2440 MSFT_ImpInfo impinfo;
2441 TLBImpLib *pImpLib;
2443 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2445 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2446 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2448 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2449 if(pImpLib->offset==impinfo.oImpFile)
2450 break;
2452 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2453 ref->reference = offset & (~0x3);
2454 ref->pImpTLInfo = pImpLib;
2455 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2456 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2457 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2458 ref->index = TLB_REF_USE_GUID;
2459 } else
2460 ref->index = impinfo.oGuid;
2461 }else{
2462 ERR("Cannot find a reference\n");
2463 ref->reference = -1;
2464 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2466 }else{
2467 /* in this typelib */
2468 ref->index = MSFT_HREFTYPE_INDEX(offset);
2469 ref->reference = offset;
2470 ref->pImpTLInfo = TLB_REF_INTERNAL;
2474 /* process Implemented Interfaces of a com class */
2475 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2476 int offset)
2478 int i;
2479 MSFT_RefRecord refrec;
2480 TLBImplType *pImpl;
2482 TRACE_(typelib)("\n");
2484 pTI->impltypes = TLBImplType_Alloc(count);
2485 pImpl = pTI->impltypes;
2486 for(i=0;i<count;i++){
2487 if(offset<0) break; /* paranoia */
2488 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2489 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2490 pImpl->hRef = refrec.reftype;
2491 pImpl->implflags=refrec.flags;
2492 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2493 offset=refrec.onext;
2494 ++pImpl;
2498 * process a typeinfo record
2500 static ITypeInfoImpl * MSFT_DoTypeInfo(
2501 TLBContext *pcx,
2502 int count,
2503 ITypeLibImpl * pLibInfo)
2505 MSFT_TypeInfoBase tiBase;
2506 ITypeInfoImpl *ptiRet;
2508 TRACE_(typelib)("count=%u\n", count);
2510 ptiRet = ITypeInfoImpl_Constructor();
2511 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2512 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2514 /* this is where we are coming from */
2515 ptiRet->pTypeLib = pLibInfo;
2516 ptiRet->index=count;
2517 /* fill in the typeattr fields */
2519 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2520 ptiRet->TypeAttr.lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2521 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2522 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2523 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2524 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2525 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2526 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2527 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2528 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2529 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2530 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2531 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2532 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2533 MSFT_GetTdesc(pcx, tiBase.datatype1,
2534 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2536 /* FIXME: */
2537 /* IDLDESC idldescType; *//* never saw this one != zero */
2539 /* name, eventually add to a hash table */
2540 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2541 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2542 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2543 /* help info */
2544 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2545 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2546 ptiRet->dwHelpContext=tiBase.helpcontext;
2548 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2549 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2551 /* note: InfoType's Help file and HelpStringDll come from the containing
2552 * library. Further HelpString and Docstring appear to be the same thing :(
2554 /* functions */
2555 if(ptiRet->TypeAttr.cFuncs >0 )
2556 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2557 ptiRet->TypeAttr.cVars,
2558 tiBase.memoffset, &ptiRet->funcdescs);
2559 /* variables */
2560 if(ptiRet->TypeAttr.cVars >0 )
2561 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2562 ptiRet->TypeAttr.cVars,
2563 tiBase.memoffset, &ptiRet->vardescs);
2564 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2565 switch(ptiRet->TypeAttr.typekind)
2567 case TKIND_COCLASS:
2568 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2569 tiBase.datatype1);
2570 break;
2571 case TKIND_DISPATCH:
2572 /* This is not -1 when the interface is a non-base dual interface or
2573 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2574 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2575 not this interface.
2578 if (tiBase.datatype1 != -1)
2580 ptiRet->impltypes = TLBImplType_Alloc(1);
2581 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2582 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2584 break;
2585 default:
2586 ptiRet->impltypes = TLBImplType_Alloc(1);
2587 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2588 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2589 break;
2592 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2594 TRACE_(typelib)("%s guid: %s kind:%s\n",
2595 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2596 debugstr_guid(&ptiRet->TypeAttr.guid),
2597 typekind_desc[ptiRet->TypeAttr.typekind]);
2598 if (TRACE_ON(typelib))
2599 dump_TypeInfo(ptiRet);
2601 return ptiRet;
2604 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2606 char *string;
2607 INT16 len_str, len_piece;
2608 int offs = 0, lengthInChars;
2610 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2611 while (1) {
2612 TLBString *tlbstr;
2614 if (offs >= pcx->pTblDir->pStringtab.length)
2615 return S_OK;
2617 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2618 len_piece = len_str + sizeof(INT16);
2619 if(len_piece % 4)
2620 len_piece = (len_piece + 4) & ~0x3;
2621 if(len_piece < 8)
2622 len_piece = 8;
2624 string = heap_alloc(len_piece + 1);
2625 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2626 string[len_str] = '\0';
2628 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2629 string, -1, NULL, 0);
2630 if (!lengthInChars) {
2631 heap_free(string);
2632 return E_UNEXPECTED;
2635 tlbstr = heap_alloc(sizeof(TLBString));
2637 tlbstr->offset = offs;
2638 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2639 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2641 heap_free(string);
2643 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2645 offs += len_piece;
2649 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2650 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2651 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2652 * tradeoff here.
2654 static struct list tlb_cache = LIST_INIT(tlb_cache);
2655 static CRITICAL_SECTION cache_section;
2656 static CRITICAL_SECTION_DEBUG cache_section_debug =
2658 0, 0, &cache_section,
2659 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2660 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2662 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2665 typedef struct TLB_PEFile
2667 IUnknown IUnknown_iface;
2668 LONG refs;
2669 HMODULE dll;
2670 HRSRC typelib_resource;
2671 HGLOBAL typelib_global;
2672 LPVOID typelib_base;
2673 } TLB_PEFile;
2675 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2677 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2680 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2682 if (IsEqualIID(riid, &IID_IUnknown))
2684 *ppv = iface;
2685 IUnknown_AddRef(iface);
2686 return S_OK;
2688 *ppv = NULL;
2689 return E_NOINTERFACE;
2692 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2694 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2695 return InterlockedIncrement(&This->refs);
2698 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2700 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2701 ULONG refs = InterlockedDecrement(&This->refs);
2702 if (!refs)
2704 if (This->typelib_global)
2705 FreeResource(This->typelib_global);
2706 if (This->dll)
2707 FreeLibrary(This->dll);
2708 heap_free(This);
2710 return refs;
2713 static const IUnknownVtbl TLB_PEFile_Vtable =
2715 TLB_PEFile_QueryInterface,
2716 TLB_PEFile_AddRef,
2717 TLB_PEFile_Release
2720 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2722 TLB_PEFile *This;
2723 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2725 This = heap_alloc(sizeof(TLB_PEFile));
2726 if (!This)
2727 return E_OUTOFMEMORY;
2729 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2730 This->refs = 1;
2731 This->dll = NULL;
2732 This->typelib_resource = NULL;
2733 This->typelib_global = NULL;
2734 This->typelib_base = NULL;
2736 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2737 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2739 if (This->dll)
2741 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2742 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2743 if (This->typelib_resource)
2745 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2746 if (This->typelib_global)
2748 This->typelib_base = LockResource(This->typelib_global);
2750 if (This->typelib_base)
2752 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2753 *ppBase = This->typelib_base;
2754 *ppFile = &This->IUnknown_iface;
2755 return S_OK;
2760 TRACE("No TYPELIB resource found\n");
2761 hr = E_FAIL;
2764 TLB_PEFile_Release(&This->IUnknown_iface);
2765 return hr;
2768 typedef struct TLB_NEFile
2770 IUnknown IUnknown_iface;
2771 LONG refs;
2772 LPVOID typelib_base;
2773 } TLB_NEFile;
2775 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2777 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2780 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2782 if (IsEqualIID(riid, &IID_IUnknown))
2784 *ppv = iface;
2785 IUnknown_AddRef(iface);
2786 return S_OK;
2788 *ppv = NULL;
2789 return E_NOINTERFACE;
2792 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2794 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2795 return InterlockedIncrement(&This->refs);
2798 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2800 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2801 ULONG refs = InterlockedDecrement(&This->refs);
2802 if (!refs)
2804 heap_free(This->typelib_base);
2805 heap_free(This);
2807 return refs;
2810 static const IUnknownVtbl TLB_NEFile_Vtable =
2812 TLB_NEFile_QueryInterface,
2813 TLB_NEFile_AddRef,
2814 TLB_NEFile_Release
2817 /***********************************************************************
2818 * read_xx_header [internal]
2820 static int read_xx_header( HFILE lzfd )
2822 IMAGE_DOS_HEADER mzh;
2823 char magic[3];
2825 LZSeek( lzfd, 0, SEEK_SET );
2826 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2827 return 0;
2828 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2829 return 0;
2831 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2832 if ( 2 != LZRead( lzfd, magic, 2 ) )
2833 return 0;
2835 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2837 if ( magic[0] == 'N' && magic[1] == 'E' )
2838 return IMAGE_OS2_SIGNATURE;
2839 if ( magic[0] == 'P' && magic[1] == 'E' )
2840 return IMAGE_NT_SIGNATURE;
2842 magic[2] = '\0';
2843 WARN("Can't handle %s files.\n", magic );
2844 return 0;
2848 /***********************************************************************
2849 * find_ne_resource [internal]
2851 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2852 DWORD *resLen, DWORD *resOff )
2854 IMAGE_OS2_HEADER nehd;
2855 NE_TYPEINFO *typeInfo;
2856 NE_NAMEINFO *nameInfo;
2857 DWORD nehdoffset;
2858 LPBYTE resTab;
2859 DWORD resTabSize;
2860 int count;
2862 /* Read in NE header */
2863 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2864 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2866 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2867 if ( !resTabSize )
2869 TRACE("No resources in NE dll\n" );
2870 return FALSE;
2873 /* Read in resource table */
2874 resTab = heap_alloc( resTabSize );
2875 if ( !resTab ) return FALSE;
2877 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2878 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2880 heap_free( resTab );
2881 return FALSE;
2884 /* Find resource */
2885 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2887 if (!IS_INTRESOURCE(typeid)) /* named type */
2889 BYTE len = strlen( typeid );
2890 while (typeInfo->type_id)
2892 if (!(typeInfo->type_id & 0x8000))
2894 BYTE *p = resTab + typeInfo->type_id;
2895 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2897 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2898 typeInfo->count * sizeof(NE_NAMEINFO));
2901 else /* numeric type id */
2903 WORD id = LOWORD(typeid) | 0x8000;
2904 while (typeInfo->type_id)
2906 if (typeInfo->type_id == id) goto found_type;
2907 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2908 typeInfo->count * sizeof(NE_NAMEINFO));
2911 TRACE("No typeid entry found for %p\n", typeid );
2912 heap_free( resTab );
2913 return FALSE;
2915 found_type:
2916 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2918 if (!IS_INTRESOURCE(resid)) /* named resource */
2920 BYTE len = strlen( resid );
2921 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2923 BYTE *p = resTab + nameInfo->id;
2924 if (nameInfo->id & 0x8000) continue;
2925 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2928 else /* numeric resource id */
2930 WORD id = LOWORD(resid) | 0x8000;
2931 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2932 if (nameInfo->id == id) goto found_name;
2934 TRACE("No resid entry found for %p\n", typeid );
2935 heap_free( resTab );
2936 return FALSE;
2938 found_name:
2939 /* Return resource data */
2940 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2941 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2943 heap_free( resTab );
2944 return TRUE;
2947 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2949 HFILE lzfd = -1;
2950 OFSTRUCT ofs;
2951 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2952 TLB_NEFile *This;
2954 This = heap_alloc(sizeof(TLB_NEFile));
2955 if (!This) return E_OUTOFMEMORY;
2957 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
2958 This->refs = 1;
2959 This->typelib_base = NULL;
2961 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2962 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2964 DWORD reslen, offset;
2965 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2967 This->typelib_base = heap_alloc(reslen);
2968 if( !This->typelib_base )
2969 hr = E_OUTOFMEMORY;
2970 else
2972 LZSeek( lzfd, offset, SEEK_SET );
2973 reslen = LZRead( lzfd, This->typelib_base, reslen );
2974 LZClose( lzfd );
2975 *ppBase = This->typelib_base;
2976 *pdwTLBLength = reslen;
2977 *ppFile = &This->IUnknown_iface;
2978 return S_OK;
2983 if( lzfd >= 0) LZClose( lzfd );
2984 TLB_NEFile_Release(&This->IUnknown_iface);
2985 return hr;
2988 typedef struct TLB_Mapping
2990 IUnknown IUnknown_iface;
2991 LONG refs;
2992 HANDLE file;
2993 HANDLE mapping;
2994 LPVOID typelib_base;
2995 } TLB_Mapping;
2997 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
2999 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3002 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3004 if (IsEqualIID(riid, &IID_IUnknown))
3006 *ppv = iface;
3007 IUnknown_AddRef(iface);
3008 return S_OK;
3010 *ppv = NULL;
3011 return E_NOINTERFACE;
3014 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3016 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3017 return InterlockedIncrement(&This->refs);
3020 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3022 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3023 ULONG refs = InterlockedDecrement(&This->refs);
3024 if (!refs)
3026 if (This->typelib_base)
3027 UnmapViewOfFile(This->typelib_base);
3028 if (This->mapping)
3029 CloseHandle(This->mapping);
3030 if (This->file != INVALID_HANDLE_VALUE)
3031 CloseHandle(This->file);
3032 heap_free(This);
3034 return refs;
3037 static const IUnknownVtbl TLB_Mapping_Vtable =
3039 TLB_Mapping_QueryInterface,
3040 TLB_Mapping_AddRef,
3041 TLB_Mapping_Release
3044 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3046 TLB_Mapping *This;
3048 This = heap_alloc(sizeof(TLB_Mapping));
3049 if (!This)
3050 return E_OUTOFMEMORY;
3052 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3053 This->refs = 1;
3054 This->file = INVALID_HANDLE_VALUE;
3055 This->mapping = NULL;
3056 This->typelib_base = NULL;
3058 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3059 if (INVALID_HANDLE_VALUE != This->file)
3061 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3062 if (This->mapping)
3064 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3065 if(This->typelib_base)
3067 /* retrieve file size */
3068 *pdwTLBLength = GetFileSize(This->file, NULL);
3069 *ppBase = This->typelib_base;
3070 *ppFile = &This->IUnknown_iface;
3071 return S_OK;
3076 IUnknown_Release(&This->IUnknown_iface);
3077 return TYPE_E_CANTLOADLIBRARY;
3080 /****************************************************************************
3081 * TLB_ReadTypeLib
3083 * find the type of the typelib file and map the typelib resource into
3084 * the memory
3087 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3088 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3090 ITypeLibImpl *entry;
3091 HRESULT ret;
3092 INT index = 1;
3093 LPWSTR index_str, file = (LPWSTR)pszFileName;
3094 LPVOID pBase = NULL;
3095 DWORD dwTLBLength = 0;
3096 IUnknown *pFile = NULL;
3098 *ppTypeLib = NULL;
3100 index_str = strrchrW(pszFileName, '\\');
3101 if(index_str && *++index_str != '\0')
3103 LPWSTR end_ptr;
3104 LONG idx = strtolW(index_str, &end_ptr, 10);
3105 if(*end_ptr == '\0')
3107 int str_len = index_str - pszFileName - 1;
3108 index = idx;
3109 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3110 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3111 file[str_len] = 0;
3115 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3117 if(strchrW(file, '\\'))
3119 lstrcpyW(pszPath, file);
3121 else
3123 int len = GetSystemDirectoryW(pszPath, cchPath);
3124 pszPath[len] = '\\';
3125 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3129 if(file != pszFileName) heap_free(file);
3131 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3133 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3134 EnterCriticalSection(&cache_section);
3135 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3137 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3139 TRACE("cache hit\n");
3140 *ppTypeLib = &entry->ITypeLib2_iface;
3141 ITypeLib2_AddRef(*ppTypeLib);
3142 LeaveCriticalSection(&cache_section);
3143 return S_OK;
3146 LeaveCriticalSection(&cache_section);
3148 /* now actually load and parse the typelib */
3150 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3151 if (ret == TYPE_E_CANTLOADLIBRARY)
3152 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3153 if (ret == TYPE_E_CANTLOADLIBRARY)
3154 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3155 if (SUCCEEDED(ret))
3157 if (dwTLBLength >= 4)
3159 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3160 if (dwSignature == MSFT_SIGNATURE)
3161 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3162 else if (dwSignature == SLTG_SIGNATURE)
3163 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3164 else
3166 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3167 ret = TYPE_E_CANTLOADLIBRARY;
3170 else
3171 ret = TYPE_E_CANTLOADLIBRARY;
3172 IUnknown_Release(pFile);
3175 if(*ppTypeLib) {
3176 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3178 TRACE("adding to cache\n");
3179 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3180 lstrcpyW(impl->path, pszPath);
3181 /* We should really canonicalise the path here. */
3182 impl->index = index;
3184 /* FIXME: check if it has added already in the meantime */
3185 EnterCriticalSection(&cache_section);
3186 list_add_head(&tlb_cache, &impl->entry);
3187 LeaveCriticalSection(&cache_section);
3188 ret = S_OK;
3190 else
3192 if(ret != E_FAIL)
3193 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3195 ret = TYPE_E_CANTLOADLIBRARY;
3199 return ret;
3202 /*================== ITypeLib(2) Methods ===================================*/
3204 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3206 ITypeLibImpl* pTypeLibImpl;
3208 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3209 if (!pTypeLibImpl) return NULL;
3211 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3212 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3213 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3214 pTypeLibImpl->ref = 1;
3216 list_init(&pTypeLibImpl->implib_list);
3217 list_init(&pTypeLibImpl->custdata_list);
3218 list_init(&pTypeLibImpl->name_list);
3219 list_init(&pTypeLibImpl->string_list);
3220 list_init(&pTypeLibImpl->ref_list);
3221 pTypeLibImpl->dispatch_href = -1;
3223 return pTypeLibImpl;
3226 /****************************************************************************
3227 * ITypeLib2_Constructor_MSFT
3229 * loading an MSFT typelib from an in-memory image
3231 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3233 TLBContext cx;
3234 LONG lPSegDir;
3235 MSFT_Header tlbHeader;
3236 MSFT_SegDir tlbSegDir;
3237 ITypeLibImpl * pTypeLibImpl;
3239 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3241 pTypeLibImpl = TypeLibImpl_Constructor();
3242 if (!pTypeLibImpl) return NULL;
3244 /* get pointer to beginning of typelib data */
3245 cx.pos = 0;
3246 cx.oStart=0;
3247 cx.mapping = pLib;
3248 cx.pLibInfo = pTypeLibImpl;
3249 cx.length = dwTLBLength;
3251 /* read header */
3252 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3253 TRACE_(typelib)("header:\n");
3254 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3255 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3256 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3257 return NULL;
3259 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3261 /* there is a small amount of information here until the next important
3262 * part:
3263 * the segment directory . Try to calculate the amount of data */
3264 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3266 /* now read the segment directory */
3267 TRACE("read segment directory (at %d)\n",lPSegDir);
3268 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3269 cx.pTblDir = &tlbSegDir;
3271 /* just check two entries */
3272 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3274 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3275 heap_free(pTypeLibImpl);
3276 return NULL;
3279 MSFT_ReadAllNames(&cx);
3280 MSFT_ReadAllStrings(&cx);
3282 /* now fill our internal data */
3283 /* TLIBATTR fields */
3284 MSFT_ReadGuid(&pTypeLibImpl->guid, tlbHeader.posguid, &cx);
3286 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3287 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3288 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3289 pTypeLibImpl->libflags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3291 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3292 pTypeLibImpl->lcid = tlbHeader.lcid;
3294 /* name, eventually add to a hash table */
3295 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3297 /* help info */
3298 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3299 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3301 if( tlbHeader.varflags & HELPDLLFLAG)
3303 int offset;
3304 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3305 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3308 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3310 /* custom data */
3311 if(tlbHeader.CustomDataOffset >= 0)
3313 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3316 /* fill in type descriptions */
3317 if(tlbSegDir.pTypdescTab.length > 0)
3319 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3320 INT16 td[4];
3321 pTypeLibImpl->ctTypeDesc = cTD;
3322 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3323 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3324 for(i=0; i<cTD; )
3326 /* FIXME: add several sanity checks here */
3327 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3328 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3330 /* FIXME: check safearray */
3331 if(td[3] < 0)
3332 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3333 else
3334 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3336 else if(td[0] == VT_CARRAY)
3338 /* array descr table here */
3339 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3341 else if(td[0] == VT_USERDEFINED)
3343 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3345 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3348 /* second time around to fill the array subscript info */
3349 for(i=0;i<cTD;i++)
3351 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3352 if(tlbSegDir.pArrayDescriptions.offset>0)
3354 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3355 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3357 if(td[1]<0)
3358 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3359 else
3360 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3362 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3364 for(j = 0; j<td[2]; j++)
3366 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3367 sizeof(INT), &cx, DO_NOT_SEEK);
3368 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3369 sizeof(INT), &cx, DO_NOT_SEEK);
3372 else
3374 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3375 ERR("didn't find array description data\n");
3380 /* imported type libs */
3381 if(tlbSegDir.pImpFiles.offset>0)
3383 TLBImpLib *pImpLib;
3384 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3385 UINT16 size;
3387 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3389 char *name;
3391 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3392 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3393 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3395 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3396 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3397 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3398 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3400 size >>= 2;
3401 name = heap_alloc_zero(size+1);
3402 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3403 pImpLib->name = TLB_MultiByteToBSTR(name);
3404 heap_free(name);
3406 MSFT_ReadGuid(&pImpLib->guid, oGuid, &cx);
3407 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3409 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3413 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3414 if(pTypeLibImpl->dispatch_href != -1)
3415 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3417 /* type infos */
3418 if(tlbHeader.nrtypeinfos >= 0 )
3420 ITypeInfoImpl **ppTI;
3421 int i;
3423 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3425 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3427 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3429 ++ppTI;
3430 (pTypeLibImpl->TypeInfoCount)++;
3434 TRACE("(%p)\n", pTypeLibImpl);
3435 return &pTypeLibImpl->ITypeLib2_iface;
3439 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3441 char b[3];
3442 int i;
3443 short s;
3445 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3446 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3447 return FALSE;
3450 guid->Data4[0] = s >> 8;
3451 guid->Data4[1] = s & 0xff;
3453 b[2] = '\0';
3454 for(i = 0; i < 6; i++) {
3455 memcpy(b, str + 24 + 2 * i, 2);
3456 guid->Data4[i + 2] = strtol(b, NULL, 16);
3458 return TRUE;
3461 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3463 WORD bytelen;
3464 DWORD len;
3465 BSTR tmp_str;
3467 *pStr = NULL;
3468 bytelen = *(const WORD*)ptr;
3469 if(bytelen == 0xffff) return 2;
3471 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3472 tmp_str = SysAllocStringLen(NULL, len);
3473 if (*tmp_str) {
3474 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3475 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3476 SysFreeString(tmp_str);
3478 return bytelen + 2;
3481 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3483 WORD bytelen;
3485 *str = NULL;
3486 bytelen = *(const WORD*)ptr;
3487 if(bytelen == 0xffff) return 2;
3488 *str = heap_alloc(bytelen + 1);
3489 memcpy(*str, ptr + 2, bytelen);
3490 (*str)[bytelen] = '\0';
3491 return bytelen + 2;
3494 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3496 BSTR tmp_str;
3497 TLBString *tlbstr;
3499 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3500 if (tlbstr->offset == offset)
3501 return tlbstr;
3504 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3505 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3506 SysFreeString(tmp_str);
3508 return tlbstr;
3511 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3513 char *ptr = pLibBlk;
3514 WORD w;
3516 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3517 FIXME("libblk magic = %04x\n", w);
3518 return 0;
3521 ptr += 6;
3522 if((w = *(WORD*)ptr) != 0xffff) {
3523 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3524 ptr += w;
3526 ptr += 2;
3528 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3530 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3532 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3533 ptr += 4;
3535 pTypeLibImpl->syskind = *(WORD*)ptr;
3536 ptr += 2;
3538 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3539 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3540 else
3541 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3542 ptr += 2;
3544 ptr += 4; /* skip res12 */
3546 pTypeLibImpl->libflags = *(WORD*)ptr;
3547 ptr += 2;
3549 pTypeLibImpl->ver_major = *(WORD*)ptr;
3550 ptr += 2;
3552 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3553 ptr += 2;
3555 memcpy(&pTypeLibImpl->guid, ptr, sizeof(GUID));
3556 ptr += sizeof(GUID);
3558 return ptr - (char*)pLibBlk;
3561 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3562 typedef struct
3564 unsigned int num;
3565 HREFTYPE refs[1];
3566 } sltg_ref_lookup_t;
3568 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3569 HREFTYPE *typelib_ref)
3571 if(table && typeinfo_ref < table->num)
3573 *typelib_ref = table->refs[typeinfo_ref];
3574 return S_OK;
3577 ERR_(typelib)("Unable to find reference\n");
3578 *typelib_ref = -1;
3579 return E_FAIL;
3582 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3584 BOOL done = FALSE;
3586 while(!done) {
3587 if((*pType & 0xe00) == 0xe00) {
3588 pTD->vt = VT_PTR;
3589 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3590 pTD = pTD->u.lptdesc;
3592 switch(*pType & 0x3f) {
3593 case VT_PTR:
3594 pTD->vt = VT_PTR;
3595 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3596 pTD = pTD->u.lptdesc;
3597 break;
3599 case VT_USERDEFINED:
3600 pTD->vt = VT_USERDEFINED;
3601 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3602 done = TRUE;
3603 break;
3605 case VT_CARRAY:
3607 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3608 array */
3610 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3612 pTD->vt = VT_CARRAY;
3613 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3614 pTD->u.lpadesc->cDims = pSA->cDims;
3615 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3616 pSA->cDims * sizeof(SAFEARRAYBOUND));
3618 pTD = &pTD->u.lpadesc->tdescElem;
3619 break;
3622 case VT_SAFEARRAY:
3624 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3625 useful? */
3627 pType++;
3628 pTD->vt = VT_SAFEARRAY;
3629 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3630 pTD = pTD->u.lptdesc;
3631 break;
3633 default:
3634 pTD->vt = *pType & 0x3f;
3635 done = TRUE;
3636 break;
3638 pType++;
3640 return pType;
3643 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3644 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3646 /* Handle [in/out] first */
3647 if((*pType & 0xc000) == 0xc000)
3648 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3649 else if(*pType & 0x8000)
3650 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3651 else if(*pType & 0x4000)
3652 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3653 else
3654 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3656 if(*pType & 0x2000)
3657 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3659 if(*pType & 0x80)
3660 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3662 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3666 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3667 char *pNameTable)
3669 unsigned int ref;
3670 char *name;
3671 TLBRefType *ref_type;
3672 sltg_ref_lookup_t *table;
3673 HREFTYPE typelib_ref;
3675 if(pRef->magic != SLTG_REF_MAGIC) {
3676 FIXME("Ref magic = %x\n", pRef->magic);
3677 return NULL;
3679 name = ( (char*)pRef->names + pRef->number);
3681 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3682 table->num = pRef->number >> 3;
3684 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3686 /* We don't want the first href to be 0 */
3687 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3689 for(ref = 0; ref < pRef->number >> 3; ref++) {
3690 char *refname;
3691 unsigned int lib_offs, type_num;
3693 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3695 name += SLTG_ReadStringA(name, &refname);
3696 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3697 FIXME_(typelib)("Can't sscanf ref\n");
3698 if(lib_offs != 0xffff) {
3699 TLBImpLib *import;
3701 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3702 if(import->offset == lib_offs)
3703 break;
3705 if(&import->entry == &pTL->implib_list) {
3706 char fname[MAX_PATH+1];
3707 int len;
3709 import = heap_alloc_zero(sizeof(*import));
3710 import->offset = lib_offs;
3711 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3712 &import->guid);
3713 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3714 &import->wVersionMajor,
3715 &import->wVersionMinor,
3716 &import->lcid, fname) != 4) {
3717 FIXME_(typelib)("can't sscanf ref %s\n",
3718 pNameTable + lib_offs + 40);
3720 len = strlen(fname);
3721 if(fname[len-1] != '#')
3722 FIXME("fname = %s\n", fname);
3723 fname[len-1] = '\0';
3724 import->name = TLB_MultiByteToBSTR(fname);
3725 list_add_tail(&pTL->implib_list, &import->entry);
3727 ref_type->pImpTLInfo = import;
3729 /* Store a reference to IDispatch */
3730 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid, &IID_StdOle) && type_num == 4)
3731 pTL->dispatch_href = typelib_ref;
3733 } else { /* internal ref */
3734 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3736 ref_type->reference = typelib_ref;
3737 ref_type->index = type_num;
3739 heap_free(refname);
3740 list_add_tail(&pTL->ref_list, &ref_type->entry);
3742 table->refs[ref] = typelib_ref;
3743 typelib_ref += 4;
3745 if((BYTE)*name != SLTG_REF_MAGIC)
3746 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3747 dump_TLBRefType(pTL);
3748 return table;
3751 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3752 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3754 SLTG_ImplInfo *info;
3755 TLBImplType *pImplType;
3756 /* I don't really get this structure, usually it's 0x16 bytes
3757 long, but iuser.tlb contains some that are 0x18 bytes long.
3758 That's ok because we can use the next ptr to jump to the next
3759 one. But how do we know the length of the last one? The WORD
3760 at offs 0x8 might be the clue. For now I'm just assuming that
3761 the last one is the regular 0x16 bytes. */
3763 info = (SLTG_ImplInfo*)pBlk;
3764 while(1){
3765 pTI->TypeAttr.cImplTypes++;
3766 if(info->next == 0xffff)
3767 break;
3768 info = (SLTG_ImplInfo*)(pBlk + info->next);
3771 info = (SLTG_ImplInfo*)pBlk;
3772 pTI->impltypes = TLBImplType_Alloc(pTI->TypeAttr.cImplTypes);
3773 pImplType = pTI->impltypes;
3774 while(1) {
3775 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3776 pImplType->implflags = info->impltypeflags;
3777 ++pImplType;
3779 if(info->next == 0xffff)
3780 break;
3781 if(OneOnly)
3782 FIXME_(typelib)("Interface inheriting more than one interface\n");
3783 info = (SLTG_ImplInfo*)(pBlk + info->next);
3785 info++; /* see comment at top of function */
3786 return (char*)info;
3789 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3790 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3792 TLBVarDesc *pVarDesc;
3793 const TLBString *prevName = NULL;
3794 SLTG_Variable *pItem;
3795 unsigned short i;
3796 WORD *pType;
3798 pVarDesc = pTI->vardescs = TLBVarDesc_Constructor(cVars);
3800 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3801 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3803 pVarDesc->vardesc.memid = pItem->memid;
3805 if (pItem->magic != SLTG_VAR_MAGIC &&
3806 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3807 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3808 return;
3811 if (pItem->name == 0xfffe)
3812 pVarDesc->Name = prevName;
3813 else
3814 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
3816 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
3817 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3818 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3820 if(pItem->flags & 0x02)
3821 pType = &pItem->type;
3822 else
3823 pType = (WORD*)(pBlk + pItem->type);
3825 if (pItem->flags & ~0xda)
3826 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3828 SLTG_DoElem(pType, pBlk,
3829 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3831 if (TRACE_ON(typelib)) {
3832 char buf[300];
3833 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3834 TRACE_(typelib)("elemdescVar: %s\n", buf);
3837 if (pItem->flags & 0x40) {
3838 TRACE_(typelib)("VAR_DISPATCH\n");
3839 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3841 else if (pItem->flags & 0x10) {
3842 TRACE_(typelib)("VAR_CONST\n");
3843 pVarDesc->vardesc.varkind = VAR_CONST;
3844 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3845 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3846 if (pItem->flags & 0x08)
3847 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3848 else {
3849 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3851 case VT_LPSTR:
3852 case VT_LPWSTR:
3853 case VT_BSTR:
3855 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3856 BSTR str;
3857 TRACE_(typelib)("len = %u\n", len);
3858 if (len == 0xffff) {
3859 str = NULL;
3860 } else {
3861 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3862 str = SysAllocStringLen(NULL, alloc_len);
3863 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3865 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3866 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3867 break;
3869 case VT_I2:
3870 case VT_UI2:
3871 case VT_I4:
3872 case VT_UI4:
3873 case VT_INT:
3874 case VT_UINT:
3875 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3876 *(INT*)(pBlk + pItem->byte_offs);
3877 break;
3878 default:
3879 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3883 else {
3884 TRACE_(typelib)("VAR_PERINSTANCE\n");
3885 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3886 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3889 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3890 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3892 if (pItem->flags & 0x80)
3893 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3895 prevName = pVarDesc->Name;
3897 pTI->TypeAttr.cVars = cVars;
3900 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3901 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3903 SLTG_Function *pFunc;
3904 unsigned short i;
3905 TLBFuncDesc *pFuncDesc;
3907 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
3909 pFuncDesc = pTI->funcdescs;
3910 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3911 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3913 int param;
3914 WORD *pType, *pArg;
3916 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3917 case SLTG_FUNCTION_MAGIC:
3918 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3919 break;
3920 case SLTG_DISPATCH_FUNCTION_MAGIC:
3921 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3922 break;
3923 case SLTG_STATIC_FUNCTION_MAGIC:
3924 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
3925 break;
3926 default:
3927 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3928 continue;
3930 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
3932 pFuncDesc->funcdesc.memid = pFunc->dispid;
3933 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
3934 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
3935 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
3936 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3937 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
3939 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3940 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
3942 if(pFunc->retnextopt & 0x80)
3943 pType = &pFunc->rettype;
3944 else
3945 pType = (WORD*)(pBlk + pFunc->rettype);
3947 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
3949 pFuncDesc->funcdesc.lprgelemdescParam =
3950 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
3951 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
3953 pArg = (WORD*)(pBlk + pFunc->arg_off);
3955 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
3956 char *paramName = pNameTable + *pArg;
3957 BOOL HaveOffs;
3958 /* If arg type follows then paramName points to the 2nd
3959 letter of the name, else the next WORD is an offset to
3960 the arg type and paramName points to the first letter.
3961 So let's take one char off paramName and see if we're
3962 pointing at an alpha-numeric char. However if *pArg is
3963 0xffff or 0xfffe then the param has no name, the former
3964 meaning that the next WORD is the type, the latter
3965 meaning that the next WORD is an offset to the type. */
3967 HaveOffs = FALSE;
3968 if(*pArg == 0xffff)
3969 paramName = NULL;
3970 else if(*pArg == 0xfffe) {
3971 paramName = NULL;
3972 HaveOffs = TRUE;
3974 else if(paramName[-1] && !isalnum(paramName[-1]))
3975 HaveOffs = TRUE;
3977 pArg++;
3979 if(HaveOffs) { /* the next word is an offset to type */
3980 pType = (WORD*)(pBlk + *pArg);
3981 SLTG_DoElem(pType, pBlk,
3982 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3983 pArg++;
3984 } else {
3985 if(paramName)
3986 paramName--;
3987 pArg = SLTG_DoElem(pArg, pBlk,
3988 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3991 /* Are we an optional param ? */
3992 if(pFuncDesc->funcdesc.cParams - param <=
3993 pFuncDesc->funcdesc.cParamsOpt)
3994 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3996 if(paramName) {
3997 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
3998 paramName - pNameTable, pTI->pTypeLib);
3999 } else {
4000 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4004 pTI->TypeAttr.cFuncs = cFuncs;
4007 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4008 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4009 SLTG_TypeInfoTail *pTITail)
4011 char *pFirstItem;
4012 sltg_ref_lookup_t *ref_lookup = NULL;
4014 if(pTIHeader->href_table != 0xffffffff) {
4015 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4016 pNameTable);
4019 pFirstItem = pBlk;
4021 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4022 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4024 heap_free(ref_lookup);
4028 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4029 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4030 const SLTG_TypeInfoTail *pTITail)
4032 char *pFirstItem;
4033 sltg_ref_lookup_t *ref_lookup = NULL;
4035 if(pTIHeader->href_table != 0xffffffff) {
4036 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4037 pNameTable);
4040 pFirstItem = pBlk;
4042 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4043 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4046 if (pTITail->funcs_off != 0xffff)
4047 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4049 heap_free(ref_lookup);
4051 if (TRACE_ON(typelib))
4052 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
4055 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4056 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4057 const SLTG_TypeInfoTail *pTITail)
4059 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4062 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4063 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4064 const SLTG_TypeInfoTail *pTITail)
4066 WORD *pType;
4067 sltg_ref_lookup_t *ref_lookup = NULL;
4069 if (pTITail->simple_alias) {
4070 /* if simple alias, no more processing required */
4071 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
4072 return;
4075 if(pTIHeader->href_table != 0xffffffff) {
4076 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4077 pNameTable);
4080 /* otherwise it is an offset to a type */
4081 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4083 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
4085 heap_free(ref_lookup);
4088 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4089 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4090 const SLTG_TypeInfoTail *pTITail)
4092 sltg_ref_lookup_t *ref_lookup = NULL;
4093 if (pTIHeader->href_table != 0xffffffff)
4094 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4095 pNameTable);
4097 if (pTITail->vars_off != 0xffff)
4098 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4100 if (pTITail->funcs_off != 0xffff)
4101 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4103 if (pTITail->impls_off != 0xffff)
4104 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4106 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4107 * of dispinterface functions including the IDispatch ones, so
4108 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4109 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
4111 heap_free(ref_lookup);
4112 if (TRACE_ON(typelib))
4113 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
4116 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4117 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4118 const SLTG_TypeInfoTail *pTITail)
4120 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4123 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4124 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4125 const SLTG_TypeInfoTail *pTITail)
4127 sltg_ref_lookup_t *ref_lookup = NULL;
4128 if (pTIHeader->href_table != 0xffffffff)
4129 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4130 pNameTable);
4132 if (pTITail->vars_off != 0xffff)
4133 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4135 if (pTITail->funcs_off != 0xffff)
4136 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4137 heap_free(ref_lookup);
4138 if (TRACE_ON(typelib))
4139 dump_TypeInfo(pTI);
4142 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4143 manageable copy of it into this */
4144 typedef struct {
4145 WORD small_no;
4146 char *index_name;
4147 char *other_name;
4148 WORD res1a;
4149 WORD name_offs;
4150 WORD more_bytes;
4151 char *extra;
4152 WORD res20;
4153 DWORD helpcontext;
4154 WORD res26;
4155 GUID uuid;
4156 } SLTG_InternalOtherTypeInfo;
4158 /****************************************************************************
4159 * ITypeLib2_Constructor_SLTG
4161 * loading a SLTG typelib from an in-memory image
4163 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4165 ITypeLibImpl *pTypeLibImpl;
4166 SLTG_Header *pHeader;
4167 SLTG_BlkEntry *pBlkEntry;
4168 SLTG_Magic *pMagic;
4169 SLTG_Index *pIndex;
4170 SLTG_Pad9 *pPad9;
4171 LPVOID pBlk, pFirstBlk;
4172 SLTG_LibBlk *pLibBlk;
4173 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4174 char *pAfterOTIBlks = NULL;
4175 char *pNameTable, *ptr;
4176 int i;
4177 DWORD len, order;
4178 ITypeInfoImpl **ppTypeInfoImpl;
4180 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4183 pTypeLibImpl = TypeLibImpl_Constructor();
4184 if (!pTypeLibImpl) return NULL;
4186 pHeader = pLib;
4188 TRACE_(typelib)("header:\n");
4189 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4190 pHeader->nrOfFileBlks );
4191 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4192 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4193 pHeader->SLTG_magic);
4194 return NULL;
4197 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4198 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4200 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4201 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4203 /* Next we have a magic block */
4204 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4206 /* Let's see if we're still in sync */
4207 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4208 sizeof(SLTG_COMPOBJ_MAGIC))) {
4209 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4210 return NULL;
4212 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4213 sizeof(SLTG_DIR_MAGIC))) {
4214 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4215 return NULL;
4218 pIndex = (SLTG_Index*)(pMagic+1);
4220 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4222 pFirstBlk = pPad9 + 1;
4224 /* We'll set up a ptr to the main library block, which is the last one. */
4226 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4227 pBlkEntry[order].next != 0;
4228 order = pBlkEntry[order].next - 1, i++) {
4229 pBlk = (char*)pBlk + pBlkEntry[order].len;
4231 pLibBlk = pBlk;
4233 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4235 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4236 interspersed */
4238 len += 0x40;
4240 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4242 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4245 ptr = (char*)pLibBlk + len;
4247 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4248 WORD w, extra;
4249 len = 0;
4251 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4253 w = *(WORD*)(ptr + 2);
4254 if(w != 0xffff) {
4255 len += w;
4256 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4257 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4258 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4260 w = *(WORD*)(ptr + 4 + len);
4261 if(w != 0xffff) {
4262 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4263 len += w;
4264 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4265 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4266 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4268 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4269 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4270 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4271 if(extra) {
4272 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4273 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4274 len += extra;
4276 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4277 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4278 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4279 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4280 len += sizeof(SLTG_OtherTypeInfo);
4281 ptr += len;
4284 pAfterOTIBlks = ptr;
4286 /* Skip this WORD and get the next DWORD */
4287 len = *(DWORD*)(pAfterOTIBlks + 2);
4289 /* Now add this to pLibBLk look at what we're pointing at and
4290 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4291 dust and we should be pointing at the beginning of the name
4292 table */
4294 pNameTable = (char*)pLibBlk + len;
4296 switch(*(WORD*)pNameTable) {
4297 case 0xffff:
4298 break;
4299 case 0x0200:
4300 pNameTable += 0x20;
4301 break;
4302 default:
4303 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4304 break;
4307 pNameTable += 0x216;
4309 pNameTable += 2;
4311 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4313 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4316 /* Hopefully we now have enough ptrs set up to actually read in
4317 some TypeInfos. It's not clear which order to do them in, so
4318 I'll just follow the links along the BlkEntry chain and read
4319 them in the order in which they are in the file */
4321 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4322 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4324 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4325 pBlkEntry[order].next != 0;
4326 order = pBlkEntry[order].next - 1, i++) {
4328 SLTG_TypeInfoHeader *pTIHeader;
4329 SLTG_TypeInfoTail *pTITail;
4330 SLTG_MemberHeader *pMemHeader;
4332 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4333 FIXME_(typelib)("Index strings don't match\n");
4334 heap_free(pOtherTypeInfoBlks);
4335 return NULL;
4338 pTIHeader = pBlk;
4339 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4340 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4341 heap_free(pOtherTypeInfoBlks);
4342 return NULL;
4344 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4345 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4346 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4348 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4349 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4350 (*ppTypeInfoImpl)->index = i;
4351 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4352 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4353 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
4354 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
4355 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
4356 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
4357 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
4358 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4360 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4361 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4363 if((pTIHeader->typeflags1 & 7) != 2)
4364 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4365 if(pTIHeader->typeflags3 != 2)
4366 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4368 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4369 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4370 typekind_desc[pTIHeader->typekind],
4371 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4372 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4374 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4376 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4378 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4379 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4380 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4382 switch(pTIHeader->typekind) {
4383 case TKIND_ENUM:
4384 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4385 pTIHeader, pTITail);
4386 break;
4388 case TKIND_RECORD:
4389 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4390 pTIHeader, pTITail);
4391 break;
4393 case TKIND_INTERFACE:
4394 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4395 pTIHeader, pTITail);
4396 break;
4398 case TKIND_COCLASS:
4399 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4400 pTIHeader, pTITail);
4401 break;
4403 case TKIND_ALIAS:
4404 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4405 pTIHeader, pTITail);
4406 break;
4408 case TKIND_DISPATCH:
4409 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4410 pTIHeader, pTITail);
4411 break;
4413 case TKIND_MODULE:
4414 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4415 pTIHeader, pTITail);
4416 break;
4418 default:
4419 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4420 break;
4424 /* could get cFuncs, cVars and cImplTypes from here
4425 but we've already set those */
4426 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4427 X(06);
4428 X(16);
4429 X(18);
4430 X(1a);
4431 X(1e);
4432 X(24);
4433 X(26);
4434 X(2a);
4435 X(2c);
4436 X(2e);
4437 X(30);
4438 X(32);
4439 X(34);
4440 #undef X
4441 ++ppTypeInfoImpl;
4442 pBlk = (char*)pBlk + pBlkEntry[order].len;
4445 if(i != pTypeLibImpl->TypeInfoCount) {
4446 FIXME("Somehow processed %d TypeInfos\n", i);
4447 heap_free(pOtherTypeInfoBlks);
4448 return NULL;
4451 heap_free(pOtherTypeInfoBlks);
4452 return &pTypeLibImpl->ITypeLib2_iface;
4455 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4457 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4459 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4461 if(IsEqualIID(riid, &IID_IUnknown) ||
4462 IsEqualIID(riid,&IID_ITypeLib)||
4463 IsEqualIID(riid,&IID_ITypeLib2))
4465 *ppv = &This->ITypeLib2_iface;
4467 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4468 IsEqualIID(riid, &IID_ICreateTypeLib2))
4470 *ppv = &This->ICreateTypeLib2_iface;
4472 else
4474 *ppv = NULL;
4475 TRACE("-- Interface: E_NOINTERFACE\n");
4476 return E_NOINTERFACE;
4479 IUnknown_AddRef((IUnknown*)*ppv);
4480 return S_OK;
4483 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4485 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4486 ULONG ref = InterlockedIncrement(&This->ref);
4488 TRACE("(%p) ref=%u\n", This, ref);
4490 return ref;
4493 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4495 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4496 ULONG ref = InterlockedDecrement(&This->ref);
4498 TRACE("(%p) ref=%u\n",This, ref);
4500 if (!ref)
4502 TLBImpLib *pImpLib, *pImpLibNext;
4503 TLBRefType *ref_type;
4504 TLBString *tlbstr, *tlbstr_next;
4505 void *cursor2;
4506 int i;
4508 /* remove cache entry */
4509 if(This->path)
4511 TRACE("removing from cache list\n");
4512 EnterCriticalSection(&cache_section);
4513 if(This->entry.next)
4514 list_remove(&This->entry);
4515 LeaveCriticalSection(&cache_section);
4516 heap_free(This->path);
4518 TRACE(" destroying ITypeLib(%p)\n",This);
4520 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4521 list_remove(&tlbstr->entry);
4522 heap_free(tlbstr);
4525 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4526 list_remove(&tlbstr->entry);
4527 heap_free(tlbstr);
4530 TLB_FreeCustData(&This->custdata_list);
4532 for (i = 0; i < This->ctTypeDesc; i++)
4533 if (This->pTypeDesc[i].vt == VT_CARRAY)
4534 heap_free(This->pTypeDesc[i].u.lpadesc);
4536 heap_free(This->pTypeDesc);
4538 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4540 if (pImpLib->pImpTypeLib)
4541 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4542 SysFreeString(pImpLib->name);
4544 list_remove(&pImpLib->entry);
4545 heap_free(pImpLib);
4548 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4550 list_remove(&ref_type->entry);
4551 heap_free(ref_type);
4554 for (i = 0; i < This->TypeInfoCount; ++i)
4555 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4556 heap_free(This->typeinfos);
4557 heap_free(This);
4558 return 0;
4561 return ref;
4564 /* ITypeLib::GetTypeInfoCount
4566 * Returns the number of type descriptions in the type library
4568 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4570 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4571 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4572 return This->TypeInfoCount;
4575 /* ITypeLib::GetTypeInfo
4577 * retrieves the specified type description in the library.
4579 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4580 ITypeLib2 *iface,
4581 UINT index,
4582 ITypeInfo **ppTInfo)
4584 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4586 TRACE("%p %u %p\n", This, index, ppTInfo);
4588 if(!ppTInfo)
4589 return E_INVALIDARG;
4591 if(index >= This->TypeInfoCount)
4592 return TYPE_E_ELEMENTNOTFOUND;
4594 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4595 ITypeInfo_AddRef(*ppTInfo);
4597 return S_OK;
4601 /* ITypeLibs::GetTypeInfoType
4603 * Retrieves the type of a type description.
4605 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4606 ITypeLib2 *iface,
4607 UINT index,
4608 TYPEKIND *pTKind)
4610 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4612 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4614 if(!pTKind)
4615 return E_INVALIDARG;
4617 if(index >= This->TypeInfoCount)
4618 return TYPE_E_ELEMENTNOTFOUND;
4620 *pTKind = This->typeinfos[index]->TypeAttr.typekind;
4622 return S_OK;
4625 /* ITypeLib::GetTypeInfoOfGuid
4627 * Retrieves the type description that corresponds to the specified GUID.
4630 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4631 ITypeLib2 *iface,
4632 REFGUID guid,
4633 ITypeInfo **ppTInfo)
4635 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4636 int i;
4638 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4640 for(i = 0; i < This->TypeInfoCount; ++i){
4641 if(IsEqualIID(&This->typeinfos[i]->TypeAttr.guid, guid)){
4642 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4643 ITypeInfo_AddRef(*ppTInfo);
4644 return S_OK;
4648 return TYPE_E_ELEMENTNOTFOUND;
4651 /* ITypeLib::GetLibAttr
4653 * Retrieves the structure that contains the library's attributes.
4656 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4657 ITypeLib2 *iface,
4658 LPTLIBATTR *attr)
4660 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4662 TRACE("(%p, %p)\n", This, attr);
4664 if (!attr) return E_INVALIDARG;
4666 *attr = heap_alloc(sizeof(**attr));
4667 if (!*attr) return E_OUTOFMEMORY;
4669 (*attr)->guid = This->guid;
4670 (*attr)->lcid = This->set_lcid;
4671 (*attr)->syskind = This->syskind;
4672 (*attr)->wMajorVerNum = This->ver_major;
4673 (*attr)->wMinorVerNum = This->ver_minor;
4674 (*attr)->wLibFlags = This->libflags;
4676 return S_OK;
4679 /* ITypeLib::GetTypeComp
4681 * Enables a client compiler to bind to a library's types, variables,
4682 * constants, and global functions.
4685 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4686 ITypeLib2 *iface,
4687 ITypeComp **ppTComp)
4689 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4691 TRACE("(%p)->(%p)\n",This,ppTComp);
4692 *ppTComp = &This->ITypeComp_iface;
4693 ITypeComp_AddRef(*ppTComp);
4695 return S_OK;
4698 /* ITypeLib::GetDocumentation
4700 * Retrieves the library's documentation string, the complete Help file name
4701 * and path, and the context identifier for the library Help topic in the Help
4702 * file.
4704 * On a successful return all non-null BSTR pointers will have been set,
4705 * possibly to NULL.
4707 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4708 ITypeLib2 *iface,
4709 INT index,
4710 BSTR *pBstrName,
4711 BSTR *pBstrDocString,
4712 DWORD *pdwHelpContext,
4713 BSTR *pBstrHelpFile)
4715 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4716 HRESULT result = E_INVALIDARG;
4717 ITypeInfo *pTInfo;
4719 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4720 This, index,
4721 pBstrName, pBstrDocString,
4722 pdwHelpContext, pBstrHelpFile);
4724 if(index<0)
4726 /* documentation for the typelib */
4727 if(pBstrName)
4729 if (This->Name)
4731 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4732 goto memerr1;
4734 else
4735 *pBstrName = NULL;
4737 if(pBstrDocString)
4739 if (This->DocString)
4741 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4742 goto memerr2;
4744 else if (This->Name)
4746 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->Name))))
4747 goto memerr2;
4749 else
4750 *pBstrDocString = NULL;
4752 if(pdwHelpContext)
4754 *pdwHelpContext = This->dwHelpContext;
4756 if(pBstrHelpFile)
4758 if (This->HelpFile)
4760 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4761 goto memerr3;
4763 else
4764 *pBstrHelpFile = NULL;
4767 result = S_OK;
4769 else
4771 /* for a typeinfo */
4772 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4774 if(SUCCEEDED(result))
4776 result = ITypeInfo_GetDocumentation(pTInfo,
4777 MEMBERID_NIL,
4778 pBstrName,
4779 pBstrDocString,
4780 pdwHelpContext, pBstrHelpFile);
4782 ITypeInfo_Release(pTInfo);
4785 return result;
4786 memerr3:
4787 if (pBstrDocString) SysFreeString (*pBstrDocString);
4788 memerr2:
4789 if (pBstrName) SysFreeString (*pBstrName);
4790 memerr1:
4791 return STG_E_INSUFFICIENTMEMORY;
4794 /* ITypeLib::IsName
4796 * Indicates whether a passed-in string contains the name of a type or member
4797 * described in the library.
4800 static HRESULT WINAPI ITypeLib2_fnIsName(
4801 ITypeLib2 *iface,
4802 LPOLESTR szNameBuf,
4803 ULONG lHashVal,
4804 BOOL *pfName)
4806 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4807 int tic;
4808 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
4810 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4811 pfName);
4813 *pfName=TRUE;
4814 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4815 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4816 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4817 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4818 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4819 int pc;
4820 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4821 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
4822 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
4823 goto ITypeLib2_fnIsName_exit;
4826 for(vrc = 0; vrc < pTInfo->TypeAttr.cVars; ++vrc){
4827 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4828 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4832 *pfName=FALSE;
4834 ITypeLib2_fnIsName_exit:
4835 TRACE("(%p)slow! search for %s: %s found!\n", This,
4836 debugstr_w(szNameBuf), *pfName?"NOT":"");
4838 return S_OK;
4841 /* ITypeLib::FindName
4843 * Finds occurrences of a type description in a type library. This may be used
4844 * to quickly verify that a name exists in a type library.
4847 static HRESULT WINAPI ITypeLib2_fnFindName(
4848 ITypeLib2 *iface,
4849 LPOLESTR name,
4850 ULONG hash,
4851 ITypeInfo **ppTInfo,
4852 MEMBERID *memid,
4853 UINT16 *found)
4855 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4856 int tic;
4857 UINT count = 0;
4858 UINT len;
4860 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4862 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4863 return E_INVALIDARG;
4865 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4866 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4867 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4868 TLBVarDesc *var;
4869 UINT fdc;
4871 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4872 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4873 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4874 int pc;
4876 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4877 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4878 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
4879 goto ITypeLib2_fnFindName_exit;
4883 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->TypeAttr.cVars, name);
4884 if (var)
4885 goto ITypeLib2_fnFindName_exit;
4887 continue;
4888 ITypeLib2_fnFindName_exit:
4889 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4890 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4891 count++;
4893 TRACE("found %d typeinfos\n", count);
4895 *found = count;
4897 return S_OK;
4900 /* ITypeLib::ReleaseTLibAttr
4902 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4905 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4906 ITypeLib2 *iface,
4907 TLIBATTR *pTLibAttr)
4909 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4910 TRACE("(%p)->(%p)\n", This, pTLibAttr);
4911 heap_free(pTLibAttr);
4914 /* ITypeLib2::GetCustData
4916 * gets the custom data
4918 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4919 ITypeLib2 * iface,
4920 REFGUID guid,
4921 VARIANT *pVarVal)
4923 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4924 TLBCustData *pCData;
4926 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
4928 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
4929 if(!pCData)
4930 return TYPE_E_ELEMENTNOTFOUND;
4932 VariantInit(pVarVal);
4933 VariantCopy(pVarVal, &pCData->data);
4935 return S_OK;
4938 /* ITypeLib2::GetLibStatistics
4940 * Returns statistics about a type library that are required for efficient
4941 * sizing of hash tables.
4944 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4945 ITypeLib2 * iface,
4946 ULONG *pcUniqueNames,
4947 ULONG *pcchUniqueNames)
4949 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4951 FIXME("(%p): stub!\n", This);
4953 if(pcUniqueNames) *pcUniqueNames=1;
4954 if(pcchUniqueNames) *pcchUniqueNames=1;
4955 return S_OK;
4958 /* ITypeLib2::GetDocumentation2
4960 * Retrieves the library's documentation string, the complete Help file name
4961 * and path, the localization context to use, and the context ID for the
4962 * library Help topic in the Help file.
4965 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4966 ITypeLib2 * iface,
4967 INT index,
4968 LCID lcid,
4969 BSTR *pbstrHelpString,
4970 DWORD *pdwHelpStringContext,
4971 BSTR *pbstrHelpStringDll)
4973 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4974 HRESULT result;
4975 ITypeInfo *pTInfo;
4977 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4979 /* the help string should be obtained from the helpstringdll,
4980 * using the _DLLGetDocumentation function, based on the supplied
4981 * lcid. Nice to do sometime...
4983 if(index<0)
4985 /* documentation for the typelib */
4986 if(pbstrHelpString)
4987 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
4988 if(pdwHelpStringContext)
4989 *pdwHelpStringContext=This->dwHelpContext;
4990 if(pbstrHelpStringDll)
4991 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
4993 result = S_OK;
4995 else
4997 /* for a typeinfo */
4998 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5000 if(SUCCEEDED(result))
5002 ITypeInfo2 * pTInfo2;
5003 result = ITypeInfo_QueryInterface(pTInfo,
5004 &IID_ITypeInfo2,
5005 (LPVOID*) &pTInfo2);
5007 if(SUCCEEDED(result))
5009 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5010 MEMBERID_NIL,
5011 lcid,
5012 pbstrHelpString,
5013 pdwHelpStringContext,
5014 pbstrHelpStringDll);
5016 ITypeInfo2_Release(pTInfo2);
5019 ITypeInfo_Release(pTInfo);
5022 return result;
5025 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5027 TLBCustData *pCData;
5028 unsigned int ct;
5029 CUSTDATAITEM *cdi;
5031 ct = list_count(custdata_list);
5033 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5034 if(!pCustData->prgCustData)
5035 return E_OUTOFMEMORY;
5037 pCustData->cCustData = ct;
5039 cdi = pCustData->prgCustData;
5040 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5041 cdi->guid = pCData->guid;
5042 VariantCopy(&cdi->varValue, &pCData->data);
5043 ++cdi;
5046 return S_OK;
5050 /* ITypeLib2::GetAllCustData
5052 * Gets all custom data items for the library.
5055 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5056 ITypeLib2 * iface,
5057 CUSTDATA *pCustData)
5059 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5060 TRACE("(%p)->(%p)\n", This, pCustData);
5061 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5064 static const ITypeLib2Vtbl tlbvt = {
5065 ITypeLib2_fnQueryInterface,
5066 ITypeLib2_fnAddRef,
5067 ITypeLib2_fnRelease,
5068 ITypeLib2_fnGetTypeInfoCount,
5069 ITypeLib2_fnGetTypeInfo,
5070 ITypeLib2_fnGetTypeInfoType,
5071 ITypeLib2_fnGetTypeInfoOfGuid,
5072 ITypeLib2_fnGetLibAttr,
5073 ITypeLib2_fnGetTypeComp,
5074 ITypeLib2_fnGetDocumentation,
5075 ITypeLib2_fnIsName,
5076 ITypeLib2_fnFindName,
5077 ITypeLib2_fnReleaseTLibAttr,
5079 ITypeLib2_fnGetCustData,
5080 ITypeLib2_fnGetLibStatistics,
5081 ITypeLib2_fnGetDocumentation2,
5082 ITypeLib2_fnGetAllCustData
5086 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5088 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5090 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5093 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5095 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5097 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5100 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5102 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5104 return ITypeLib2_Release(&This->ITypeLib2_iface);
5107 static HRESULT WINAPI ITypeLibComp_fnBind(
5108 ITypeComp * iface,
5109 OLECHAR * szName,
5110 ULONG lHash,
5111 WORD wFlags,
5112 ITypeInfo ** ppTInfo,
5113 DESCKIND * pDescKind,
5114 BINDPTR * pBindPtr)
5116 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5117 int typemismatch=0, i;
5119 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5121 *pDescKind = DESCKIND_NONE;
5122 pBindPtr->lptcomp = NULL;
5123 *ppTInfo = NULL;
5125 for(i = 0; i < This->TypeInfoCount; ++i){
5126 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5127 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5129 /* FIXME: check wFlags here? */
5130 /* FIXME: we should use a hash table to look this info up using lHash
5131 * instead of an O(n) search */
5132 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
5133 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
5135 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5137 *pDescKind = DESCKIND_TYPECOMP;
5138 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5139 ITypeComp_AddRef(pBindPtr->lptcomp);
5140 TRACE("module or enum: %s\n", debugstr_w(szName));
5141 return S_OK;
5145 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
5146 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
5148 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5149 HRESULT hr;
5151 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5152 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5154 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5155 return S_OK;
5157 else if (hr == TYPE_E_TYPEMISMATCH)
5158 typemismatch = 1;
5161 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
5162 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5164 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5165 HRESULT hr;
5166 ITypeInfo *subtypeinfo;
5167 BINDPTR subbindptr;
5168 DESCKIND subdesckind;
5170 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5171 &subtypeinfo, &subdesckind, &subbindptr);
5172 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5174 TYPEDESC tdesc_appobject;
5175 const VARDESC vardesc_appobject =
5177 -2, /* memid */
5178 NULL, /* lpstrSchema */
5180 0 /* oInst */
5183 /* ELEMDESC */
5185 /* TYPEDESC */
5187 &tdesc_appobject
5189 VT_PTR
5192 0, /* wVarFlags */
5193 VAR_STATIC /* varkind */
5196 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5197 tdesc_appobject.vt = VT_USERDEFINED;
5199 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5201 /* cleanup things filled in by Bind call so we can put our
5202 * application object data in there instead */
5203 switch (subdesckind)
5205 case DESCKIND_FUNCDESC:
5206 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5207 break;
5208 case DESCKIND_VARDESC:
5209 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5210 break;
5211 default:
5212 break;
5214 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5216 if (pTypeInfo->hreftype == -1)
5217 FIXME("no hreftype for interface %p\n", pTypeInfo);
5219 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5220 if (FAILED(hr))
5221 return hr;
5223 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5224 *ppTInfo = (ITypeInfo *)pTypeInfo;
5225 ITypeInfo_AddRef(*ppTInfo);
5226 return S_OK;
5228 else if (hr == TYPE_E_TYPEMISMATCH)
5229 typemismatch = 1;
5233 if (typemismatch)
5235 TRACE("type mismatch %s\n", debugstr_w(szName));
5236 return TYPE_E_TYPEMISMATCH;
5238 else
5240 TRACE("name not found %s\n", debugstr_w(szName));
5241 return S_OK;
5245 static HRESULT WINAPI ITypeLibComp_fnBindType(
5246 ITypeComp * iface,
5247 OLECHAR * szName,
5248 ULONG lHash,
5249 ITypeInfo ** ppTInfo,
5250 ITypeComp ** ppTComp)
5252 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5253 ITypeInfoImpl *info;
5255 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5257 if(!szName || !ppTInfo || !ppTComp)
5258 return E_INVALIDARG;
5260 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5261 if(!info){
5262 *ppTInfo = NULL;
5263 *ppTComp = NULL;
5264 return S_OK;
5267 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5268 ITypeInfo_AddRef(*ppTInfo);
5269 *ppTComp = &info->ITypeComp_iface;
5270 ITypeComp_AddRef(*ppTComp);
5272 return S_OK;
5275 static const ITypeCompVtbl tlbtcvt =
5278 ITypeLibComp_fnQueryInterface,
5279 ITypeLibComp_fnAddRef,
5280 ITypeLibComp_fnRelease,
5282 ITypeLibComp_fnBind,
5283 ITypeLibComp_fnBindType
5286 /*================== ITypeInfo(2) Methods ===================================*/
5287 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5289 ITypeInfoImpl *pTypeInfoImpl;
5291 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5292 if (pTypeInfoImpl)
5294 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5295 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5296 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5297 pTypeInfoImpl->ref = 0;
5298 pTypeInfoImpl->hreftype = -1;
5299 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
5300 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
5301 list_init(&pTypeInfoImpl->custdata_list);
5303 TRACE("(%p)\n", pTypeInfoImpl);
5304 return pTypeInfoImpl;
5307 /* ITypeInfo::QueryInterface
5309 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5310 ITypeInfo2 *iface,
5311 REFIID riid,
5312 VOID **ppvObject)
5314 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5316 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5318 *ppvObject=NULL;
5319 if(IsEqualIID(riid, &IID_IUnknown) ||
5320 IsEqualIID(riid,&IID_ITypeInfo)||
5321 IsEqualIID(riid,&IID_ITypeInfo2))
5322 *ppvObject = This;
5323 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5324 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5325 *ppvObject = &This->ICreateTypeInfo2_iface;
5327 if(*ppvObject){
5328 ITypeInfo2_AddRef(iface);
5329 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5330 return S_OK;
5332 TRACE("-- Interface: E_NOINTERFACE\n");
5333 return E_NOINTERFACE;
5336 /* ITypeInfo::AddRef
5338 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5340 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5341 ULONG ref = InterlockedIncrement(&This->ref);
5343 TRACE("(%p)->ref is %u\n",This, ref);
5345 if (ref == 1 /* incremented from 0 */)
5346 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5348 return ref;
5351 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5353 UINT i;
5355 TRACE("destroying ITypeInfo(%p)\n",This);
5357 for (i = 0; i < This->TypeAttr.cFuncs; ++i)
5359 int j;
5360 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5361 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5363 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5364 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5366 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5367 heap_free(elemdesc->u.paramdesc.pparamdescex);
5369 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5371 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5372 heap_free(pFInfo->pParamDesc);
5373 TLB_FreeCustData(&pFInfo->custdata_list);
5375 heap_free(This->funcdescs);
5377 for(i = 0; i < This->TypeAttr.cVars; ++i)
5379 TLBVarDesc *pVInfo = &This->vardescs[i];
5380 if (pVInfo->vardesc.varkind == VAR_CONST)
5382 VariantClear(pVInfo->vardesc.u.lpvarValue);
5383 heap_free(pVInfo->vardesc.u.lpvarValue);
5385 TLB_FreeCustData(&pVInfo->custdata_list);
5387 heap_free(This->vardescs);
5389 if(This->impltypes){
5390 for (i = 0; i < This->TypeAttr.cImplTypes; ++i){
5391 TLBImplType *pImpl = &This->impltypes[i];
5392 TLB_FreeCustData(&pImpl->custdata_list);
5394 heap_free(This->impltypes);
5397 TLB_FreeCustData(&This->custdata_list);
5399 heap_free(This);
5402 /* ITypeInfo::Release
5404 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5406 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5407 ULONG ref = InterlockedDecrement(&This->ref);
5409 TRACE("(%p)->(%u)\n",This, ref);
5411 if (!ref)
5413 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5414 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5415 if (not_attached_to_typelib)
5416 heap_free(This);
5417 /* otherwise This will be freed when typelib is freed */
5420 return ref;
5423 /* ITypeInfo::GetTypeAttr
5425 * Retrieves a TYPEATTR structure that contains the attributes of the type
5426 * description.
5429 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5430 LPTYPEATTR *ppTypeAttr)
5432 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5433 SIZE_T size;
5435 TRACE("(%p)\n",This);
5437 size = sizeof(**ppTypeAttr);
5438 if (This->TypeAttr.typekind == TKIND_ALIAS)
5439 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5441 *ppTypeAttr = heap_alloc(size);
5442 if (!*ppTypeAttr)
5443 return E_OUTOFMEMORY;
5445 **ppTypeAttr = This->TypeAttr;
5447 if (This->TypeAttr.typekind == TKIND_ALIAS)
5448 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5449 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5451 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5452 /* This should include all the inherited funcs */
5453 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5454 /* This is always the size of IDispatch's vtbl */
5455 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5456 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5458 return S_OK;
5461 /* ITypeInfo::GetTypeComp
5463 * Retrieves the ITypeComp interface for the type description, which enables a
5464 * client compiler to bind to the type description's members.
5467 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5468 ITypeComp * *ppTComp)
5470 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5472 TRACE("(%p)->(%p)\n", This, ppTComp);
5474 *ppTComp = &This->ITypeComp_iface;
5475 ITypeComp_AddRef(*ppTComp);
5476 return S_OK;
5479 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5481 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5482 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5483 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5484 return size;
5487 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5489 *dest = *src;
5490 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5491 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5493 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5494 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5495 *buffer += sizeof(PARAMDESCEX);
5496 *pparamdescex_dest = *pparamdescex_src;
5497 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5498 VariantInit(&pparamdescex_dest->varDefaultValue);
5499 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5500 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5502 else
5503 dest->u.paramdesc.pparamdescex = NULL;
5504 return S_OK;
5507 static HRESULT TLB_SanitizeBSTR(BSTR str)
5509 UINT len = SysStringLen(str), i;
5510 for (i = 0; i < len; ++i)
5511 if (str[i] > 0x7f)
5512 str[i] = '?';
5513 return S_OK;
5516 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5518 if (V_VT(var) == VT_INT)
5519 return VariantChangeType(var, var, 0, VT_I4);
5520 else if (V_VT(var) == VT_UINT)
5521 return VariantChangeType(var, var, 0, VT_UI4);
5522 else if (V_VT(var) == VT_BSTR)
5523 return TLB_SanitizeBSTR(V_BSTR(var));
5525 return S_OK;
5528 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5530 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5531 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5534 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5536 FUNCDESC *dest;
5537 char *buffer;
5538 SIZE_T size = sizeof(*src);
5539 SHORT i;
5540 HRESULT hr;
5542 size += sizeof(*src->lprgscode) * src->cScodes;
5543 size += TLB_SizeElemDesc(&src->elemdescFunc);
5544 for (i = 0; i < src->cParams; i++)
5546 size += sizeof(ELEMDESC);
5547 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5550 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5551 if (!dest) return E_OUTOFMEMORY;
5553 *dest = *src;
5554 if (dispinterface) /* overwrite funckind */
5555 dest->funckind = FUNC_DISPATCH;
5556 buffer = (char *)(dest + 1);
5558 dest->oVft = dest->oVft & 0xFFFC;
5560 if (dest->cScodes) {
5561 dest->lprgscode = (SCODE *)buffer;
5562 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5563 buffer += sizeof(*src->lprgscode) * src->cScodes;
5564 } else
5565 dest->lprgscode = NULL;
5567 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5568 if (FAILED(hr))
5570 SysFreeString((BSTR)dest);
5571 return hr;
5574 if (dest->cParams) {
5575 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5576 buffer += sizeof(ELEMDESC) * src->cParams;
5577 for (i = 0; i < src->cParams; i++)
5579 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5580 if (FAILED(hr))
5581 break;
5583 if (FAILED(hr))
5585 /* undo the above actions */
5586 for (i = i - 1; i >= 0; i--)
5587 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5588 TLB_FreeElemDesc(&dest->elemdescFunc);
5589 SysFreeString((BSTR)dest);
5590 return hr;
5592 } else
5593 dest->lprgelemdescParam = NULL;
5595 /* special treatment for dispinterfaces: this makes functions appear
5596 * to return their [retval] value when it is really returning an
5597 * HRESULT */
5598 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5600 if (dest->cParams &&
5601 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5603 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5604 if (elemdesc->tdesc.vt != VT_PTR)
5606 ERR("elemdesc should have started with VT_PTR instead of:\n");
5607 if (ERR_ON(ole))
5608 dump_ELEMDESC(elemdesc);
5609 return E_UNEXPECTED;
5612 /* copy last parameter to the return value. we are using a flat
5613 * buffer so there is no danger of leaking memory in
5614 * elemdescFunc */
5615 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5617 /* remove the last parameter */
5618 dest->cParams--;
5620 else
5621 /* otherwise this function is made to appear to have no return
5622 * value */
5623 dest->elemdescFunc.tdesc.vt = VT_VOID;
5627 *dest_ptr = dest;
5628 return S_OK;
5631 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5633 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5635 if (index >= This->TypeAttr.cFuncs)
5636 return TYPE_E_ELEMENTNOTFOUND;
5638 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5639 return S_OK;
5642 /* internal function to make the inherited interfaces' methods appear
5643 * part of the interface */
5644 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5645 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5647 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5648 HRESULT hr;
5649 UINT implemented_funcs = 0;
5651 if (funcs)
5652 *funcs = 0;
5653 else
5654 *hrefoffset = DISPATCH_HREF_OFFSET;
5656 if(This->impltypes)
5658 ITypeInfo *pSubTypeInfo;
5659 UINT sub_funcs;
5661 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5662 if (FAILED(hr))
5663 return hr;
5665 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5666 index,
5667 ppFuncDesc,
5668 &sub_funcs, hrefoffset);
5669 implemented_funcs += sub_funcs;
5670 ITypeInfo_Release(pSubTypeInfo);
5671 if (SUCCEEDED(hr))
5672 return hr;
5673 *hrefoffset += DISPATCH_HREF_OFFSET;
5676 if (funcs)
5677 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5678 else
5679 *hrefoffset = 0;
5681 if (index < implemented_funcs)
5682 return E_INVALIDARG;
5683 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5684 ppFuncDesc);
5687 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5689 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5690 while (TRUE)
5692 switch (pTypeDesc->vt)
5694 case VT_USERDEFINED:
5695 pTypeDesc->u.hreftype += hrefoffset;
5696 return;
5697 case VT_PTR:
5698 case VT_SAFEARRAY:
5699 pTypeDesc = pTypeDesc->u.lptdesc;
5700 break;
5701 case VT_CARRAY:
5702 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5703 break;
5704 default:
5705 return;
5710 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5712 SHORT i;
5713 for (i = 0; i < pFuncDesc->cParams; i++)
5714 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5715 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5718 /* ITypeInfo::GetFuncDesc
5720 * Retrieves the FUNCDESC structure that contains information about a
5721 * specified function.
5724 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5725 LPFUNCDESC *ppFuncDesc)
5727 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5728 const FUNCDESC *internal_funcdesc;
5729 HRESULT hr;
5730 UINT hrefoffset = 0;
5732 TRACE("(%p) index %d\n", This, index);
5734 if (!ppFuncDesc)
5735 return E_INVALIDARG;
5737 if (This->needs_layout)
5738 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5740 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5741 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5742 &internal_funcdesc, NULL,
5743 &hrefoffset);
5744 else
5745 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5746 &internal_funcdesc);
5747 if (FAILED(hr))
5749 WARN("description for function %d not found\n", index);
5750 return hr;
5753 hr = TLB_AllocAndInitFuncDesc(
5754 internal_funcdesc,
5755 ppFuncDesc,
5756 This->TypeAttr.typekind == TKIND_DISPATCH);
5758 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5759 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5761 TRACE("-- 0x%08x\n", hr);
5762 return hr;
5765 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5767 VARDESC *dest;
5768 char *buffer;
5769 SIZE_T size = sizeof(*src);
5770 HRESULT hr;
5772 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5773 if (src->varkind == VAR_CONST)
5774 size += sizeof(VARIANT);
5775 size += TLB_SizeElemDesc(&src->elemdescVar);
5777 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5778 if (!dest) return E_OUTOFMEMORY;
5780 *dest = *src;
5781 buffer = (char *)(dest + 1);
5782 if (src->lpstrSchema)
5784 int len;
5785 dest->lpstrSchema = (LPOLESTR)buffer;
5786 len = strlenW(src->lpstrSchema);
5787 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5788 buffer += (len + 1) * sizeof(WCHAR);
5791 if (src->varkind == VAR_CONST)
5793 HRESULT hr;
5795 dest->u.lpvarValue = (VARIANT *)buffer;
5796 *dest->u.lpvarValue = *src->u.lpvarValue;
5797 buffer += sizeof(VARIANT);
5798 VariantInit(dest->u.lpvarValue);
5799 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5800 if (FAILED(hr))
5802 SysFreeString((BSTR)dest);
5803 return hr;
5806 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5807 if (FAILED(hr))
5809 if (src->varkind == VAR_CONST)
5810 VariantClear(dest->u.lpvarValue);
5811 SysFreeString((BSTR)dest);
5812 return hr;
5814 *dest_ptr = dest;
5815 return S_OK;
5818 /* ITypeInfo::GetVarDesc
5820 * Retrieves a VARDESC structure that describes the specified variable.
5823 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5824 LPVARDESC *ppVarDesc)
5826 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5827 const TLBVarDesc *pVDesc = &This->vardescs[index];
5829 TRACE("(%p) index %d\n", This, index);
5831 if(index >= This->TypeAttr.cVars)
5832 return TYPE_E_ELEMENTNOTFOUND;
5834 if (This->needs_layout)
5835 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5837 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5840 /* ITypeInfo_GetNames
5842 * Retrieves the variable with the specified member ID (or the name of the
5843 * property or method and its parameters) that correspond to the specified
5844 * function ID.
5846 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5847 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5849 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5850 const TLBFuncDesc *pFDesc;
5851 const TLBVarDesc *pVDesc;
5852 int i;
5853 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5854 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
5855 if(pFDesc)
5857 /* function found, now return function and parameter names */
5858 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5860 if(!i)
5861 *rgBstrNames=SysAllocString(TLB_get_bstr(pFDesc->Name));
5862 else
5863 rgBstrNames[i]=SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i-1].Name));
5865 *pcNames=i;
5867 else
5869 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
5870 if(pVDesc)
5872 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
5873 *pcNames=1;
5875 else
5877 if(This->impltypes &&
5878 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5879 /* recursive search */
5880 ITypeInfo *pTInfo;
5881 HRESULT result;
5882 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5883 if(SUCCEEDED(result))
5885 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5886 ITypeInfo_Release(pTInfo);
5887 return result;
5889 WARN("Could not search inherited interface!\n");
5891 else
5893 WARN("no names found\n");
5895 *pcNames=0;
5896 return TYPE_E_ELEMENTNOTFOUND;
5899 return S_OK;
5903 /* ITypeInfo::GetRefTypeOfImplType
5905 * If a type description describes a COM class, it retrieves the type
5906 * description of the implemented interface types. For an interface,
5907 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5908 * if any exist.
5911 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5912 ITypeInfo2 *iface,
5913 UINT index,
5914 HREFTYPE *pRefType)
5916 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5917 HRESULT hr = S_OK;
5919 TRACE("(%p) index %d\n", This, index);
5920 if (TRACE_ON(ole)) dump_TypeInfo(This);
5922 if(index==(UINT)-1)
5924 /* only valid on dual interfaces;
5925 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5928 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5930 *pRefType = -2;
5932 else
5934 hr = TYPE_E_ELEMENTNOTFOUND;
5937 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5939 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5940 *pRefType = This->pTypeLib->dispatch_href;
5942 else
5944 if(index >= This->TypeAttr.cImplTypes)
5945 hr = TYPE_E_ELEMENTNOTFOUND;
5946 else
5947 *pRefType = This->impltypes[index].hRef;
5950 if(TRACE_ON(ole))
5952 if(SUCCEEDED(hr))
5953 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5954 else
5955 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5958 return hr;
5961 /* ITypeInfo::GetImplTypeFlags
5963 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5964 * or base interface in a type description.
5966 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5967 UINT index, INT *pImplTypeFlags)
5969 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5971 TRACE("(%p) index %d\n", This, index);
5973 if(!pImplTypeFlags)
5974 return E_INVALIDARG;
5976 if(This->TypeAttr.typekind == TKIND_DISPATCH && index == 0){
5977 *pImplTypeFlags = 0;
5978 return S_OK;
5981 if(index >= This->TypeAttr.cImplTypes)
5982 return TYPE_E_ELEMENTNOTFOUND;
5984 *pImplTypeFlags = This->impltypes[index].implflags;
5986 return S_OK;
5989 /* GetIDsOfNames
5990 * Maps between member names and member IDs, and parameter names and
5991 * parameter IDs.
5993 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5994 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5996 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5997 const TLBVarDesc *pVDesc;
5998 HRESULT ret=S_OK;
5999 UINT i, fdc;
6001 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6002 cNames);
6004 /* init out parameters in case of failure */
6005 for (i = 0; i < cNames; i++)
6006 pMemId[i] = MEMBERID_NIL;
6008 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc) {
6009 int j;
6010 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6011 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6012 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6013 for(i=1; i < cNames; i++){
6014 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6015 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6016 break;
6017 if( j<pFDesc->funcdesc.cParams)
6018 pMemId[i]=j;
6019 else
6020 ret=DISP_E_UNKNOWNNAME;
6022 TRACE("-- 0x%08x\n", ret);
6023 return ret;
6026 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, *rgszNames);
6027 if(pVDesc){
6028 if(cNames)
6029 *pMemId = pVDesc->vardesc.memid;
6030 return ret;
6032 /* not found, see if it can be found in an inherited interface */
6033 if(This->impltypes) {
6034 /* recursive search */
6035 ITypeInfo *pTInfo;
6036 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6037 if(SUCCEEDED(ret)){
6038 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6039 ITypeInfo_Release(pTInfo);
6040 return ret;
6042 WARN("Could not search inherited interface!\n");
6043 } else
6044 WARN("no names found\n");
6045 return DISP_E_UNKNOWNNAME;
6049 #ifdef __i386__
6051 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6052 __ASM_GLOBAL_FUNC( call_method,
6053 "pushl %ebp\n\t"
6054 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6055 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6056 "movl %esp,%ebp\n\t"
6057 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6058 "pushl %esi\n\t"
6059 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6060 "pushl %edi\n\t"
6061 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6062 "movl 12(%ebp),%edx\n\t"
6063 "movl %esp,%edi\n\t"
6064 "shll $2,%edx\n\t"
6065 "jz 1f\n\t"
6066 "subl %edx,%edi\n\t"
6067 "andl $~15,%edi\n\t"
6068 "movl %edi,%esp\n\t"
6069 "movl 12(%ebp),%ecx\n\t"
6070 "movl 16(%ebp),%esi\n\t"
6071 "cld\n\t"
6072 "rep; movsl\n"
6073 "1:\tcall *8(%ebp)\n\t"
6074 "subl %esp,%edi\n\t"
6075 "movl 20(%ebp),%ecx\n\t"
6076 "movl %edi,(%ecx)\n\t"
6077 "leal -8(%ebp),%esp\n\t"
6078 "popl %edi\n\t"
6079 __ASM_CFI(".cfi_same_value %edi\n\t")
6080 "popl %esi\n\t"
6081 __ASM_CFI(".cfi_same_value %esi\n\t")
6082 "popl %ebp\n\t"
6083 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6084 __ASM_CFI(".cfi_same_value %ebp\n\t")
6085 "ret" )
6087 /* same function but returning floating point */
6088 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6090 /* ITypeInfo::Invoke
6092 * Invokes a method, or accesses a property of an object, that implements the
6093 * interface described by the type description.
6095 DWORD
6096 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6097 DWORD res;
6098 int stack_offset;
6100 if (TRACE_ON(ole)) {
6101 int i;
6102 TRACE("Calling %p(",func);
6103 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6104 if (nrargs > 30) TRACE("...");
6105 TRACE(")\n");
6108 switch (callconv) {
6109 case CC_STDCALL:
6110 case CC_CDECL:
6111 res = call_method( func, nrargs, args, &stack_offset );
6112 break;
6113 default:
6114 FIXME("unsupported calling convention %d\n",callconv);
6115 res = -1;
6116 break;
6118 TRACE("returns %08x\n",res);
6119 return res;
6122 #elif defined(__x86_64__)
6124 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6125 __ASM_GLOBAL_FUNC( call_method,
6126 "pushq %rbp\n\t"
6127 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6128 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6129 "movq %rsp,%rbp\n\t"
6130 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6131 "pushq %rsi\n\t"
6132 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6133 "pushq %rdi\n\t"
6134 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6135 "movq %rcx,%rax\n\t"
6136 "movq $4,%rcx\n\t"
6137 "cmp %rcx,%rdx\n\t"
6138 "cmovgq %rdx,%rcx\n\t"
6139 "leaq 0(,%rcx,8),%rdx\n\t"
6140 "subq %rdx,%rsp\n\t"
6141 "andq $~15,%rsp\n\t"
6142 "movq %rsp,%rdi\n\t"
6143 "movq %r8,%rsi\n\t"
6144 "rep; movsq\n\t"
6145 "movq 0(%rsp),%rcx\n\t"
6146 "movq 8(%rsp),%rdx\n\t"
6147 "movq 16(%rsp),%r8\n\t"
6148 "movq 24(%rsp),%r9\n\t"
6149 "movq %rcx,%xmm0\n\t"
6150 "movq %rdx,%xmm1\n\t"
6151 "movq %r8,%xmm2\n\t"
6152 "movq %r9,%xmm3\n\t"
6153 "callq *%rax\n\t"
6154 "leaq -16(%rbp),%rsp\n\t"
6155 "popq %rdi\n\t"
6156 __ASM_CFI(".cfi_same_value %rdi\n\t")
6157 "popq %rsi\n\t"
6158 __ASM_CFI(".cfi_same_value %rsi\n\t")
6159 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6160 "popq %rbp\n\t"
6161 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6162 __ASM_CFI(".cfi_same_value %rbp\n\t")
6163 "ret")
6165 /* same function but returning floating point */
6166 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6168 #endif /* __x86_64__ */
6170 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6172 HRESULT hr = S_OK;
6173 ITypeInfo *tinfo2 = NULL;
6174 TYPEATTR *tattr = NULL;
6176 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6177 if (hr)
6179 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6180 "hr = 0x%08x\n",
6181 tdesc->u.hreftype, hr);
6182 return hr;
6184 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6185 if (hr)
6187 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6188 ITypeInfo_Release(tinfo2);
6189 return hr;
6192 switch (tattr->typekind)
6194 case TKIND_ENUM:
6195 *vt |= VT_I4;
6196 break;
6198 case TKIND_ALIAS:
6199 tdesc = &tattr->tdescAlias;
6200 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6201 break;
6203 case TKIND_INTERFACE:
6204 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6205 *vt |= VT_DISPATCH;
6206 else
6207 *vt |= VT_UNKNOWN;
6208 break;
6210 case TKIND_DISPATCH:
6211 *vt |= VT_DISPATCH;
6212 break;
6214 case TKIND_COCLASS:
6215 *vt |= VT_DISPATCH;
6216 break;
6218 case TKIND_RECORD:
6219 FIXME("TKIND_RECORD unhandled.\n");
6220 hr = E_NOTIMPL;
6221 break;
6223 case TKIND_UNION:
6224 FIXME("TKIND_UNION unhandled.\n");
6225 hr = E_NOTIMPL;
6226 break;
6228 default:
6229 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6230 hr = E_NOTIMPL;
6231 break;
6233 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6234 ITypeInfo_Release(tinfo2);
6235 return hr;
6238 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6240 HRESULT hr = S_OK;
6242 /* enforce only one level of pointer indirection */
6243 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6245 tdesc = tdesc->u.lptdesc;
6247 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6248 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6249 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6250 if ((tdesc->vt == VT_USERDEFINED) ||
6251 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6253 VARTYPE vt_userdefined = 0;
6254 const TYPEDESC *tdesc_userdefined = tdesc;
6255 if (tdesc->vt == VT_PTR)
6257 vt_userdefined = VT_BYREF;
6258 tdesc_userdefined = tdesc->u.lptdesc;
6260 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6261 if ((hr == S_OK) &&
6262 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6263 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6265 *vt |= vt_userdefined;
6266 return S_OK;
6269 *vt = VT_BYREF;
6272 switch (tdesc->vt)
6274 case VT_HRESULT:
6275 *vt |= VT_ERROR;
6276 break;
6277 case VT_USERDEFINED:
6278 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6279 break;
6280 case VT_VOID:
6281 case VT_CARRAY:
6282 case VT_PTR:
6283 case VT_LPSTR:
6284 case VT_LPWSTR:
6285 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6286 hr = DISP_E_BADVARTYPE;
6287 break;
6288 case VT_SAFEARRAY:
6289 *vt |= VT_ARRAY;
6290 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6291 break;
6292 case VT_INT:
6293 *vt |= VT_I4;
6294 break;
6295 case VT_UINT:
6296 *vt |= VT_UI4;
6297 break;
6298 default:
6299 *vt |= tdesc->vt;
6300 break;
6302 return hr;
6305 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6307 ITypeInfo *tinfo2;
6308 TYPEATTR *tattr;
6309 HRESULT hres;
6311 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6312 if(FAILED(hres))
6313 return hres;
6315 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6316 if(FAILED(hres)) {
6317 ITypeInfo_Release(tinfo2);
6318 return hres;
6321 switch(tattr->typekind) {
6322 case TKIND_ALIAS:
6323 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6324 break;
6326 case TKIND_INTERFACE:
6327 case TKIND_DISPATCH:
6328 *guid = tattr->guid;
6329 break;
6331 default:
6332 ERR("Unexpected typekind %d\n", tattr->typekind);
6333 hres = E_UNEXPECTED;
6336 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6337 ITypeInfo_Release(tinfo2);
6338 return hres;
6341 /***********************************************************************
6342 * DispCallFunc (OLEAUT32.@)
6344 * Invokes a function of the specified calling convention, passing the
6345 * specified arguments and returns the result.
6347 * PARAMS
6348 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6349 * oVft [I] The offset in the vtable. See notes.
6350 * cc [I] Calling convention of the function to call.
6351 * vtReturn [I] The return type of the function.
6352 * cActuals [I] Number of parameters.
6353 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6354 * prgpvarg [I] The arguments to pass.
6355 * pvargResult [O] The return value of the function. Can be NULL.
6357 * RETURNS
6358 * Success: S_OK.
6359 * Failure: HRESULT code.
6361 * NOTES
6362 * The HRESULT return value of this function is not affected by the return
6363 * value of the user supplied function, which is returned in pvargResult.
6365 * If pvInstance is NULL then a non-object function is to be called and oVft
6366 * is the address of the function to call.
6368 * The cc parameter can be one of the following values:
6369 *|CC_FASTCALL
6370 *|CC_CDECL
6371 *|CC_PASCAL
6372 *|CC_STDCALL
6373 *|CC_FPFASTCALL
6374 *|CC_SYSCALL
6375 *|CC_MPWCDECL
6376 *|CC_MPWPASCAL
6379 HRESULT WINAPI
6380 DispCallFunc(
6381 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6382 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6384 #ifdef __i386__
6385 int argspos, stack_offset;
6386 void *func;
6387 UINT i;
6388 DWORD *args;
6390 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6391 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6392 pvargResult, V_VT(pvargResult));
6394 if (cc != CC_STDCALL && cc != CC_CDECL)
6396 FIXME("unsupported calling convention %d\n",cc);
6397 return E_INVALIDARG;
6400 /* maximum size for an argument is sizeof(VARIANT) */
6401 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6403 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6404 argspos = 1;
6405 if (pvInstance)
6407 const FARPROC *vtable = *(FARPROC **)pvInstance;
6408 func = vtable[oVft/sizeof(void *)];
6409 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6411 else func = (void *)oVft;
6413 for (i = 0; i < cActuals; i++)
6415 VARIANT *arg = prgpvarg[i];
6417 switch (prgvt[i])
6419 case VT_EMPTY:
6420 break;
6421 case VT_I8:
6422 case VT_UI8:
6423 case VT_R8:
6424 case VT_DATE:
6425 case VT_CY:
6426 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6427 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6428 break;
6429 case VT_DECIMAL:
6430 case VT_VARIANT:
6431 memcpy( &args[argspos], arg, sizeof(*arg) );
6432 argspos += sizeof(*arg) / sizeof(DWORD);
6433 break;
6434 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6435 args[argspos++] = V_BOOL(arg);
6436 break;
6437 default:
6438 args[argspos++] = V_UI4(arg);
6439 break;
6441 TRACE("arg %u: type %d\n",i,prgvt[i]);
6442 dump_Variant(arg);
6445 switch (vtReturn)
6447 case VT_EMPTY:
6448 call_method( func, argspos - 1, args + 1, &stack_offset );
6449 break;
6450 case VT_R4:
6451 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6452 break;
6453 case VT_R8:
6454 case VT_DATE:
6455 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6456 break;
6457 case VT_DECIMAL:
6458 case VT_VARIANT:
6459 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6460 call_method( func, argspos, args, &stack_offset );
6461 break;
6462 case VT_I8:
6463 case VT_UI8:
6464 case VT_CY:
6465 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6466 break;
6467 case VT_HRESULT:
6468 WARN("invalid return type %u\n", vtReturn);
6469 heap_free( args );
6470 return E_INVALIDARG;
6471 default:
6472 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6473 break;
6475 heap_free( args );
6476 if (stack_offset && cc == CC_STDCALL)
6478 WARN( "stack pointer off by %d\n", stack_offset );
6479 return DISP_E_BADCALLEE;
6481 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6482 TRACE("retval: "); dump_Variant(pvargResult);
6483 return S_OK;
6485 #elif defined(__x86_64__)
6486 int argspos;
6487 UINT i;
6488 DWORD_PTR *args;
6489 void *func;
6491 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6492 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6493 pvargResult, V_VT(pvargResult));
6495 if (cc != CC_STDCALL && cc != CC_CDECL)
6497 FIXME("unsupported calling convention %d\n",cc);
6498 return E_INVALIDARG;
6501 /* maximum size for an argument is sizeof(DWORD_PTR) */
6502 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6504 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6505 argspos = 1;
6506 if (pvInstance)
6508 const FARPROC *vtable = *(FARPROC **)pvInstance;
6509 func = vtable[oVft/sizeof(void *)];
6510 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6512 else func = (void *)oVft;
6514 for (i = 0; i < cActuals; i++)
6516 VARIANT *arg = prgpvarg[i];
6518 switch (prgvt[i])
6520 case VT_DECIMAL:
6521 case VT_VARIANT:
6522 args[argspos++] = (ULONG_PTR)arg;
6523 break;
6524 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6525 args[argspos++] = V_BOOL(arg);
6526 break;
6527 default:
6528 args[argspos++] = V_UI8(arg);
6529 break;
6531 TRACE("arg %u: type %d\n",i,prgvt[i]);
6532 dump_Variant(arg);
6535 switch (vtReturn)
6537 case VT_R4:
6538 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6539 break;
6540 case VT_R8:
6541 case VT_DATE:
6542 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6543 break;
6544 case VT_DECIMAL:
6545 case VT_VARIANT:
6546 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6547 call_method( func, argspos, args );
6548 break;
6549 case VT_HRESULT:
6550 WARN("invalid return type %u\n", vtReturn);
6551 heap_free( args );
6552 return E_INVALIDARG;
6553 default:
6554 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6555 break;
6557 heap_free( args );
6558 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6559 TRACE("retval: "); dump_Variant(pvargResult);
6560 return S_OK;
6562 #else
6563 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6564 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6565 return E_NOTIMPL;
6566 #endif
6569 static inline BOOL func_restricted( const FUNCDESC *desc )
6571 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6574 #define INVBUF_ELEMENT_SIZE \
6575 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6576 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6577 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6578 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6579 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6580 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6581 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6582 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6584 static HRESULT WINAPI ITypeInfo_fnInvoke(
6585 ITypeInfo2 *iface,
6586 VOID *pIUnk,
6587 MEMBERID memid,
6588 UINT16 wFlags,
6589 DISPPARAMS *pDispParams,
6590 VARIANT *pVarResult,
6591 EXCEPINFO *pExcepInfo,
6592 UINT *pArgErr)
6594 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6595 int i;
6596 unsigned int var_index;
6597 TYPEKIND type_kind;
6598 HRESULT hres;
6599 const TLBFuncDesc *pFuncInfo;
6600 UINT fdc;
6602 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6603 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6606 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6607 return DISP_E_MEMBERNOTFOUND;
6609 if (!pDispParams)
6611 ERR("NULL pDispParams not allowed\n");
6612 return E_INVALIDARG;
6615 dump_DispParms(pDispParams);
6617 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6619 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6620 pDispParams->cNamedArgs, pDispParams->cArgs);
6621 return E_INVALIDARG;
6624 /* we do this instead of using GetFuncDesc since it will return a fake
6625 * FUNCDESC for dispinterfaces and we want the real function description */
6626 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
6627 pFuncInfo = &This->funcdescs[fdc];
6628 if ((memid == pFuncInfo->funcdesc.memid) &&
6629 (wFlags & pFuncInfo->funcdesc.invkind) &&
6630 !func_restricted( &pFuncInfo->funcdesc ))
6631 break;
6634 if (fdc < This->TypeAttr.cFuncs) {
6635 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6637 if (TRACE_ON(ole))
6639 TRACE("invoking:\n");
6640 dump_TLBFuncDescOne(pFuncInfo);
6643 switch (func_desc->funckind) {
6644 case FUNC_PUREVIRTUAL:
6645 case FUNC_VIRTUAL: {
6646 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6647 VARIANT varresult;
6648 VARIANT retval; /* pointer for storing byref retvals in */
6649 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6650 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6651 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6652 UINT cNamedArgs = pDispParams->cNamedArgs;
6653 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6654 UINT vargs_converted=0;
6656 hres = S_OK;
6658 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6660 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6662 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6663 hres = DISP_E_PARAMNOTFOUND;
6664 goto func_fail;
6668 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6670 ERR("functions with the vararg attribute do not support named arguments\n");
6671 hres = DISP_E_NONAMEDARGS;
6672 goto func_fail;
6675 for (i = 0; i < func_desc->cParams; i++)
6677 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6678 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6679 if (FAILED(hres))
6680 goto func_fail;
6683 TRACE("changing args\n");
6684 for (i = 0; i < func_desc->cParams; i++)
6686 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6687 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6688 VARIANTARG *src_arg;
6690 if (wParamFlags & PARAMFLAG_FLCID)
6692 VARIANTARG *arg;
6693 arg = prgpvarg[i] = &rgvarg[i];
6694 V_VT(arg) = VT_I4;
6695 V_I4(arg) = This->pTypeLib->lcid;
6696 continue;
6699 src_arg = NULL;
6701 if (cNamedArgs)
6703 USHORT j;
6704 for (j = 0; j < cNamedArgs; j++)
6705 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6707 src_arg = &pDispParams->rgvarg[j];
6708 break;
6712 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6714 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6715 vargs_converted++;
6718 if (wParamFlags & PARAMFLAG_FRETVAL)
6720 /* under most conditions the caller is not allowed to
6721 * pass in a dispparam arg in the index of what would be
6722 * the retval parameter. however, there is an exception
6723 * where the extra parameter is used in an extra
6724 * IDispatch::Invoke below */
6725 if ((i < pDispParams->cArgs) &&
6726 ((func_desc->cParams != 1) || !pVarResult ||
6727 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6729 hres = DISP_E_BADPARAMCOUNT;
6730 break;
6733 /* note: this check is placed so that if the caller passes
6734 * in a VARIANTARG for the retval we just ignore it, like
6735 * native does */
6736 if (i == func_desc->cParams - 1)
6738 VARIANTARG *arg;
6739 arg = prgpvarg[i] = &rgvarg[i];
6740 memset(arg, 0, sizeof(*arg));
6741 V_VT(arg) = rgvt[i];
6742 memset(&retval, 0, sizeof(retval));
6743 V_BYREF(arg) = &retval;
6745 else
6747 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6748 hres = E_UNEXPECTED;
6749 break;
6752 else if (src_arg)
6754 dump_Variant(src_arg);
6756 if(rgvt[i]!=V_VT(src_arg))
6758 if (rgvt[i] == VT_VARIANT)
6759 hres = VariantCopy(&rgvarg[i], src_arg);
6760 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6762 if (rgvt[i] == V_VT(src_arg))
6763 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6764 else
6766 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6767 if (wParamFlags & PARAMFLAG_FIN)
6768 hres = VariantCopy(&missing_arg[i], src_arg);
6769 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6771 V_VT(&rgvarg[i]) = rgvt[i];
6773 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6775 SAFEARRAY *a;
6776 SAFEARRAYBOUND bound;
6777 VARIANT *v;
6778 LONG j;
6779 bound.lLbound = 0;
6780 bound.cElements = pDispParams->cArgs-i;
6781 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6783 ERR("SafeArrayCreate failed\n");
6784 break;
6786 hres = SafeArrayAccessData(a, (LPVOID)&v);
6787 if (hres != S_OK)
6789 ERR("SafeArrayAccessData failed with %x\n", hres);
6790 SafeArrayDestroy(a);
6791 break;
6793 for (j = 0; j < bound.cElements; j++)
6794 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6795 hres = SafeArrayUnaccessData(a);
6796 if (hres != S_OK)
6798 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6799 SafeArrayDestroy(a);
6800 break;
6802 V_ARRAY(&rgvarg[i]) = a;
6803 V_VT(&rgvarg[i]) = rgvt[i];
6805 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6807 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6808 if (wParamFlags & PARAMFLAG_FIN)
6809 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6810 else
6811 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6812 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6813 V_VT(&rgvarg[i]) = rgvt[i];
6815 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6817 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6818 V_VT(&rgvarg[i]) = rgvt[i];
6820 else
6822 /* FIXME: this doesn't work for VT_BYREF arguments if
6823 * they are not the same type as in the paramdesc */
6824 V_VT(&rgvarg[i]) = V_VT(src_arg);
6825 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6826 V_VT(&rgvarg[i]) = rgvt[i];
6829 if (FAILED(hres))
6831 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6832 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6833 debugstr_VT(src_arg), debugstr_VF(src_arg));
6834 break;
6836 prgpvarg[i] = &rgvarg[i];
6838 else
6840 prgpvarg[i] = src_arg;
6843 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6844 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6845 && V_UNKNOWN(prgpvarg[i])) {
6846 IUnknown *userdefined_iface;
6847 GUID guid;
6849 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6850 if(FAILED(hres))
6851 break;
6853 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6854 if(FAILED(hres)) {
6855 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6856 break;
6859 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6860 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6863 else if (wParamFlags & PARAMFLAG_FOPT)
6865 VARIANTARG *arg;
6866 arg = prgpvarg[i] = &rgvarg[i];
6867 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6869 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6870 if (FAILED(hres))
6871 break;
6873 else
6875 VARIANTARG *missing_arg;
6876 /* if the function wants a pointer to a variant then
6877 * set that up, otherwise just pass the VT_ERROR in
6878 * the argument by value */
6879 if (rgvt[i] & VT_BYREF)
6881 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6882 V_VT(arg) = VT_VARIANT | VT_BYREF;
6883 V_VARIANTREF(arg) = missing_arg;
6885 else
6886 missing_arg = arg;
6887 V_VT(missing_arg) = VT_ERROR;
6888 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6891 else
6893 hres = DISP_E_BADPARAMCOUNT;
6894 break;
6897 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6899 /* VT_VOID is a special case for return types, so it is not
6900 * handled in the general function */
6901 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6902 V_VT(&varresult) = VT_EMPTY;
6903 else
6905 V_VT(&varresult) = 0;
6906 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6907 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6910 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
6911 V_VT(&varresult), func_desc->cParams, rgvt,
6912 prgpvarg, &varresult);
6914 vargs_converted = 0;
6916 for (i = 0; i < func_desc->cParams; i++)
6918 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6919 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6921 if (wParamFlags & PARAMFLAG_FLCID)
6922 continue;
6923 else if (wParamFlags & PARAMFLAG_FRETVAL)
6925 if (TRACE_ON(ole))
6927 TRACE("[retval] value: ");
6928 dump_Variant(prgpvarg[i]);
6931 if (pVarResult)
6933 VariantInit(pVarResult);
6934 /* deref return value */
6935 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6938 VARIANT_ClearInd(prgpvarg[i]);
6940 else if (vargs_converted < pDispParams->cArgs)
6942 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6943 if (wParamFlags & PARAMFLAG_FOUT)
6945 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6947 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6949 if (FAILED(hres))
6951 ERR("failed to convert param %d to vt %d\n", i,
6952 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6953 break;
6957 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6958 func_desc->cParamsOpt < 0 &&
6959 i == func_desc->cParams-1)
6961 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6962 LONG j, ubound;
6963 VARIANT *v;
6964 hres = SafeArrayGetUBound(a, 1, &ubound);
6965 if (hres != S_OK)
6967 ERR("SafeArrayGetUBound failed with %x\n", hres);
6968 break;
6970 hres = SafeArrayAccessData(a, (LPVOID)&v);
6971 if (hres != S_OK)
6973 ERR("SafeArrayAccessData failed with %x\n", hres);
6974 break;
6976 for (j = 0; j <= ubound; j++)
6977 VariantClear(&v[j]);
6978 hres = SafeArrayUnaccessData(a);
6979 if (hres != S_OK)
6981 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6982 break;
6985 VariantClear(&rgvarg[i]);
6986 vargs_converted++;
6988 else if (wParamFlags & PARAMFLAG_FOPT)
6990 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6991 VariantClear(&rgvarg[i]);
6994 VariantClear(&missing_arg[i]);
6997 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6999 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7000 hres = DISP_E_EXCEPTION;
7001 if (pExcepInfo)
7003 IErrorInfo *pErrorInfo;
7004 pExcepInfo->scode = V_ERROR(&varresult);
7005 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7007 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7008 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7009 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7010 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7012 IErrorInfo_Release(pErrorInfo);
7016 if (V_VT(&varresult) != VT_ERROR)
7018 TRACE("varresult value: ");
7019 dump_Variant(&varresult);
7021 if (pVarResult)
7023 VariantClear(pVarResult);
7024 *pVarResult = varresult;
7026 else
7027 VariantClear(&varresult);
7030 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7031 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7032 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7033 (pDispParams->cArgs != 0))
7035 if (V_VT(pVarResult) == VT_DISPATCH)
7037 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7038 /* Note: not VariantClear; we still need the dispatch
7039 * pointer to be valid */
7040 VariantInit(pVarResult);
7041 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7042 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7043 pDispParams, pVarResult, pExcepInfo, pArgErr);
7044 IDispatch_Release(pDispatch);
7046 else
7048 VariantClear(pVarResult);
7049 hres = DISP_E_NOTACOLLECTION;
7053 func_fail:
7054 heap_free(buffer);
7055 break;
7057 case FUNC_DISPATCH: {
7058 IDispatch *disp;
7060 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7061 if (SUCCEEDED(hres)) {
7062 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7063 hres = IDispatch_Invoke(
7064 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7065 pVarResult,pExcepInfo,pArgErr
7067 if (FAILED(hres))
7068 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7069 IDispatch_Release(disp);
7070 } else
7071 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7072 break;
7074 default:
7075 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7076 hres = E_FAIL;
7077 break;
7080 TRACE("-- 0x%08x\n", hres);
7081 return hres;
7083 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7084 VARDESC *var_desc;
7086 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7087 if(FAILED(hres)) return hres;
7089 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7090 dump_VARDESC(var_desc);
7091 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7092 return E_NOTIMPL;
7095 /* not found, look for it in inherited interfaces */
7096 ITypeInfo2_GetTypeKind(iface, &type_kind);
7097 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7098 if(This->impltypes) {
7099 /* recursive search */
7100 ITypeInfo *pTInfo;
7101 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7102 if(SUCCEEDED(hres)){
7103 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7104 ITypeInfo_Release(pTInfo);
7105 return hres;
7107 WARN("Could not search inherited interface!\n");
7110 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7111 return DISP_E_MEMBERNOTFOUND;
7114 /* ITypeInfo::GetDocumentation
7116 * Retrieves the documentation string, the complete Help file name and path,
7117 * and the context ID for the Help topic for a specified type description.
7119 * (Can be tested by the Visual Basic Editor in Word for instance.)
7121 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7122 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7123 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7125 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7126 const TLBFuncDesc *pFDesc;
7127 const TLBVarDesc *pVDesc;
7128 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7129 " HelpContext(%p) HelpFile(%p)\n",
7130 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7131 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7132 if(pBstrName)
7133 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7134 if(pBstrDocString)
7135 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7136 if(pdwHelpContext)
7137 *pdwHelpContext=This->dwHelpContext;
7138 if(pBstrHelpFile)
7139 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7140 return S_OK;
7141 }else {/* for a member */
7142 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7143 if(pFDesc){
7144 if(pBstrName)
7145 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7146 if(pBstrDocString)
7147 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7148 if(pdwHelpContext)
7149 *pdwHelpContext=pFDesc->helpcontext;
7150 if(pBstrHelpFile)
7151 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7152 return S_OK;
7154 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7155 if(pVDesc){
7156 if(pBstrName)
7157 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7158 if(pBstrDocString)
7159 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7160 if(pdwHelpContext)
7161 *pdwHelpContext=pVDesc->HelpContext;
7162 if(pBstrHelpFile)
7163 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7164 return S_OK;
7168 if(This->impltypes &&
7169 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
7170 /* recursive search */
7171 ITypeInfo *pTInfo;
7172 HRESULT result;
7173 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7174 if(SUCCEEDED(result)) {
7175 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7176 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7177 ITypeInfo_Release(pTInfo);
7178 return result;
7180 WARN("Could not search inherited interface!\n");
7183 WARN("member %d not found\n", memid);
7184 return TYPE_E_ELEMENTNOTFOUND;
7187 /* ITypeInfo::GetDllEntry
7189 * Retrieves a description or specification of an entry point for a function
7190 * in a DLL.
7192 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7193 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7194 WORD *pwOrdinal)
7196 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7197 const TLBFuncDesc *pFDesc;
7199 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7201 if (pBstrDllName) *pBstrDllName = NULL;
7202 if (pBstrName) *pBstrName = NULL;
7203 if (pwOrdinal) *pwOrdinal = 0;
7205 if (This->TypeAttr.typekind != TKIND_MODULE)
7206 return TYPE_E_BADMODULEKIND;
7208 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7209 if(pFDesc){
7210 dump_TypeInfo(This);
7211 if (TRACE_ON(ole))
7212 dump_TLBFuncDescOne(pFDesc);
7214 if (pBstrDllName)
7215 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7217 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7218 if (pBstrName)
7219 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7220 if (pwOrdinal)
7221 *pwOrdinal = -1;
7222 return S_OK;
7224 if (pBstrName)
7225 *pBstrName = NULL;
7226 if (pwOrdinal)
7227 *pwOrdinal = LOWORD(pFDesc->Entry);
7228 return S_OK;
7230 return TYPE_E_ELEMENTNOTFOUND;
7233 /* internal function to make the inherited interfaces' methods appear
7234 * part of the interface */
7235 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7236 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7238 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7239 HRESULT hr;
7241 TRACE("%p, 0x%x\n", iface, *hRefType);
7243 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7245 ITypeInfo *pSubTypeInfo;
7247 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7248 if (FAILED(hr))
7249 return hr;
7251 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7252 hRefType, ppTInfo);
7253 ITypeInfo_Release(pSubTypeInfo);
7254 if (SUCCEEDED(hr))
7255 return hr;
7257 *hRefType -= DISPATCH_HREF_OFFSET;
7259 if (!(*hRefType & DISPATCH_HREF_MASK))
7260 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7261 else
7262 return E_FAIL;
7265 /* ITypeInfo::GetRefTypeInfo
7267 * If a type description references other type descriptions, it retrieves
7268 * the referenced type descriptions.
7270 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7271 ITypeInfo2 *iface,
7272 HREFTYPE hRefType,
7273 ITypeInfo **ppTInfo)
7275 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7276 HRESULT result = E_FAIL;
7278 if(!ppTInfo)
7279 return E_INVALIDARG;
7281 if ((INT)hRefType < 0) {
7282 ITypeInfoImpl *pTypeInfoImpl;
7284 if (!(This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL) ||
7285 !(This->TypeAttr.typekind == TKIND_INTERFACE ||
7286 This->TypeAttr.typekind == TKIND_DISPATCH))
7287 return TYPE_E_ELEMENTNOTFOUND;
7289 /* when we meet a DUAL typeinfo, we must create the alternate
7290 * version of it.
7292 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7294 *pTypeInfoImpl = *This;
7295 pTypeInfoImpl->ref = 0;
7297 if (This->TypeAttr.typekind == TKIND_INTERFACE)
7298 pTypeInfoImpl->TypeAttr.typekind = TKIND_DISPATCH;
7299 else
7300 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
7302 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7303 /* the AddRef implicitly adds a reference to the parent typelib, which
7304 * stops the copied data from being destroyed until the new typeinfo's
7305 * refcount goes to zero, but we need to signal to the new instance to
7306 * not free its data structures when it is destroyed */
7307 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7309 ITypeInfo_AddRef(*ppTInfo);
7311 result = S_OK;
7312 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7313 (This->TypeAttr.typekind == TKIND_DISPATCH))
7315 HREFTYPE href_dispatch = hRefType;
7316 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7317 } else {
7318 TLBRefType *ref_type;
7319 ITypeLib *pTLib = NULL;
7320 UINT i;
7322 if(!(hRefType & 0x1)){
7323 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7325 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7327 result = S_OK;
7328 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7329 ITypeInfo_AddRef(*ppTInfo);
7330 goto end;
7333 result = TYPE_E_ELEMENTNOTFOUND;
7334 goto end;
7337 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7339 if(ref_type->reference == (hRefType & (~0x3)))
7340 break;
7342 if(&ref_type->entry == &This->pTypeLib->ref_list)
7344 FIXME("Can't find pRefType for ref %x\n", hRefType);
7345 goto end;
7348 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7349 UINT Index;
7350 TRACE("internal reference\n");
7351 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7352 } else {
7353 if(ref_type->pImpTLInfo->pImpTypeLib) {
7354 TRACE("typeinfo in imported typelib that is already loaded\n");
7355 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7356 ITypeLib_AddRef(pTLib);
7357 result = S_OK;
7358 } else {
7359 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7360 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
7361 ref_type->pImpTLInfo->wVersionMajor,
7362 ref_type->pImpTLInfo->wVersionMinor,
7363 ref_type->pImpTLInfo->lcid,
7364 &pTLib);
7366 if(FAILED(result)) {
7367 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
7368 result=LoadTypeLib(libnam, &pTLib);
7369 SysFreeString(libnam);
7371 if(SUCCEEDED(result)) {
7372 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7373 ITypeLib_AddRef(pTLib);
7377 if(SUCCEEDED(result)) {
7378 if(ref_type->index == TLB_REF_USE_GUID)
7379 result = ITypeLib_GetTypeInfoOfGuid(pTLib, &ref_type->guid, ppTInfo);
7380 else
7381 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7383 if (pTLib != NULL)
7384 ITypeLib_Release(pTLib);
7387 end:
7388 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7389 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7390 return result;
7393 /* ITypeInfo::AddressOfMember
7395 * Retrieves the addresses of static functions or variables, such as those
7396 * defined in a DLL.
7398 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7399 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7401 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7402 HRESULT hr;
7403 BSTR dll, entry;
7404 WORD ordinal;
7405 HMODULE module;
7407 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7409 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7410 if (FAILED(hr))
7411 return hr;
7413 module = LoadLibraryW(dll);
7414 if (!module)
7416 ERR("couldn't load %s\n", debugstr_w(dll));
7417 SysFreeString(dll);
7418 SysFreeString(entry);
7419 return STG_E_FILENOTFOUND;
7421 /* FIXME: store library somewhere where we can free it */
7423 if (entry)
7425 LPSTR entryA;
7426 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7427 entryA = heap_alloc(len);
7428 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7430 *ppv = GetProcAddress(module, entryA);
7431 if (!*ppv)
7432 ERR("function not found %s\n", debugstr_a(entryA));
7434 heap_free(entryA);
7436 else
7438 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7439 if (!*ppv)
7440 ERR("function not found %d\n", ordinal);
7443 SysFreeString(dll);
7444 SysFreeString(entry);
7446 if (!*ppv)
7447 return TYPE_E_DLLFUNCTIONNOTFOUND;
7449 return S_OK;
7452 /* ITypeInfo::CreateInstance
7454 * Creates a new instance of a type that describes a component object class
7455 * (coclass).
7457 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7458 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7460 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7461 HRESULT hr;
7462 TYPEATTR *pTA;
7464 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7466 *ppvObj = NULL;
7468 if(pOuterUnk)
7470 WARN("Not able to aggregate\n");
7471 return CLASS_E_NOAGGREGATION;
7474 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7475 if(FAILED(hr)) return hr;
7477 if(pTA->typekind != TKIND_COCLASS)
7479 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7480 hr = E_INVALIDARG;
7481 goto end;
7484 hr = S_FALSE;
7485 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7487 IUnknown *pUnk;
7488 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7489 TRACE("GetActiveObject rets %08x\n", hr);
7490 if(hr == S_OK)
7492 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7493 IUnknown_Release(pUnk);
7497 if(hr != S_OK)
7498 hr = CoCreateInstance(&pTA->guid, NULL,
7499 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7500 riid, ppvObj);
7502 end:
7503 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7504 return hr;
7507 /* ITypeInfo::GetMops
7509 * Retrieves marshalling information.
7511 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7512 BSTR *pBstrMops)
7514 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7515 FIXME("(%p %d) stub!\n", This, memid);
7516 *pBstrMops = NULL;
7517 return S_OK;
7520 /* ITypeInfo::GetContainingTypeLib
7522 * Retrieves the containing type library and the index of the type description
7523 * within that type library.
7525 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7526 ITypeLib * *ppTLib, UINT *pIndex)
7528 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7530 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7531 if (pIndex) {
7532 *pIndex=This->index;
7533 TRACE("returning pIndex=%d\n", *pIndex);
7536 if (ppTLib) {
7537 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7538 ITypeLib_AddRef(*ppTLib);
7539 TRACE("returning ppTLib=%p\n", *ppTLib);
7542 return S_OK;
7545 /* ITypeInfo::ReleaseTypeAttr
7547 * Releases a TYPEATTR previously returned by GetTypeAttr.
7550 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7551 TYPEATTR* pTypeAttr)
7553 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7554 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7555 heap_free(pTypeAttr);
7558 /* ITypeInfo::ReleaseFuncDesc
7560 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7562 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7563 ITypeInfo2 *iface,
7564 FUNCDESC *pFuncDesc)
7566 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7567 SHORT i;
7569 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7571 for (i = 0; i < pFuncDesc->cParams; i++)
7572 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7573 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7575 SysFreeString((BSTR)pFuncDesc);
7578 /* ITypeInfo::ReleaseVarDesc
7580 * Releases a VARDESC previously returned by GetVarDesc.
7582 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7583 VARDESC *pVarDesc)
7585 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7586 TRACE("(%p)->(%p)\n", This, pVarDesc);
7588 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7589 if (pVarDesc->varkind == VAR_CONST)
7590 VariantClear(pVarDesc->u.lpvarValue);
7591 SysFreeString((BSTR)pVarDesc);
7594 /* ITypeInfo2::GetTypeKind
7596 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7599 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7600 TYPEKIND *pTypeKind)
7602 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7603 *pTypeKind=This->TypeAttr.typekind;
7604 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7605 return S_OK;
7608 /* ITypeInfo2::GetTypeFlags
7610 * Returns the type flags without any allocations. This returns a DWORD type
7611 * flag, which expands the type flags without growing the TYPEATTR (type
7612 * attribute).
7615 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7617 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7618 *pTypeFlags=This->TypeAttr.wTypeFlags;
7619 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7620 return S_OK;
7623 /* ITypeInfo2::GetFuncIndexOfMemId
7624 * Binds to a specific member based on a known DISPID, where the member name
7625 * is not known (for example, when binding to a default member).
7628 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7629 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7631 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7632 UINT fdc;
7633 HRESULT result;
7635 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7636 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7637 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7638 break;
7640 if(fdc < This->TypeAttr.cFuncs) {
7641 *pFuncIndex = fdc;
7642 result = S_OK;
7643 } else
7644 result = TYPE_E_ELEMENTNOTFOUND;
7646 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7647 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7648 return result;
7651 /* TypeInfo2::GetVarIndexOfMemId
7653 * Binds to a specific member based on a known DISPID, where the member name
7654 * is not known (for example, when binding to a default member).
7657 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7658 MEMBERID memid, UINT *pVarIndex)
7660 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7661 TLBVarDesc *pVarInfo;
7663 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7665 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7666 if(!pVarInfo)
7667 return TYPE_E_ELEMENTNOTFOUND;
7669 *pVarIndex = (pVarInfo - This->vardescs);
7671 return S_OK;
7674 /* ITypeInfo2::GetCustData
7676 * Gets the custom data
7678 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7679 ITypeInfo2 * iface,
7680 REFGUID guid,
7681 VARIANT *pVarVal)
7683 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7684 TLBCustData *pCData;
7686 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7688 if(!guid || !pVarVal)
7689 return E_INVALIDARG;
7691 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7693 VariantInit( pVarVal);
7694 if (pCData)
7695 VariantCopy( pVarVal, &pCData->data);
7696 else
7697 VariantClear( pVarVal );
7698 return S_OK;
7701 /* ITypeInfo2::GetFuncCustData
7703 * Gets the custom data
7705 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7706 ITypeInfo2 * iface,
7707 UINT index,
7708 REFGUID guid,
7709 VARIANT *pVarVal)
7711 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7712 TLBCustData *pCData;
7713 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7715 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7717 if(index >= This->TypeAttr.cFuncs)
7718 return TYPE_E_ELEMENTNOTFOUND;
7720 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7721 if(!pCData)
7722 return TYPE_E_ELEMENTNOTFOUND;
7724 VariantInit(pVarVal);
7725 VariantCopy(pVarVal, &pCData->data);
7727 return S_OK;
7730 /* ITypeInfo2::GetParamCustData
7732 * Gets the custom data
7734 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7735 ITypeInfo2 * iface,
7736 UINT indexFunc,
7737 UINT indexParam,
7738 REFGUID guid,
7739 VARIANT *pVarVal)
7741 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7742 TLBCustData *pCData;
7743 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7745 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7746 debugstr_guid(guid), pVarVal);
7748 if(indexFunc >= This->TypeAttr.cFuncs)
7749 return TYPE_E_ELEMENTNOTFOUND;
7751 if(indexParam >= pFDesc->funcdesc.cParams)
7752 return TYPE_E_ELEMENTNOTFOUND;
7754 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7755 if(!pCData)
7756 return TYPE_E_ELEMENTNOTFOUND;
7758 VariantInit(pVarVal);
7759 VariantCopy(pVarVal, &pCData->data);
7761 return S_OK;
7764 /* ITypeInfo2::GetVarCustData
7766 * Gets the custom data
7768 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7769 ITypeInfo2 * iface,
7770 UINT index,
7771 REFGUID guid,
7772 VARIANT *pVarVal)
7774 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7775 TLBCustData *pCData;
7776 TLBVarDesc *pVDesc = &This->vardescs[index];
7778 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7780 if(index >= This->TypeAttr.cVars)
7781 return TYPE_E_ELEMENTNOTFOUND;
7783 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7784 if(!pCData)
7785 return TYPE_E_ELEMENTNOTFOUND;
7787 VariantInit(pVarVal);
7788 VariantCopy(pVarVal, &pCData->data);
7790 return S_OK;
7793 /* ITypeInfo2::GetImplCustData
7795 * Gets the custom data
7797 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7798 ITypeInfo2 * iface,
7799 UINT index,
7800 REFGUID guid,
7801 VARIANT *pVarVal)
7803 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7804 TLBCustData *pCData;
7805 TLBImplType *pRDesc = &This->impltypes[index];
7807 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7809 if(index >= This->TypeAttr.cImplTypes)
7810 return TYPE_E_ELEMENTNOTFOUND;
7812 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7813 if(!pCData)
7814 return TYPE_E_ELEMENTNOTFOUND;
7816 VariantInit(pVarVal);
7817 VariantCopy(pVarVal, &pCData->data);
7819 return S_OK;
7822 /* ITypeInfo2::GetDocumentation2
7824 * Retrieves the documentation string, the complete Help file name and path,
7825 * the localization context to use, and the context ID for the library Help
7826 * topic in the Help file.
7829 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7830 ITypeInfo2 * iface,
7831 MEMBERID memid,
7832 LCID lcid,
7833 BSTR *pbstrHelpString,
7834 DWORD *pdwHelpStringContext,
7835 BSTR *pbstrHelpStringDll)
7837 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7838 const TLBFuncDesc *pFDesc;
7839 const TLBVarDesc *pVDesc;
7840 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7841 "HelpStringContext(%p) HelpStringDll(%p)\n",
7842 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7843 pbstrHelpStringDll );
7844 /* the help string should be obtained from the helpstringdll,
7845 * using the _DLLGetDocumentation function, based on the supplied
7846 * lcid. Nice to do sometime...
7848 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7849 if(pbstrHelpString)
7850 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
7851 if(pdwHelpStringContext)
7852 *pdwHelpStringContext=This->dwHelpStringContext;
7853 if(pbstrHelpStringDll)
7854 *pbstrHelpStringDll=
7855 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7856 return S_OK;
7857 }else {/* for a member */
7858 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7859 if(pFDesc){
7860 if(pbstrHelpString)
7861 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7862 if(pdwHelpStringContext)
7863 *pdwHelpStringContext=pFDesc->HelpStringContext;
7864 if(pbstrHelpStringDll)
7865 *pbstrHelpStringDll=
7866 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7867 return S_OK;
7869 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7870 if(pVDesc){
7871 if(pbstrHelpString)
7872 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7873 if(pdwHelpStringContext)
7874 *pdwHelpStringContext=pVDesc->HelpStringContext;
7875 if(pbstrHelpStringDll)
7876 *pbstrHelpStringDll=
7877 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7878 return S_OK;
7881 return TYPE_E_ELEMENTNOTFOUND;
7884 /* ITypeInfo2::GetAllCustData
7886 * Gets all custom data items for the Type info.
7889 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7890 ITypeInfo2 * iface,
7891 CUSTDATA *pCustData)
7893 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7895 TRACE("%p %p\n", This, pCustData);
7897 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
7900 /* ITypeInfo2::GetAllFuncCustData
7902 * Gets all custom data items for the specified Function
7905 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7906 ITypeInfo2 * iface,
7907 UINT index,
7908 CUSTDATA *pCustData)
7910 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7911 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7913 TRACE("%p %u %p\n", This, index, pCustData);
7915 if(index >= This->TypeAttr.cFuncs)
7916 return TYPE_E_ELEMENTNOTFOUND;
7918 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
7921 /* ITypeInfo2::GetAllParamCustData
7923 * Gets all custom data items for the Functions
7926 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7927 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7929 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7930 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7932 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
7934 if(indexFunc >= This->TypeAttr.cFuncs)
7935 return TYPE_E_ELEMENTNOTFOUND;
7937 if(indexParam >= pFDesc->funcdesc.cParams)
7938 return TYPE_E_ELEMENTNOTFOUND;
7940 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
7943 /* ITypeInfo2::GetAllVarCustData
7945 * Gets all custom data items for the specified Variable
7948 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7949 UINT index, CUSTDATA *pCustData)
7951 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7952 TLBVarDesc * pVDesc = &This->vardescs[index];
7954 TRACE("%p %u %p\n", This, index, pCustData);
7956 if(index >= This->TypeAttr.cVars)
7957 return TYPE_E_ELEMENTNOTFOUND;
7959 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
7962 /* ITypeInfo2::GetAllImplCustData
7964 * Gets all custom data items for the specified implementation type
7967 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7968 ITypeInfo2 * iface,
7969 UINT index,
7970 CUSTDATA *pCustData)
7972 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7973 TLBImplType *pRDesc = &This->impltypes[index];
7975 TRACE("%p %u %p\n", This, index, pCustData);
7977 if(index >= This->TypeAttr.cImplTypes)
7978 return TYPE_E_ELEMENTNOTFOUND;
7980 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
7983 static const ITypeInfo2Vtbl tinfvt =
7986 ITypeInfo_fnQueryInterface,
7987 ITypeInfo_fnAddRef,
7988 ITypeInfo_fnRelease,
7990 ITypeInfo_fnGetTypeAttr,
7991 ITypeInfo_fnGetTypeComp,
7992 ITypeInfo_fnGetFuncDesc,
7993 ITypeInfo_fnGetVarDesc,
7994 ITypeInfo_fnGetNames,
7995 ITypeInfo_fnGetRefTypeOfImplType,
7996 ITypeInfo_fnGetImplTypeFlags,
7997 ITypeInfo_fnGetIDsOfNames,
7998 ITypeInfo_fnInvoke,
7999 ITypeInfo_fnGetDocumentation,
8000 ITypeInfo_fnGetDllEntry,
8001 ITypeInfo_fnGetRefTypeInfo,
8002 ITypeInfo_fnAddressOfMember,
8003 ITypeInfo_fnCreateInstance,
8004 ITypeInfo_fnGetMops,
8005 ITypeInfo_fnGetContainingTypeLib,
8006 ITypeInfo_fnReleaseTypeAttr,
8007 ITypeInfo_fnReleaseFuncDesc,
8008 ITypeInfo_fnReleaseVarDesc,
8010 ITypeInfo2_fnGetTypeKind,
8011 ITypeInfo2_fnGetTypeFlags,
8012 ITypeInfo2_fnGetFuncIndexOfMemId,
8013 ITypeInfo2_fnGetVarIndexOfMemId,
8014 ITypeInfo2_fnGetCustData,
8015 ITypeInfo2_fnGetFuncCustData,
8016 ITypeInfo2_fnGetParamCustData,
8017 ITypeInfo2_fnGetVarCustData,
8018 ITypeInfo2_fnGetImplTypeCustData,
8019 ITypeInfo2_fnGetDocumentation2,
8020 ITypeInfo2_fnGetAllCustData,
8021 ITypeInfo2_fnGetAllFuncCustData,
8022 ITypeInfo2_fnGetAllParamCustData,
8023 ITypeInfo2_fnGetAllVarCustData,
8024 ITypeInfo2_fnGetAllImplTypeCustData,
8027 /******************************************************************************
8028 * CreateDispTypeInfo [OLEAUT32.31]
8030 * Build type information for an object so it can be called through an
8031 * IDispatch interface.
8033 * RETURNS
8034 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8035 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8037 * NOTES
8038 * This call allows an objects methods to be accessed through IDispatch, by
8039 * building an ITypeInfo object that IDispatch can use to call through.
8041 HRESULT WINAPI CreateDispTypeInfo(
8042 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8043 LCID lcid, /* [I] Locale Id */
8044 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8046 ITypeInfoImpl *pTIClass, *pTIIface;
8047 ITypeLibImpl *pTypeLibImpl;
8048 unsigned int param, func;
8049 TLBFuncDesc *pFuncDesc;
8050 TLBRefType *ref;
8052 TRACE("\n");
8053 pTypeLibImpl = TypeLibImpl_Constructor();
8054 if (!pTypeLibImpl) return E_FAIL;
8056 pTypeLibImpl->TypeInfoCount = 2;
8057 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8059 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8060 pTIIface->pTypeLib = pTypeLibImpl;
8061 pTIIface->index = 0;
8062 pTIIface->Name = NULL;
8063 pTIIface->dwHelpContext = -1;
8064 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
8065 pTIIface->TypeAttr.lcid = lcid;
8066 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
8067 pTIIface->TypeAttr.wMajorVerNum = 0;
8068 pTIIface->TypeAttr.wMinorVerNum = 0;
8069 pTIIface->TypeAttr.cbAlignment = 2;
8070 pTIIface->TypeAttr.cbSizeInstance = -1;
8071 pTIIface->TypeAttr.cbSizeVft = -1;
8072 pTIIface->TypeAttr.cFuncs = 0;
8073 pTIIface->TypeAttr.cImplTypes = 0;
8074 pTIIface->TypeAttr.cVars = 0;
8075 pTIIface->TypeAttr.wTypeFlags = 0;
8076 pTIIface->hreftype = 0;
8078 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8079 pFuncDesc = pTIIface->funcdescs;
8080 for(func = 0; func < pidata->cMembers; func++) {
8081 METHODDATA *md = pidata->pmethdata + func;
8082 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8083 pFuncDesc->funcdesc.memid = md->dispid;
8084 pFuncDesc->funcdesc.lprgscode = NULL;
8085 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8086 pFuncDesc->funcdesc.invkind = md->wFlags;
8087 pFuncDesc->funcdesc.callconv = md->cc;
8088 pFuncDesc->funcdesc.cParams = md->cArgs;
8089 pFuncDesc->funcdesc.cParamsOpt = 0;
8090 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8091 pFuncDesc->funcdesc.cScodes = 0;
8092 pFuncDesc->funcdesc.wFuncFlags = 0;
8093 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8094 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8095 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8096 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8097 md->cArgs * sizeof(ELEMDESC));
8098 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8099 for(param = 0; param < md->cArgs; param++) {
8100 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8101 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8103 pFuncDesc->helpcontext = 0;
8104 pFuncDesc->HelpStringContext = 0;
8105 pFuncDesc->HelpString = NULL;
8106 pFuncDesc->Entry = NULL;
8107 list_init(&pFuncDesc->custdata_list);
8108 pTIIface->TypeAttr.cFuncs++;
8109 ++pFuncDesc;
8112 dump_TypeInfo(pTIIface);
8114 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8115 pTIClass->pTypeLib = pTypeLibImpl;
8116 pTIClass->index = 1;
8117 pTIClass->Name = NULL;
8118 pTIClass->dwHelpContext = -1;
8119 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
8120 pTIClass->TypeAttr.lcid = lcid;
8121 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
8122 pTIClass->TypeAttr.wMajorVerNum = 0;
8123 pTIClass->TypeAttr.wMinorVerNum = 0;
8124 pTIClass->TypeAttr.cbAlignment = 2;
8125 pTIClass->TypeAttr.cbSizeInstance = -1;
8126 pTIClass->TypeAttr.cbSizeVft = -1;
8127 pTIClass->TypeAttr.cFuncs = 0;
8128 pTIClass->TypeAttr.cImplTypes = 1;
8129 pTIClass->TypeAttr.cVars = 0;
8130 pTIClass->TypeAttr.wTypeFlags = 0;
8131 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8133 pTIClass->impltypes = TLBImplType_Alloc(1);
8135 ref = heap_alloc_zero(sizeof(*ref));
8136 ref->pImpTLInfo = TLB_REF_INTERNAL;
8137 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8139 dump_TypeInfo(pTIClass);
8141 *pptinfo = (ITypeInfo*)pTIClass;
8143 ITypeInfo_AddRef(*pptinfo);
8144 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8146 return S_OK;
8150 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8152 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8154 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
8157 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8159 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8161 return ITypeInfo_AddRef((ITypeInfo *)This);
8164 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8166 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8168 return ITypeInfo_Release((ITypeInfo *)This);
8171 static HRESULT WINAPI ITypeComp_fnBind(
8172 ITypeComp * iface,
8173 OLECHAR * szName,
8174 ULONG lHash,
8175 WORD wFlags,
8176 ITypeInfo ** ppTInfo,
8177 DESCKIND * pDescKind,
8178 BINDPTR * pBindPtr)
8180 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8181 const TLBFuncDesc *pFDesc;
8182 const TLBVarDesc *pVDesc;
8183 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8184 UINT fdc;
8186 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8188 *pDescKind = DESCKIND_NONE;
8189 pBindPtr->lpfuncdesc = NULL;
8190 *ppTInfo = NULL;
8192 for(fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
8193 pFDesc = &This->funcdescs[fdc];
8194 if (!strcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8195 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8196 break;
8197 else
8198 /* name found, but wrong flags */
8199 hr = TYPE_E_TYPEMISMATCH;
8203 if (fdc < This->TypeAttr.cFuncs)
8205 HRESULT hr = TLB_AllocAndInitFuncDesc(
8206 &pFDesc->funcdesc,
8207 &pBindPtr->lpfuncdesc,
8208 This->TypeAttr.typekind == TKIND_DISPATCH);
8209 if (FAILED(hr))
8210 return hr;
8211 *pDescKind = DESCKIND_FUNCDESC;
8212 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8213 ITypeInfo_AddRef(*ppTInfo);
8214 return S_OK;
8215 } else {
8216 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, szName);
8217 if(pVDesc){
8218 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8219 if (FAILED(hr))
8220 return hr;
8221 *pDescKind = DESCKIND_VARDESC;
8222 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8223 ITypeInfo_AddRef(*ppTInfo);
8224 return S_OK;
8227 /* FIXME: search each inherited interface, not just the first */
8228 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8229 /* recursive search */
8230 ITypeInfo *pTInfo;
8231 ITypeComp *pTComp;
8232 HRESULT hr;
8233 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8234 if (SUCCEEDED(hr))
8236 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8237 ITypeInfo_Release(pTInfo);
8239 if (SUCCEEDED(hr))
8241 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8242 ITypeComp_Release(pTComp);
8243 return hr;
8245 WARN("Could not search inherited interface!\n");
8247 if (hr == DISP_E_MEMBERNOTFOUND)
8248 hr = S_OK;
8249 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8250 return hr;
8253 static HRESULT WINAPI ITypeComp_fnBindType(
8254 ITypeComp * iface,
8255 OLECHAR * szName,
8256 ULONG lHash,
8257 ITypeInfo ** ppTInfo,
8258 ITypeComp ** ppTComp)
8260 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8262 /* strange behaviour (does nothing) but like the
8263 * original */
8265 if (!ppTInfo || !ppTComp)
8266 return E_POINTER;
8268 *ppTInfo = NULL;
8269 *ppTComp = NULL;
8271 return S_OK;
8274 static const ITypeCompVtbl tcompvt =
8277 ITypeComp_fnQueryInterface,
8278 ITypeComp_fnAddRef,
8279 ITypeComp_fnRelease,
8281 ITypeComp_fnBind,
8282 ITypeComp_fnBindType
8285 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8286 REFIID riid, void **object)
8288 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8290 return ITypeLib2_QueryInterface((ITypeLib2*)This, riid, object);
8293 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8295 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8297 return ITypeLib2_AddRef((ITypeLib2*)This);
8300 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8302 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8304 return ITypeLib2_Release((ITypeLib2*)This);
8307 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8308 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8310 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8311 ITypeInfoImpl *info;
8312 HRESULT hres;
8314 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8316 if (!ctinfo || !name)
8317 return E_INVALIDARG;
8319 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8320 if (info)
8321 return TYPE_E_NAMECONFLICT;
8323 if (This->typeinfos)
8324 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8325 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8326 else
8327 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8329 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8331 info->pTypeLib = This;
8332 info->Name = TLB_append_str(&This->name_list, name);
8333 info->index = This->TypeInfoCount;
8334 info->TypeAttr.typekind = kind;
8335 info->TypeAttr.cbAlignment = 4;
8337 switch(info->TypeAttr.typekind) {
8338 case TKIND_ENUM:
8339 case TKIND_INTERFACE:
8340 case TKIND_DISPATCH:
8341 case TKIND_COCLASS:
8342 info->TypeAttr.cbSizeInstance = 4;
8343 break;
8344 case TKIND_RECORD:
8345 case TKIND_UNION:
8346 info->TypeAttr.cbSizeInstance = 0;
8347 break;
8348 case TKIND_MODULE:
8349 info->TypeAttr.cbSizeInstance = 2;
8350 break;
8351 case TKIND_ALIAS:
8352 info->TypeAttr.cbSizeInstance = -0x75;
8353 break;
8354 default:
8355 FIXME("unrecognized typekind %d\n", info->TypeAttr.typekind);
8356 info->TypeAttr.cbSizeInstance = 0xdeadbeef;
8357 break;
8360 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8361 &IID_ICreateTypeInfo, (void **)ctinfo);
8362 if (FAILED(hres)) {
8363 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8364 return hres;
8367 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8369 ++This->TypeInfoCount;
8371 return S_OK;
8374 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8375 LPOLESTR name)
8377 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8379 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8381 if (!name)
8382 return E_INVALIDARG;
8384 This->Name = TLB_append_str(&This->name_list, name);
8386 return S_OK;
8389 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8390 WORD majorVerNum, WORD minorVerNum)
8392 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8394 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8396 This->ver_major = majorVerNum;
8397 This->ver_minor = minorVerNum;
8399 return S_OK;
8402 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8403 REFGUID guid)
8405 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8407 TRACE("%p %s\n", This, debugstr_guid(guid));
8409 memcpy(&This->guid, guid, sizeof(GUID));
8411 return S_OK;
8414 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8415 LPOLESTR doc)
8417 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8419 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8421 if (!doc)
8422 return E_INVALIDARG;
8424 This->DocString = TLB_append_str(&This->string_list, doc);
8426 return S_OK;
8429 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8430 LPOLESTR helpFileName)
8432 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8434 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8436 if (!helpFileName)
8437 return E_INVALIDARG;
8439 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8441 return S_OK;
8444 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8445 DWORD helpContext)
8447 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8449 TRACE("%p %d\n", This, helpContext);
8451 This->dwHelpContext = helpContext;
8453 return S_OK;
8456 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8457 LCID lcid)
8459 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8461 TRACE("%p %x\n", This, lcid);
8463 This->set_lcid = lcid;
8465 return S_OK;
8468 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8469 UINT libFlags)
8471 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8473 TRACE("%p %x\n", This, libFlags);
8475 This->libflags = libFlags;
8477 return S_OK;
8480 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
8482 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8483 FIXME("%p - stub\n", This);
8484 return E_NOTIMPL;
8487 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
8488 LPOLESTR name)
8490 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8491 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
8492 return E_NOTIMPL;
8495 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
8496 REFGUID guid, VARIANT *varVal)
8498 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8499 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
8500 return E_NOTIMPL;
8503 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
8504 ULONG helpStringContext)
8506 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8507 FIXME("%p %u - stub\n", This, helpStringContext);
8508 return E_NOTIMPL;
8511 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
8512 LPOLESTR filename)
8514 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8515 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
8517 if (!filename)
8518 return E_INVALIDARG;
8520 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
8522 return S_OK;
8525 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
8526 ICreateTypeLib2_fnQueryInterface,
8527 ICreateTypeLib2_fnAddRef,
8528 ICreateTypeLib2_fnRelease,
8529 ICreateTypeLib2_fnCreateTypeInfo,
8530 ICreateTypeLib2_fnSetName,
8531 ICreateTypeLib2_fnSetVersion,
8532 ICreateTypeLib2_fnSetGuid,
8533 ICreateTypeLib2_fnSetDocString,
8534 ICreateTypeLib2_fnSetHelpFileName,
8535 ICreateTypeLib2_fnSetHelpContext,
8536 ICreateTypeLib2_fnSetLcid,
8537 ICreateTypeLib2_fnSetLibFlags,
8538 ICreateTypeLib2_fnSaveAllChanges,
8539 ICreateTypeLib2_fnDeleteTypeInfo,
8540 ICreateTypeLib2_fnSetCustData,
8541 ICreateTypeLib2_fnSetHelpStringContext,
8542 ICreateTypeLib2_fnSetHelpStringDll
8545 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
8546 REFIID riid, void **object)
8548 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8550 return ITypeInfo2_QueryInterface((ITypeInfo2*)This, riid, object);
8553 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
8555 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8557 return ITypeInfo2_AddRef((ITypeInfo2*)This);
8560 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
8562 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8564 return ITypeInfo2_Release((ITypeInfo2*)This);
8567 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
8568 REFGUID guid)
8570 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8572 TRACE("%p %s\n", This, debugstr_guid(guid));
8574 memcpy(&This->TypeAttr.guid, guid, sizeof(GUID));
8576 return S_OK;
8579 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
8580 UINT typeFlags)
8582 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8583 WORD old_flags;
8584 HRESULT hres;
8586 TRACE("%p %x\n", This, typeFlags);
8588 if (typeFlags & TYPEFLAG_FDUAL) {
8589 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
8590 ITypeLib *stdole;
8591 ITypeInfo *dispatch;
8592 HREFTYPE hreftype;
8593 HRESULT hres;
8595 hres = LoadTypeLib(stdole2tlb, &stdole);
8596 if(FAILED(hres))
8597 return hres;
8599 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
8600 ITypeLib_Release(stdole);
8601 if(FAILED(hres))
8602 return hres;
8604 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
8605 ITypeInfo_Release(dispatch);
8606 if(FAILED(hres))
8607 return hres;
8610 old_flags = This->TypeAttr.wTypeFlags;
8611 This->TypeAttr.wTypeFlags = typeFlags;
8613 hres = ICreateTypeInfo2_LayOut(iface);
8614 if (FAILED(hres)) {
8615 This->TypeAttr.wTypeFlags = old_flags;
8616 return hres;
8619 return S_OK;
8622 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
8623 LPOLESTR doc)
8625 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8627 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8629 if (!doc)
8630 return E_INVALIDARG;
8632 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
8634 return S_OK;
8637 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
8638 DWORD helpContext)
8640 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8642 TRACE("%p %d\n", This, helpContext);
8644 This->dwHelpContext = helpContext;
8646 return S_OK;
8649 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
8650 WORD majorVerNum, WORD minorVerNum)
8652 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8654 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8656 This->TypeAttr.wMajorVerNum = majorVerNum;
8657 This->TypeAttr.wMinorVerNum = minorVerNum;
8659 return S_OK;
8662 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
8663 ITypeInfo *typeInfo, HREFTYPE *refType)
8665 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8666 UINT index;
8667 ITypeLib *container;
8668 TLBRefType *ref_type;
8669 TLBImpLib *implib;
8670 TYPEATTR *typeattr;
8671 TLIBATTR *libattr;
8672 HRESULT hres;
8674 TRACE("%p %p %p\n", This, typeInfo, refType);
8676 if (!typeInfo || !refType)
8677 return E_INVALIDARG;
8679 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
8680 if (FAILED(hres))
8681 return hres;
8683 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
8684 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
8686 ITypeLib_Release(container);
8688 *refType = target->hreftype;
8690 return S_OK;
8693 hres = ITypeLib_GetLibAttr(container, &libattr);
8694 if (FAILED(hres)) {
8695 ITypeLib_Release(container);
8696 return hres;
8699 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
8700 if(IsEqualGUID(&implib->guid, &libattr->guid) &&
8701 implib->lcid == libattr->lcid &&
8702 implib->wVersionMajor == libattr->wMajorVerNum &&
8703 implib->wVersionMinor == libattr->wMinorVerNum)
8704 break;
8707 if(&implib->entry == &This->pTypeLib->implib_list){
8708 implib = heap_alloc_zero(sizeof(TLBImpLib));
8710 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
8711 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
8712 implib->name = SysAllocString(our_container->path);
8713 }else{
8714 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
8715 libattr->wMinorVerNum, libattr->lcid, &implib->name);
8716 if(FAILED(hres)){
8717 implib->name = NULL;
8718 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
8722 implib->guid = libattr->guid;
8723 implib->lcid = libattr->lcid;
8724 implib->wVersionMajor = libattr->wMajorVerNum;
8725 implib->wVersionMinor = libattr->wMinorVerNum;
8727 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
8730 ITypeLib_ReleaseTLibAttr(container, libattr);
8731 ITypeLib_Release(container);
8733 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
8734 if (FAILED(hres))
8735 return hres;
8737 index = 0;
8738 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
8739 if(ref_type->index == TLB_REF_USE_GUID &&
8740 IsEqualGUID(&ref_type->guid, &typeattr->guid) &&
8741 ref_type->tkind == typeattr->typekind)
8742 break;
8743 ++index;
8746 if(&ref_type->entry == &This->pTypeLib->ref_list){
8747 ref_type = heap_alloc_zero(sizeof(TLBRefType));
8749 ref_type->tkind = typeattr->typekind;
8750 ref_type->pImpTLInfo = implib;
8751 ref_type->reference = index * sizeof(MSFT_ImpInfo);
8753 ref_type->index = TLB_REF_USE_GUID;
8755 ref_type->guid = typeattr->guid;
8757 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
8760 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
8762 *refType = ref_type->reference | 0x1;
8764 if(IsEqualGUID(&ref_type->guid, &IID_IDispatch))
8765 This->pTypeLib->dispatch_href = *refType;
8767 return S_OK;
8770 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
8771 UINT index, FUNCDESC *funcDesc)
8773 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8774 TLBFuncDesc tmp_func_desc, *func_desc;
8775 int buf_size, i;
8776 char *buffer;
8777 HRESULT hres;
8779 TRACE("%p %u %p\n", This, index, funcDesc);
8781 if (!funcDesc || funcDesc->oVft & 3)
8782 return E_INVALIDARG;
8784 switch (This->TypeAttr.typekind) {
8785 case TKIND_MODULE:
8786 if (funcDesc->funckind != FUNC_STATIC)
8787 return TYPE_E_BADMODULEKIND;
8788 break;
8789 case TKIND_DISPATCH:
8790 if (funcDesc->funckind != FUNC_DISPATCH)
8791 return TYPE_E_BADMODULEKIND;
8792 break;
8793 default:
8794 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
8795 return TYPE_E_BADMODULEKIND;
8798 if (index > This->TypeAttr.cFuncs)
8799 return TYPE_E_ELEMENTNOTFOUND;
8801 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
8802 !funcDesc->cParams)
8803 return TYPE_E_INCONSISTENTPROPFUNCS;
8805 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
8806 TLBFuncDesc_Constructor(&tmp_func_desc);
8808 tmp_func_desc.funcdesc = *funcDesc;
8810 if (tmp_func_desc.funcdesc.oVft != 0)
8811 tmp_func_desc.funcdesc.oVft |= 1;
8813 if (funcDesc->cScodes) {
8814 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
8815 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
8816 } else
8817 tmp_func_desc.funcdesc.lprgscode = NULL;
8819 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
8820 for (i = 0; i < funcDesc->cParams; ++i) {
8821 buf_size += sizeof(ELEMDESC);
8822 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
8824 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
8825 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
8827 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
8828 if (FAILED(hres)) {
8829 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
8830 heap_free(tmp_func_desc.funcdesc.lprgscode);
8831 return hres;
8834 for (i = 0; i < funcDesc->cParams; ++i) {
8835 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
8836 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
8837 if (FAILED(hres)) {
8838 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
8839 heap_free(tmp_func_desc.funcdesc.lprgscode);
8840 return hres;
8842 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
8843 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
8844 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
8845 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
8846 if (FAILED(hres)) {
8847 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
8848 heap_free(tmp_func_desc.funcdesc.lprgscode);
8849 return hres;
8854 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
8856 if (This->funcdescs) {
8857 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
8858 sizeof(TLBFuncDesc) * (This->TypeAttr.cFuncs + 1));
8860 if (index < This->TypeAttr.cFuncs) {
8861 memmove(This->funcdescs + index + 1, This->funcdescs + index,
8862 (This->TypeAttr.cFuncs - index) * sizeof(TLBFuncDesc));
8863 func_desc = This->funcdescs + index;
8864 } else
8865 func_desc = This->funcdescs + This->TypeAttr.cFuncs;
8867 /* move custdata lists to the new memory location */
8868 for(i = 0; i < This->TypeAttr.cFuncs + 1; ++i){
8869 if(index != i){
8870 TLBFuncDesc *fd = &This->funcdescs[i];
8871 if(fd->custdata_list.prev == fd->custdata_list.next)
8872 list_init(&fd->custdata_list);
8873 else{
8874 fd->custdata_list.prev->next = &fd->custdata_list;
8875 fd->custdata_list.next->prev = &fd->custdata_list;
8879 } else
8880 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
8882 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
8883 list_init(&func_desc->custdata_list);
8885 ++This->TypeAttr.cFuncs;
8887 This->needs_layout = TRUE;
8889 return S_OK;
8892 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
8893 UINT index, HREFTYPE refType)
8895 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8896 TLBImplType *impl_type;
8897 HRESULT hres;
8899 TRACE("%p %u %d\n", This, index, refType);
8901 switch(This->TypeAttr.typekind){
8902 case TKIND_COCLASS: {
8903 if (index == -1) {
8904 FIXME("Unhandled index: -1\n");
8905 return E_NOTIMPL;
8908 if(index != This->TypeAttr.cImplTypes)
8909 return TYPE_E_ELEMENTNOTFOUND;
8911 break;
8913 case TKIND_INTERFACE:
8914 case TKIND_DISPATCH:
8915 if (index != 0 || This->TypeAttr.cImplTypes)
8916 return TYPE_E_ELEMENTNOTFOUND;
8917 break;
8918 default:
8919 FIXME("Unimplemented typekind: %d\n", This->TypeAttr.typekind);
8920 return E_NOTIMPL;
8923 if (This->impltypes){
8924 UINT i;
8926 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
8927 sizeof(TLBImplType) * (This->TypeAttr.cImplTypes + 1));
8929 if (index < This->TypeAttr.cImplTypes) {
8930 memmove(This->impltypes + index + 1, This->impltypes + index,
8931 (This->TypeAttr.cImplTypes - index) * sizeof(TLBImplType));
8932 impl_type = This->impltypes + index;
8933 } else
8934 impl_type = This->impltypes + This->TypeAttr.cImplTypes;
8936 /* move custdata lists to the new memory location */
8937 for(i = 0; i < This->TypeAttr.cImplTypes + 1; ++i){
8938 if(index != i){
8939 TLBImplType *it = &This->impltypes[i];
8940 if(it->custdata_list.prev == it->custdata_list.next)
8941 list_init(&it->custdata_list);
8942 else{
8943 it->custdata_list.prev->next = &it->custdata_list;
8944 it->custdata_list.next->prev = &it->custdata_list;
8948 } else
8949 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
8951 memset(impl_type, 0, sizeof(TLBImplType));
8952 TLBImplType_Constructor(impl_type);
8953 impl_type->hRef = refType;
8955 ++This->TypeAttr.cImplTypes;
8957 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
8958 This->TypeAttr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
8960 hres = ICreateTypeInfo2_LayOut(iface);
8961 if (FAILED(hres))
8962 return hres;
8964 return S_OK;
8967 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
8968 UINT index, INT implTypeFlags)
8970 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8971 TLBImplType *impl_type = &This->impltypes[index];
8973 TRACE("%p %u %x\n", This, index, implTypeFlags);
8975 if (This->TypeAttr.typekind != TKIND_COCLASS)
8976 return TYPE_E_BADMODULEKIND;
8978 if (index >= This->TypeAttr.cImplTypes)
8979 return TYPE_E_ELEMENTNOTFOUND;
8981 impl_type->implflags = implTypeFlags;
8983 return S_OK;
8986 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
8987 WORD alignment)
8989 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8991 TRACE("%p %d\n", This, alignment);
8993 This->TypeAttr.cbAlignment = alignment;
8995 return S_OK;
8998 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
8999 LPOLESTR schema)
9001 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9003 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
9005 if (!schema)
9006 return E_INVALIDARG;
9008 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
9010 This->TypeAttr.lpstrSchema = This->Schema->str;
9012 return S_OK;
9015 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
9016 UINT index, VARDESC *varDesc)
9018 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9019 FIXME("%p %u %p - stub\n", This, index, varDesc);
9020 return E_NOTIMPL;
9023 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
9024 UINT index, LPOLESTR *names, UINT numNames)
9026 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9027 TLBFuncDesc *func_desc = &This->funcdescs[index];
9028 int i;
9030 TRACE("%p %u %p %u\n", This, index, names, numNames);
9032 if (!names)
9033 return E_INVALIDARG;
9035 if (index >= This->TypeAttr.cFuncs || numNames == 0)
9036 return TYPE_E_ELEMENTNOTFOUND;
9038 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
9039 if(numNames > func_desc->funcdesc.cParams)
9040 return TYPE_E_ELEMENTNOTFOUND;
9041 } else
9042 if(numNames > func_desc->funcdesc.cParams + 1)
9043 return TYPE_E_ELEMENTNOTFOUND;
9045 for(i = 0; i < This->TypeAttr.cFuncs; ++i) {
9046 TLBFuncDesc *iter = &This->funcdescs[i];
9047 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
9048 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
9049 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
9050 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
9051 continue;
9052 return TYPE_E_AMBIGUOUSNAME;
9056 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
9058 for (i = 1; i < numNames; ++i) {
9059 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
9060 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
9063 return S_OK;
9066 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
9067 UINT index, LPOLESTR name)
9069 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9070 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(name));
9071 return E_NOTIMPL;
9074 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
9075 TYPEDESC *tdescAlias)
9077 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9078 FIXME("%p %p - stub\n", This, tdescAlias);
9079 return E_NOTIMPL;
9082 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
9083 UINT index, LPOLESTR dllName, LPOLESTR procName)
9085 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9086 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
9087 return E_NOTIMPL;
9090 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
9091 UINT index, LPOLESTR docString)
9093 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9094 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
9095 return E_NOTIMPL;
9098 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
9099 UINT index, LPOLESTR docString)
9101 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9102 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
9103 return E_NOTIMPL;
9106 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
9107 UINT index, DWORD helpContext)
9109 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9110 TLBFuncDesc *func_desc = &This->funcdescs[index];
9112 TRACE("%p %u %d\n", This, index, helpContext);
9114 if(index >= This->TypeAttr.cFuncs)
9115 return TYPE_E_ELEMENTNOTFOUND;
9117 func_desc->helpcontext = helpContext;
9119 return S_OK;
9122 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
9123 UINT index, DWORD helpContext)
9125 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9126 FIXME("%p %u %d - stub\n", This, index, helpContext);
9127 return E_NOTIMPL;
9130 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
9131 UINT index, BSTR bstrMops)
9133 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9134 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
9135 return E_NOTIMPL;
9138 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
9139 IDLDESC *idlDesc)
9141 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9143 TRACE("%p %p\n", This, idlDesc);
9145 if (!idlDesc)
9146 return E_INVALIDARG;
9148 This->TypeAttr.idldescType.dwReserved = idlDesc->dwReserved;
9149 This->TypeAttr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
9151 return S_OK;
9154 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
9156 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9157 ITypeInfo *tinfo;
9158 TLBFuncDesc *func_desc;
9159 UINT user_vft = 0, i, depth = 0;
9160 HRESULT hres = S_OK;
9162 TRACE("%p\n", This);
9164 This->needs_layout = FALSE;
9166 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
9167 if (FAILED(hres))
9168 return hres;
9170 if (This->TypeAttr.typekind == TKIND_INTERFACE) {
9171 ITypeInfo *inh;
9172 TYPEATTR *attr;
9173 HREFTYPE inh_href;
9175 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
9177 if (SUCCEEDED(hres)) {
9178 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
9180 if (SUCCEEDED(hres)) {
9181 hres = ITypeInfo_GetTypeAttr(inh, &attr);
9182 if (FAILED(hres)) {
9183 ITypeInfo_Release(inh);
9184 ITypeInfo_Release(tinfo);
9185 return hres;
9187 This->TypeAttr.cbSizeVft = attr->cbSizeVft * 4 / sizeof(void*);
9188 ITypeInfo_ReleaseTypeAttr(inh, attr);
9191 ++depth;
9192 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
9193 if(SUCCEEDED(hres)){
9194 ITypeInfo *next;
9195 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
9196 if(SUCCEEDED(hres)){
9197 ITypeInfo_Release(inh);
9198 inh = next;
9201 }while(SUCCEEDED(hres));
9202 hres = S_OK;
9204 ITypeInfo_Release(inh);
9205 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
9206 This->TypeAttr.cbSizeVft = 0;
9207 hres = S_OK;
9208 } else {
9209 ITypeInfo_Release(tinfo);
9210 return hres;
9212 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
9213 This->TypeAttr.cbSizeVft = 0;
9214 hres = S_OK;
9215 } else {
9216 ITypeInfo_Release(tinfo);
9217 return hres;
9219 } else if (This->TypeAttr.typekind == TKIND_DISPATCH)
9220 This->TypeAttr.cbSizeVft = 7 * sizeof(void*);
9221 else
9222 This->TypeAttr.cbSizeVft = 0;
9224 func_desc = This->funcdescs;
9225 i = 0;
9226 while (i < This->TypeAttr.cFuncs) {
9227 if (!(func_desc->funcdesc.oVft & 0x1))
9228 func_desc->funcdesc.oVft = This->TypeAttr.cbSizeVft;
9230 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
9231 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
9233 This->TypeAttr.cbSizeVft += sizeof(void*);
9235 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
9236 TLBFuncDesc *iter;
9237 UINT j = 0;
9238 BOOL reset = FALSE;
9240 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
9242 iter = This->funcdescs;
9243 while (j < This->TypeAttr.cFuncs) {
9244 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
9245 if (!reset) {
9246 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->TypeAttr.cFuncs;
9247 reset = TRUE;
9248 } else
9249 ++func_desc->funcdesc.memid;
9250 iter = This->funcdescs;
9251 j = 0;
9252 } else {
9253 ++iter;
9254 ++j;
9259 ++func_desc;
9260 ++i;
9263 if (user_vft > This->TypeAttr.cbSizeVft)
9264 This->TypeAttr.cbSizeVft = user_vft + sizeof(void*);
9266 ITypeInfo_Release(tinfo);
9267 return hres;
9270 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
9271 UINT index)
9273 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9274 FIXME("%p %u - stub\n", This, index);
9275 return E_NOTIMPL;
9278 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
9279 MEMBERID memid, INVOKEKIND invKind)
9281 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9282 FIXME("%p %x %d - stub\n", This, memid, invKind);
9283 return E_NOTIMPL;
9286 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
9287 UINT index)
9289 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9290 FIXME("%p %u - stub\n", This, index);
9291 return E_NOTIMPL;
9294 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
9295 MEMBERID memid)
9297 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9298 FIXME("%p %x - stub\n", This, memid);
9299 return E_NOTIMPL;
9302 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
9303 UINT index)
9305 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9306 FIXME("%p %u - stub\n", This, index);
9307 return E_NOTIMPL;
9310 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
9311 REFGUID guid, VARIANT *varVal)
9313 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9315 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
9317 if (!guid || !varVal)
9318 return E_INVALIDARG;
9320 return TLB_set_custdata(&This->custdata_list, guid, varVal);
9323 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
9324 UINT index, REFGUID guid, VARIANT *varVal)
9326 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9327 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
9328 return E_NOTIMPL;
9331 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
9332 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
9334 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9335 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
9336 return E_NOTIMPL;
9339 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
9340 UINT index, REFGUID guid, VARIANT *varVal)
9342 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9343 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
9344 return E_NOTIMPL;
9347 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
9348 UINT index, REFGUID guid, VARIANT *varVal)
9350 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9351 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
9352 return E_NOTIMPL;
9355 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
9356 ULONG helpStringContext)
9358 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9360 TRACE("%p %u\n", This, helpStringContext);
9362 This->dwHelpStringContext = helpStringContext;
9364 return S_OK;
9367 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
9368 UINT index, ULONG helpStringContext)
9370 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9371 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
9372 return E_NOTIMPL;
9375 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
9376 UINT index, ULONG helpStringContext)
9378 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9379 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
9380 return E_NOTIMPL;
9383 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
9385 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9386 FIXME("%p - stub\n", This);
9387 return E_NOTIMPL;
9390 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
9391 LPOLESTR name)
9393 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9395 TRACE("%p %s\n", This, wine_dbgstr_w(name));
9397 if (!name)
9398 return E_INVALIDARG;
9400 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
9402 return S_OK;
9405 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
9406 ICreateTypeInfo2_fnQueryInterface,
9407 ICreateTypeInfo2_fnAddRef,
9408 ICreateTypeInfo2_fnRelease,
9409 ICreateTypeInfo2_fnSetGuid,
9410 ICreateTypeInfo2_fnSetTypeFlags,
9411 ICreateTypeInfo2_fnSetDocString,
9412 ICreateTypeInfo2_fnSetHelpContext,
9413 ICreateTypeInfo2_fnSetVersion,
9414 ICreateTypeInfo2_fnAddRefTypeInfo,
9415 ICreateTypeInfo2_fnAddFuncDesc,
9416 ICreateTypeInfo2_fnAddImplType,
9417 ICreateTypeInfo2_fnSetImplTypeFlags,
9418 ICreateTypeInfo2_fnSetAlignment,
9419 ICreateTypeInfo2_fnSetSchema,
9420 ICreateTypeInfo2_fnAddVarDesc,
9421 ICreateTypeInfo2_fnSetFuncAndParamNames,
9422 ICreateTypeInfo2_fnSetVarName,
9423 ICreateTypeInfo2_fnSetTypeDescAlias,
9424 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
9425 ICreateTypeInfo2_fnSetFuncDocString,
9426 ICreateTypeInfo2_fnSetVarDocString,
9427 ICreateTypeInfo2_fnSetFuncHelpContext,
9428 ICreateTypeInfo2_fnSetVarHelpContext,
9429 ICreateTypeInfo2_fnSetMops,
9430 ICreateTypeInfo2_fnSetTypeIdldesc,
9431 ICreateTypeInfo2_fnLayOut,
9432 ICreateTypeInfo2_fnDeleteFuncDesc,
9433 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
9434 ICreateTypeInfo2_fnDeleteVarDesc,
9435 ICreateTypeInfo2_fnDeleteVarDescByMemId,
9436 ICreateTypeInfo2_fnDeleteImplType,
9437 ICreateTypeInfo2_fnSetCustData,
9438 ICreateTypeInfo2_fnSetFuncCustData,
9439 ICreateTypeInfo2_fnSetParamCustData,
9440 ICreateTypeInfo2_fnSetVarCustData,
9441 ICreateTypeInfo2_fnSetImplTypeCustData,
9442 ICreateTypeInfo2_fnSetHelpStringContext,
9443 ICreateTypeInfo2_fnSetFuncHelpStringContext,
9444 ICreateTypeInfo2_fnSetVarHelpStringContext,
9445 ICreateTypeInfo2_fnInvalidate,
9446 ICreateTypeInfo2_fnSetName