oleaut32: Correct version byte order.
[wine.git] / dlls / oleaut32 / typelib.c
blob48a698f832abc5af10150c85bdf9dc450c11bed6
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 "winternl.h"
70 #include "lzexpand.h"
72 #include "wine/unicode.h"
73 #include "objbase.h"
74 #include "typelib.h"
75 #include "wine/debug.h"
76 #include "variant.h"
77 #include "wine/list.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(ole);
80 WINE_DECLARE_DEBUG_CHANNEL(typelib);
82 typedef struct
84 WORD offset;
85 WORD length;
86 WORD flags;
87 WORD id;
88 WORD handle;
89 WORD usage;
90 } NE_NAMEINFO;
92 typedef struct
94 WORD type_id; /* Type identifier */
95 WORD count; /* Number of resources of this type */
96 DWORD resloader; /* SetResourceHandler() */
98 * Name info array.
100 } NE_TYPEINFO;
102 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
103 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
104 static void TLB_FreeVarDesc(VARDESC*);
106 /****************************************************************************
107 * FromLExxx
109 * Takes p_iVal (which is in little endian) and returns it
110 * in the host machine's byte order.
112 #ifdef WORDS_BIGENDIAN
113 static WORD FromLEWord(WORD p_iVal)
115 return (((p_iVal & 0x00FF) << 8) |
116 ((p_iVal & 0xFF00) >> 8));
120 static DWORD FromLEDWord(DWORD p_iVal)
122 return (((p_iVal & 0x000000FF) << 24) |
123 ((p_iVal & 0x0000FF00) << 8) |
124 ((p_iVal & 0x00FF0000) >> 8) |
125 ((p_iVal & 0xFF000000) >> 24));
127 #else
128 #define FromLEWord(X) (X)
129 #define FromLEDWord(X) (X)
130 #endif
132 #define DISPATCH_HREF_OFFSET 0x01000000
133 #define DISPATCH_HREF_MASK 0xff000000
135 /****************************************************************************
136 * FromLExxx
138 * Fix byte order in any structure if necessary
140 #ifdef WORDS_BIGENDIAN
141 static void FromLEWords(void *p_Val, int p_iSize)
143 WORD *Val = p_Val;
145 p_iSize /= sizeof(WORD);
147 while (p_iSize) {
148 *Val = FromLEWord(*Val);
149 Val++;
150 p_iSize--;
155 static void FromLEDWords(void *p_Val, int p_iSize)
157 DWORD *Val = p_Val;
159 p_iSize /= sizeof(DWORD);
161 while (p_iSize) {
162 *Val = FromLEDWord(*Val);
163 Val++;
164 p_iSize--;
167 #else
168 #define FromLEWords(X,Y) /*nothing*/
169 #define FromLEDWords(X,Y) /*nothing*/
170 #endif
173 * Find a typelib key which matches a requested maj.min version.
175 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
177 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
178 WCHAR buffer[60];
179 char key_name[16];
180 DWORD len, i;
181 INT best_maj = -1, best_min = -1;
182 HKEY hkey;
184 memcpy( buffer, typelibW, sizeof(typelibW) );
185 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
187 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
188 return FALSE;
190 len = sizeof(key_name);
191 i = 0;
192 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
194 INT v_maj, v_min;
196 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
198 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
200 if (*wMaj == 0xffff && *wMin == 0xffff)
202 if (v_maj > best_maj) best_maj = v_maj;
203 if (v_min > best_min) best_min = v_min;
205 else if (*wMaj == v_maj)
207 best_maj = v_maj;
209 if (*wMin == v_min)
211 best_min = v_min;
212 break; /* exact match */
214 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
217 len = sizeof(key_name);
219 RegCloseKey( hkey );
221 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
223 if (*wMaj == 0xffff && *wMin == 0xffff)
225 if (best_maj >= 0 && best_min >= 0)
227 *wMaj = best_maj;
228 *wMin = best_min;
229 return TRUE;
233 if (*wMaj == best_maj && best_min >= 0)
235 *wMin = best_min;
236 return TRUE;
238 return FALSE;
241 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
242 /* buffer must be at least 60 characters long */
243 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
245 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
246 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
248 memcpy( buffer, TypelibW, sizeof(TypelibW) );
249 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
250 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
251 return buffer;
254 /* get the path of an interface key, in the form "Interface\\<guid>" */
255 /* buffer must be at least 50 characters long */
256 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
258 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
260 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
261 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
262 return buffer;
265 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
266 /* buffer must be at least 16 characters long */
267 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
269 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
270 static const WCHAR win16W[] = {'w','i','n','1','6',0};
271 static const WCHAR win32W[] = {'w','i','n','3','2',0};
272 static const WCHAR win64W[] = {'w','i','n','6','4',0};
274 sprintfW( buffer, LcidFormatW, lcid );
275 switch(syskind)
277 case SYS_WIN16: strcatW( buffer, win16W ); break;
278 case SYS_WIN32: strcatW( buffer, win32W ); break;
279 case SYS_WIN64: strcatW( buffer, win64W ); break;
280 default:
281 TRACE("Typelib is for unsupported syskind %i\n", syskind);
282 return NULL;
284 return buffer;
287 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
290 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
291 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
292 SYSKIND syskind, LCID lcid, LPBSTR path )
294 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
295 LCID myLCID = lcid;
296 HKEY hkey;
297 WCHAR buffer[60];
298 WCHAR Path[MAX_PATH];
299 LONG res;
301 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
303 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
304 get_typelib_key( guid, wMaj, wMin, buffer );
306 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
307 if (res == ERROR_FILE_NOT_FOUND)
309 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
310 return TYPE_E_LIBNOTREGISTERED;
312 else if (res != ERROR_SUCCESS)
314 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
315 return TYPE_E_REGISTRYACCESS;
318 while (hr != S_OK)
320 LONG dwPathLen = sizeof(Path);
322 get_lcid_subkey( myLCID, syskind, buffer );
324 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
326 if (!lcid)
327 break;
328 else if (myLCID == lcid)
330 /* try with sub-langid */
331 myLCID = SUBLANGID(lcid);
333 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
335 /* try with system langid */
336 myLCID = 0;
338 else
340 break;
343 else
345 *path = SysAllocString( Path );
346 hr = S_OK;
349 RegCloseKey( hkey );
350 TRACE_(typelib)("-- 0x%08x\n", hr);
351 return hr;
354 /****************************************************************************
355 * QueryPathOfRegTypeLib [OLEAUT32.164]
357 * Gets the path to a registered type library.
359 * PARAMS
360 * guid [I] referenced guid
361 * wMaj [I] major version
362 * wMin [I] minor version
363 * lcid [I] locale id
364 * path [O] path of typelib
366 * RETURNS
367 * Success: S_OK.
368 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
369 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
370 * opened.
372 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
374 #ifdef _WIN64
375 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path );
376 if(SUCCEEDED(hres))
377 return hres;
378 #endif
379 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
382 /******************************************************************************
383 * CreateTypeLib [OLEAUT32.160] creates a typelib
385 * RETURNS
386 * Success: S_OK
387 * Failure: Status
389 HRESULT WINAPI CreateTypeLib(
390 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
392 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
393 return E_FAIL;
396 /******************************************************************************
397 * LoadTypeLib [OLEAUT32.161]
399 * Loads a type library
401 * PARAMS
402 * szFile [I] Name of file to load from.
403 * pptLib [O] Pointer that receives ITypeLib object on success.
405 * RETURNS
406 * Success: S_OK
407 * Failure: Status
409 * SEE
410 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
412 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
414 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
415 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
418 /******************************************************************************
419 * LoadTypeLibEx [OLEAUT32.183]
421 * Loads and optionally registers a type library
423 * RETURNS
424 * Success: S_OK
425 * Failure: Status
427 HRESULT WINAPI LoadTypeLibEx(
428 LPCOLESTR szFile, /* [in] Name of file to load from */
429 REGKIND regkind, /* [in] Specify kind of registration */
430 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
432 WCHAR szPath[MAX_PATH+1];
433 HRESULT res;
435 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
437 *pptLib = NULL;
439 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
441 if (SUCCEEDED(res))
442 switch(regkind)
444 case REGKIND_DEFAULT:
445 /* don't register typelibs supplied with full path. Experimentation confirms the following */
446 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
447 (szFile[0] && (szFile[1] == ':'))) break;
448 /* else fall-through */
450 case REGKIND_REGISTER:
451 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
453 ITypeLib_Release(*pptLib);
454 *pptLib = 0;
456 break;
457 case REGKIND_NONE:
458 break;
461 TRACE(" returns %08x\n",res);
462 return res;
465 /******************************************************************************
466 * LoadRegTypeLib [OLEAUT32.162]
468 * Loads a registered type library.
470 * PARAMS
471 * rguid [I] GUID of the registered type library.
472 * wVerMajor [I] major version.
473 * wVerMinor [I] minor version.
474 * lcid [I] locale ID.
475 * ppTLib [O] pointer that receives an ITypeLib object on success.
477 * RETURNS
478 * Success: S_OK.
479 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
480 * LoadTypeLib.
482 HRESULT WINAPI LoadRegTypeLib(
483 REFGUID rguid,
484 WORD wVerMajor,
485 WORD wVerMinor,
486 LCID lcid,
487 ITypeLib **ppTLib)
489 BSTR bstr=NULL;
490 HRESULT res;
492 *ppTLib = NULL;
494 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
496 if(SUCCEEDED(res))
498 res= LoadTypeLib(bstr, ppTLib);
499 SysFreeString(bstr);
502 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
504 return res;
508 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
509 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
510 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
511 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
512 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
513 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
515 /******************************************************************************
516 * RegisterTypeLib [OLEAUT32.163]
517 * Adds information about a type library to the System Registry
518 * NOTES
519 * Docs: ITypeLib FAR * ptlib
520 * Docs: OLECHAR FAR* szFullPath
521 * Docs: OLECHAR FAR* szHelpDir
523 * RETURNS
524 * Success: S_OK
525 * Failure: Status
527 HRESULT WINAPI RegisterTypeLib(
528 ITypeLib * ptlib, /* [in] Pointer to the library*/
529 OLECHAR * szFullPath, /* [in] full Path of the library*/
530 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
531 may be NULL*/
533 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
534 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
535 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
536 HRESULT res;
537 TLIBATTR *attr;
538 WCHAR keyName[60];
539 WCHAR tmp[16];
540 HKEY key, subKey;
541 UINT types, tidx;
542 TYPEKIND kind;
543 DWORD disposition;
545 if (ptlib == NULL || szFullPath == NULL)
546 return E_INVALIDARG;
548 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
549 return E_FAIL;
551 #ifndef _WIN64
552 if (attr->syskind == SYS_WIN64) 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 tagTLBGuid {
959 GUID guid;
960 INT hreftype;
961 UINT offset;
962 struct list entry;
963 } TLBGuid;
965 typedef struct tagTLBCustData
967 TLBGuid *guid;
968 VARIANT data;
969 struct list entry;
970 } TLBCustData;
972 /* data structure for import typelibs */
973 typedef struct tagTLBImpLib
975 int offset; /* offset in the file (MSFT)
976 offset in nametable (SLTG)
977 just used to identify library while reading
978 data from file */
979 TLBGuid *guid; /* libid */
980 BSTR name; /* name */
982 LCID lcid; /* lcid of imported typelib */
984 WORD wVersionMajor; /* major version number */
985 WORD wVersionMinor; /* minor version number */
987 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
988 NULL if not yet loaded */
989 struct list entry;
990 } TLBImpLib;
992 typedef struct tagTLBString {
993 BSTR str;
994 UINT offset;
995 struct list entry;
996 } TLBString;
998 /* internal ITypeLib data */
999 typedef struct tagITypeLibImpl
1001 ITypeLib2 ITypeLib2_iface;
1002 ITypeComp ITypeComp_iface;
1003 ICreateTypeLib2 ICreateTypeLib2_iface;
1004 LONG ref;
1005 TLBGuid *guid;
1006 LCID lcid;
1007 SYSKIND syskind;
1008 int ptr_size;
1009 WORD ver_major;
1010 WORD ver_minor;
1011 WORD libflags;
1012 LCID set_lcid;
1014 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1015 * exported to the application as a UNICODE string.
1017 struct list string_list;
1018 struct list name_list;
1019 struct list guid_list;
1021 const TLBString *Name;
1022 const TLBString *DocString;
1023 const TLBString *HelpFile;
1024 const TLBString *HelpStringDll;
1025 DWORD dwHelpContext;
1026 int TypeInfoCount; /* nr of typeinfo's in librarry */
1027 struct tagITypeInfoImpl **typeinfos;
1028 struct list custdata_list;
1029 struct list implib_list;
1030 int ctTypeDesc; /* number of items in type desc array */
1031 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1032 library. Only used while reading MSFT
1033 typelibs */
1034 struct list ref_list; /* list of ref types in this typelib */
1035 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1038 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1039 struct list entry;
1040 WCHAR *path;
1041 INT index;
1042 } ITypeLibImpl;
1044 static const ITypeLib2Vtbl tlbvt;
1045 static const ITypeCompVtbl tlbtcvt;
1046 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1048 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1050 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1053 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1055 return impl_from_ITypeLib2((ITypeLib2*)iface);
1058 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1060 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1063 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1065 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1068 /* ITypeLib methods */
1069 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1070 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1072 /*======================= ITypeInfo implementation =======================*/
1074 /* data for referenced types */
1075 typedef struct tagTLBRefType
1077 INT index; /* Type index for internal ref or for external ref
1078 it the format is SLTG. -2 indicates to
1079 use guid */
1081 TYPEKIND tkind;
1082 TLBGuid *guid; /* guid of the referenced type */
1083 /* if index == TLB_REF_USE_GUID */
1085 HREFTYPE reference; /* The href of this ref */
1086 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1087 TLB_REF_INTERNAL for internal refs
1088 TLB_REF_NOT_FOUND for broken refs */
1090 struct list entry;
1091 } TLBRefType;
1093 #define TLB_REF_USE_GUID -2
1095 #define TLB_REF_INTERNAL (void*)-2
1096 #define TLB_REF_NOT_FOUND (void*)-1
1098 /* internal Parameter data */
1099 typedef struct tagTLBParDesc
1101 const TLBString *Name;
1102 struct list custdata_list;
1103 } TLBParDesc;
1105 /* internal Function data */
1106 typedef struct tagTLBFuncDesc
1108 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1109 const TLBString *Name; /* the name of this function */
1110 TLBParDesc *pParamDesc; /* array with param names and custom data */
1111 int helpcontext;
1112 int HelpStringContext;
1113 const TLBString *HelpString;
1114 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1115 struct list custdata_list;
1116 } TLBFuncDesc;
1118 /* internal Variable data */
1119 typedef struct tagTLBVarDesc
1121 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1122 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1123 const TLBString *Name; /* the name of this variable */
1124 int HelpContext;
1125 int HelpStringContext;
1126 const TLBString *HelpString;
1127 struct list custdata_list;
1128 } TLBVarDesc;
1130 /* internal implemented interface data */
1131 typedef struct tagTLBImplType
1133 HREFTYPE hRef; /* hRef of interface */
1134 int implflags; /* IMPLFLAG_*s */
1135 struct list custdata_list;
1136 } TLBImplType;
1138 /* internal TypeInfo data */
1139 typedef struct tagITypeInfoImpl
1141 ITypeInfo2 ITypeInfo2_iface;
1142 ITypeComp ITypeComp_iface;
1143 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1144 LONG ref;
1145 BOOL not_attached_to_typelib;
1146 BOOL needs_layout;
1148 TLBGuid *guid;
1149 LCID lcid;
1150 MEMBERID memidConstructor;
1151 MEMBERID memidDestructor;
1152 LPOLESTR lpstrSchema;
1153 ULONG cbSizeInstance;
1154 TYPEKIND typekind;
1155 WORD cFuncs;
1156 WORD cVars;
1157 WORD cImplTypes;
1158 WORD cbSizeVft;
1159 WORD cbAlignment;
1160 WORD wTypeFlags;
1161 WORD wMajorVerNum;
1162 WORD wMinorVerNum;
1163 TYPEDESC tdescAlias;
1164 IDLDESC idldescType;
1166 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1167 int index; /* index in this typelib; */
1168 HREFTYPE hreftype; /* hreftype for app object binding */
1169 /* type libs seem to store the doc strings in ascii
1170 * so why should we do it in unicode?
1172 const TLBString *Name;
1173 const TLBString *DocString;
1174 const TLBString *DllName;
1175 const TLBString *Schema;
1176 DWORD dwHelpContext;
1177 DWORD dwHelpStringContext;
1179 /* functions */
1180 TLBFuncDesc *funcdescs;
1182 /* variables */
1183 TLBVarDesc *vardescs;
1185 /* Implemented Interfaces */
1186 TLBImplType *impltypes;
1188 struct list *pcustdata_list;
1189 struct list custdata_list;
1190 } ITypeInfoImpl;
1192 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1194 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1197 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1199 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1202 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1204 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1207 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1209 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1212 static const ITypeInfo2Vtbl tinfvt;
1213 static const ITypeCompVtbl tcompvt;
1214 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1216 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1217 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1219 typedef struct tagTLBContext
1221 unsigned int oStart; /* start of TLB in file */
1222 unsigned int pos; /* current pos */
1223 unsigned int length; /* total length */
1224 void *mapping; /* memory mapping */
1225 MSFT_SegDir * pTblDir;
1226 ITypeLibImpl* pLibInfo;
1227 } TLBContext;
1230 static inline BSTR TLB_get_bstr(const TLBString *str)
1232 return str != NULL ? str->str : NULL;
1235 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1237 if(!str)
1238 return 1;
1239 return memcmp(left, str->str, len);
1242 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1244 return guid != NULL ? &guid->guid : NULL;
1247 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1249 return guid != NULL ? &guid->guid : &GUID_NULL;
1252 static int get_ptr_size(SYSKIND syskind)
1254 switch(syskind){
1255 case SYS_WIN64:
1256 return 8;
1257 case SYS_WIN32:
1258 case SYS_MAC:
1259 case SYS_WIN16:
1260 return 4;
1262 WARN("Unhandled syskind: 0x%x\n", syskind);
1263 return 4;
1267 debug
1269 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1270 if (pTD->vt & VT_RESERVED)
1271 szVarType += strlen(strcpy(szVarType, "reserved | "));
1272 if (pTD->vt & VT_BYREF)
1273 szVarType += strlen(strcpy(szVarType, "ref to "));
1274 if (pTD->vt & VT_ARRAY)
1275 szVarType += strlen(strcpy(szVarType, "array of "));
1276 if (pTD->vt & VT_VECTOR)
1277 szVarType += strlen(strcpy(szVarType, "vector of "));
1278 switch(pTD->vt & VT_TYPEMASK) {
1279 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1280 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1281 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1282 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1283 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1284 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1285 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1286 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1287 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1288 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1289 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1290 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1291 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1292 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1293 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1294 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1295 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1296 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1297 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1298 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1299 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1300 pTD->u.hreftype); break;
1301 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1302 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1303 case VT_PTR: sprintf(szVarType, "ptr to ");
1304 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1305 break;
1306 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1307 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1308 break;
1309 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1310 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1311 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1312 break;
1314 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1318 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1319 char buf[200];
1320 USHORT flags = edesc->u.paramdesc.wParamFlags;
1321 dump_TypeDesc(&edesc->tdesc,buf);
1322 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1323 MESSAGE("\t\tu.paramdesc.wParamFlags");
1324 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1325 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1326 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1327 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1328 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1329 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1330 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1331 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1332 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1334 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1335 int i;
1336 MESSAGE("memid is %08x\n",funcdesc->memid);
1337 for (i=0;i<funcdesc->cParams;i++) {
1338 MESSAGE("Param %d:\n",i);
1339 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1341 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1342 switch (funcdesc->funckind) {
1343 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1344 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1345 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1346 case FUNC_STATIC: MESSAGE("static");break;
1347 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1348 default: MESSAGE("unknown");break;
1350 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1351 switch (funcdesc->invkind) {
1352 case INVOKE_FUNC: MESSAGE("func");break;
1353 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1354 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1355 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1357 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1358 switch (funcdesc->callconv) {
1359 case CC_CDECL: MESSAGE("cdecl");break;
1360 case CC_PASCAL: MESSAGE("pascal");break;
1361 case CC_STDCALL: MESSAGE("stdcall");break;
1362 case CC_SYSCALL: MESSAGE("syscall");break;
1363 default:break;
1365 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1366 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1367 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1369 MESSAGE("\telemdescFunc (return value type):\n");
1370 dump_ELEMDESC(&funcdesc->elemdescFunc);
1373 static const char * const typekind_desc[] =
1375 "TKIND_ENUM",
1376 "TKIND_RECORD",
1377 "TKIND_MODULE",
1378 "TKIND_INTERFACE",
1379 "TKIND_DISPATCH",
1380 "TKIND_COCLASS",
1381 "TKIND_ALIAS",
1382 "TKIND_UNION",
1383 "TKIND_MAX"
1386 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1388 int i;
1389 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1390 for (i=0;i<pfd->funcdesc.cParams;i++)
1391 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1394 dump_FUNCDESC(&(pfd->funcdesc));
1396 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1397 if(pfd->Entry == NULL)
1398 MESSAGE("\tentry: (null)\n");
1399 else if(pfd->Entry == (void*)-1)
1400 MESSAGE("\tentry: invalid\n");
1401 else if(IS_INTRESOURCE(pfd->Entry))
1402 MESSAGE("\tentry: %p\n", pfd->Entry);
1403 else
1404 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1406 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1408 while (n)
1410 dump_TLBFuncDescOne(pfd);
1411 ++pfd;
1412 --n;
1415 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1417 while (n)
1419 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1420 ++pvd;
1421 --n;
1425 static void dump_TLBImpLib(const TLBImpLib *import)
1427 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1428 debugstr_w(import->name));
1429 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1430 import->wVersionMinor, import->lcid, import->offset);
1433 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1435 TLBRefType *ref;
1437 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1439 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1440 if(ref->index == -1)
1441 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1442 else
1443 TRACE_(typelib)("type no: %d\n", ref->index);
1445 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1447 TRACE_(typelib)("in lib\n");
1448 dump_TLBImpLib(ref->pImpTLInfo);
1453 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1455 if(!impl)
1456 return;
1457 while (n) {
1458 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1459 impl->hRef, impl->implflags);
1460 ++impl;
1461 --n;
1465 static void dump_Variant(const VARIANT * pvar)
1467 SYSTEMTIME st;
1469 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1471 if (pvar)
1473 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1474 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1476 TRACE(",%p", V_BYREF(pvar));
1478 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1480 TRACE(",%p", V_ARRAY(pvar));
1482 else switch (V_TYPE(pvar))
1484 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1485 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1486 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1487 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1488 case VT_INT:
1489 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1490 case VT_UINT:
1491 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1492 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1493 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1494 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1495 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1496 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1497 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1498 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1499 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1500 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1501 V_CY(pvar).s.Lo); break;
1502 case VT_DATE:
1503 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1504 TRACE(",<invalid>");
1505 else
1506 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1507 st.wHour, st.wMinute, st.wSecond);
1508 break;
1509 case VT_ERROR:
1510 case VT_VOID:
1511 case VT_USERDEFINED:
1512 case VT_EMPTY:
1513 case VT_NULL: break;
1514 default: TRACE(",?"); break;
1517 TRACE("}\n");
1520 static void dump_DispParms(const DISPPARAMS * pdp)
1522 unsigned int index;
1524 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1526 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1528 TRACE("named args:\n");
1529 for (index = 0; index < pdp->cNamedArgs; index++)
1530 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1533 if (pdp->cArgs && pdp->rgvarg)
1535 TRACE("args:\n");
1536 for (index = 0; index < pdp->cArgs; index++)
1537 dump_Variant( &pdp->rgvarg[index] );
1541 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1543 TRACE("%p ref=%u\n", pty, pty->ref);
1544 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1545 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1546 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1547 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1548 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1549 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1550 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1551 if (TRACE_ON(ole))
1552 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1553 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1554 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1557 static void dump_VARDESC(const VARDESC *v)
1559 MESSAGE("memid %d\n",v->memid);
1560 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1561 MESSAGE("oInst %d\n",v->u.oInst);
1562 dump_ELEMDESC(&(v->elemdescVar));
1563 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1564 MESSAGE("varkind %d\n",v->varkind);
1567 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1569 /* VT_LPWSTR is largest type that, may appear in type description */
1570 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1571 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1572 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1573 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1574 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1575 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1576 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1577 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1580 static void TLB_abort(void)
1582 DebugBreak();
1585 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1587 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1588 if (!ret) ERR("cannot allocate memory\n");
1589 return ret;
1592 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1594 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1595 if (!ret) ERR("cannot allocate memory\n");
1596 return ret;
1599 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1601 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1604 void heap_free(void *ptr)
1606 HeapFree(GetProcessHeap(), 0, ptr);
1609 /* returns the size required for a deep copy of a typedesc into a
1610 * flat buffer */
1611 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1613 SIZE_T size = 0;
1615 if (alloc_initial_space)
1616 size += sizeof(TYPEDESC);
1618 switch (tdesc->vt)
1620 case VT_PTR:
1621 case VT_SAFEARRAY:
1622 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1623 break;
1624 case VT_CARRAY:
1625 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1626 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1627 break;
1629 return size;
1632 /* deep copy a typedesc into a flat buffer */
1633 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1635 if (!dest)
1637 dest = buffer;
1638 buffer = (char *)buffer + sizeof(TYPEDESC);
1641 *dest = *src;
1643 switch (src->vt)
1645 case VT_PTR:
1646 case VT_SAFEARRAY:
1647 dest->u.lptdesc = buffer;
1648 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1649 break;
1650 case VT_CARRAY:
1651 dest->u.lpadesc = buffer;
1652 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1653 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1654 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1655 break;
1657 return buffer;
1660 /* free custom data allocated by MSFT_CustData */
1661 static inline void TLB_FreeCustData(struct list *custdata_list)
1663 TLBCustData *cd, *cdn;
1664 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1666 list_remove(&cd->entry);
1667 VariantClear(&cd->data);
1668 heap_free(cd);
1672 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1674 DWORD len;
1675 BSTR ret;
1677 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1678 ret = SysAllocStringLen(NULL, len - 1);
1679 if (!ret) return ret;
1680 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1681 return ret;
1684 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1685 UINT n, MEMBERID memid)
1687 while(n){
1688 if(funcdescs->funcdesc.memid == memid)
1689 return funcdescs;
1690 ++funcdescs;
1691 --n;
1693 return NULL;
1696 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1697 UINT n, const OLECHAR *name)
1699 while(n){
1700 if(!lstrcmpiW(TLB_get_bstr(funcdescs->Name), name))
1701 return funcdescs;
1702 ++funcdescs;
1703 --n;
1705 return NULL;
1708 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1709 UINT n, MEMBERID memid)
1711 while(n){
1712 if(vardescs->vardesc.memid == memid)
1713 return vardescs;
1714 ++vardescs;
1715 --n;
1717 return NULL;
1720 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1721 UINT n, const OLECHAR *name)
1723 while(n){
1724 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1725 return vardescs;
1726 ++vardescs;
1727 --n;
1729 return NULL;
1732 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1734 TLBCustData *cust_data;
1735 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1736 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1737 return cust_data;
1738 return NULL;
1741 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1742 UINT n, const OLECHAR *name)
1744 while(n){
1745 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1746 return *typeinfos;
1747 ++typeinfos;
1748 --n;
1750 return NULL;
1753 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1755 list_init(&var_desc->custdata_list);
1758 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1760 TLBVarDesc *ret;
1762 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1763 if(!ret)
1764 return NULL;
1766 while(n){
1767 TLBVarDesc_Constructor(&ret[n-1]);
1768 --n;
1771 return ret;
1774 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1776 TLBParDesc *ret;
1778 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1779 if(!ret)
1780 return NULL;
1782 while(n){
1783 list_init(&ret[n-1].custdata_list);
1784 --n;
1787 return ret;
1790 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1792 list_init(&func_desc->custdata_list);
1795 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1797 TLBFuncDesc *ret;
1799 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1800 if(!ret)
1801 return NULL;
1803 while(n){
1804 TLBFuncDesc_Constructor(&ret[n-1]);
1805 --n;
1808 return ret;
1811 static void TLBImplType_Constructor(TLBImplType *impl)
1813 list_init(&impl->custdata_list);
1816 static TLBImplType *TLBImplType_Alloc(UINT n)
1818 TLBImplType *ret;
1820 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1821 if(!ret)
1822 return NULL;
1824 while(n){
1825 TLBImplType_Constructor(&ret[n-1]);
1826 --n;
1829 return ret;
1832 static TLBGuid *TLB_append_guid(struct list *guid_list,
1833 const GUID *new_guid, HREFTYPE hreftype)
1835 TLBGuid *guid;
1837 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1838 if (IsEqualGUID(&guid->guid, new_guid))
1839 return guid;
1842 guid = heap_alloc(sizeof(TLBGuid));
1843 if (!guid)
1844 return NULL;
1846 memcpy(&guid->guid, new_guid, sizeof(GUID));
1847 guid->hreftype = hreftype;
1849 list_add_tail(guid_list, &guid->entry);
1851 return guid;
1854 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1856 TLBCustData *cust_data;
1858 switch(V_VT(var)){
1859 case VT_I4:
1860 case VT_R4:
1861 case VT_UI4:
1862 case VT_INT:
1863 case VT_UINT:
1864 case VT_HRESULT:
1865 case VT_BSTR:
1866 break;
1867 default:
1868 return DISP_E_BADVARTYPE;
1871 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1873 if (!cust_data) {
1874 cust_data = heap_alloc(sizeof(TLBCustData));
1875 if (!cust_data)
1876 return E_OUTOFMEMORY;
1878 cust_data->guid = tlbguid;
1879 VariantInit(&cust_data->data);
1881 list_add_tail(custdata_list, &cust_data->entry);
1882 }else
1883 VariantClear(&cust_data->data);
1885 return VariantCopy(&cust_data->data, var);
1888 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1890 TLBString *str;
1892 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1893 if (strcmpW(str->str, new_str) == 0)
1894 return str;
1897 str = heap_alloc(sizeof(TLBString));
1898 if (!str)
1899 return NULL;
1901 str->str = SysAllocString(new_str);
1902 if (!str->str) {
1903 heap_free(str);
1904 return NULL;
1907 list_add_tail(string_list, &str->entry);
1909 return str;
1912 /**********************************************************************
1914 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1916 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1918 return pcx->pos;
1921 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1923 if (where != DO_NOT_SEEK)
1925 where += pcx->oStart;
1926 if (where > pcx->length)
1928 /* FIXME */
1929 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1930 TLB_abort();
1932 pcx->pos = where;
1936 /* read function */
1937 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1939 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1940 pcx->pos, count, pcx->oStart, pcx->length, where);
1942 MSFT_Seek(pcx, where);
1943 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1944 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1945 pcx->pos += count;
1946 return count;
1949 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1950 LONG where )
1952 DWORD ret;
1954 ret = MSFT_Read(buffer, count, pcx, where);
1955 FromLEDWords(buffer, ret);
1957 return ret;
1960 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1961 LONG where )
1963 DWORD ret;
1965 ret = MSFT_Read(buffer, count, pcx, where);
1966 FromLEWords(buffer, ret);
1968 return ret;
1971 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
1973 TLBGuid *guid;
1974 MSFT_GuidEntry entry;
1975 int offs = 0;
1977 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
1978 while (1) {
1979 if (offs >= pcx->pTblDir->pGuidTab.length)
1980 return S_OK;
1982 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
1984 guid = heap_alloc(sizeof(TLBGuid));
1986 guid->offset = offs;
1987 guid->guid = entry.guid;
1988 guid->hreftype = entry.hreftype;
1990 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
1992 offs += sizeof(MSFT_GuidEntry);
1996 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
1998 TLBGuid *ret;
2000 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2001 if(ret->offset == offset){
2002 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2003 return ret;
2007 return NULL;
2010 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2012 MSFT_NameIntro niName;
2014 if (offset < 0)
2016 ERR_(typelib)("bad offset %d\n", offset);
2017 return -1;
2020 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2021 pcx->pTblDir->pNametab.offset+offset);
2023 return niName.hreftype;
2026 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2028 char *string;
2029 MSFT_NameIntro intro;
2030 INT16 len_piece;
2031 int offs = 0, lengthInChars;
2033 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2034 while (1) {
2035 TLBString *tlbstr;
2037 if (offs >= pcx->pTblDir->pNametab.length)
2038 return S_OK;
2040 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2041 intro.namelen &= 0xFF;
2042 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2043 if(len_piece % 4)
2044 len_piece = (len_piece + 4) & ~0x3;
2045 if(len_piece < 8)
2046 len_piece = 8;
2048 string = heap_alloc(len_piece + 1);
2049 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2050 string[intro.namelen] = '\0';
2052 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2053 string, -1, NULL, 0);
2054 if (!lengthInChars) {
2055 heap_free(string);
2056 return E_UNEXPECTED;
2059 tlbstr = heap_alloc(sizeof(TLBString));
2061 tlbstr->offset = offs;
2062 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2063 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2065 heap_free(string);
2067 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2069 offs += len_piece;
2073 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2075 TLBString *tlbstr;
2077 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2078 if (tlbstr->offset == offset) {
2079 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2080 return tlbstr;
2084 return NULL;
2087 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2089 TLBString *tlbstr;
2091 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2092 if (tlbstr->offset == offset) {
2093 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2094 return tlbstr;
2098 return NULL;
2102 * read a value and fill a VARIANT structure
2104 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2106 int size;
2108 TRACE_(typelib)("\n");
2110 if(offset <0) { /* data are packed in here */
2111 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2112 V_I4(pVar) = offset & 0x3ffffff;
2113 return;
2115 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2116 pcx->pTblDir->pCustData.offset + offset );
2117 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2118 switch (V_VT(pVar)){
2119 case VT_EMPTY: /* FIXME: is this right? */
2120 case VT_NULL: /* FIXME: is this right? */
2121 case VT_I2 : /* this should not happen */
2122 case VT_I4 :
2123 case VT_R4 :
2124 case VT_ERROR :
2125 case VT_BOOL :
2126 case VT_I1 :
2127 case VT_UI1 :
2128 case VT_UI2 :
2129 case VT_UI4 :
2130 case VT_INT :
2131 case VT_UINT :
2132 case VT_VOID : /* FIXME: is this right? */
2133 case VT_HRESULT :
2134 size=4; break;
2135 case VT_R8 :
2136 case VT_CY :
2137 case VT_DATE :
2138 case VT_I8 :
2139 case VT_UI8 :
2140 case VT_DECIMAL : /* FIXME: is this right? */
2141 case VT_FILETIME :
2142 size=8;break;
2143 /* pointer types with known behaviour */
2144 case VT_BSTR :{
2145 char * ptr;
2146 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2147 if(size < 0) {
2148 char next;
2149 DWORD origPos = MSFT_Tell(pcx), nullPos;
2151 do {
2152 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
2153 } while (next);
2154 nullPos = MSFT_Tell(pcx);
2155 size = nullPos - origPos;
2156 MSFT_Seek(pcx, origPos);
2158 ptr = heap_alloc_zero(size);/* allocate temp buffer */
2159 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
2160 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2161 /* FIXME: do we need a AtoW conversion here? */
2162 V_UNION(pVar, bstrVal[size])='\0';
2163 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2164 heap_free(ptr);
2166 size=-4; break;
2167 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2168 case VT_DISPATCH :
2169 case VT_VARIANT :
2170 case VT_UNKNOWN :
2171 case VT_PTR :
2172 case VT_SAFEARRAY :
2173 case VT_CARRAY :
2174 case VT_USERDEFINED :
2175 case VT_LPSTR :
2176 case VT_LPWSTR :
2177 case VT_BLOB :
2178 case VT_STREAM :
2179 case VT_STORAGE :
2180 case VT_STREAMED_OBJECT :
2181 case VT_STORED_OBJECT :
2182 case VT_BLOB_OBJECT :
2183 case VT_CF :
2184 case VT_CLSID :
2185 default:
2186 size=0;
2187 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2188 V_VT(pVar));
2191 if(size>0) /* (big|small) endian correct? */
2192 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2193 return;
2196 * create a linked list with custom data
2198 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2200 MSFT_CDGuid entry;
2201 TLBCustData* pNew;
2202 int count=0;
2204 TRACE_(typelib)("\n");
2206 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2208 while(offset >=0){
2209 count++;
2210 pNew=heap_alloc_zero(sizeof(TLBCustData));
2211 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2212 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2213 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2214 list_add_head(custdata_list, &pNew->entry);
2215 offset = entry.next;
2217 return count;
2220 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
2221 ITypeInfoImpl *pTI)
2223 if(type <0)
2224 pTd->vt=type & VT_TYPEMASK;
2225 else
2226 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2228 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2231 static int TLB_is_propgetput(INVOKEKIND invkind)
2233 return (invkind == INVOKE_PROPERTYGET ||
2234 invkind == INVOKE_PROPERTYPUT ||
2235 invkind == INVOKE_PROPERTYPUTREF);
2238 static void
2239 MSFT_DoFuncs(TLBContext* pcx,
2240 ITypeInfoImpl* pTI,
2241 int cFuncs,
2242 int cVars,
2243 int offset,
2244 TLBFuncDesc** pptfd)
2247 * member information is stored in a data structure at offset
2248 * indicated by the memoffset field of the typeinfo structure
2249 * There are several distinctive parts.
2250 * The first part starts with a field that holds the total length
2251 * of this (first) part excluding this field. Then follow the records,
2252 * for each member there is one record.
2254 * The first entry is always the length of the record (including this
2255 * length word).
2256 * The rest of the record depends on the type of the member. If there is
2257 * a field indicating the member type (function, variable, interface, etc)
2258 * I have not found it yet. At this time we depend on the information
2259 * in the type info and the usual order how things are stored.
2261 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2262 * for each member;
2264 * Third is an equal sized array with file offsets to the name entry
2265 * of each member.
2267 * The fourth and last (?) part is an array with offsets to the records
2268 * in the first part of this file segment.
2271 int infolen, nameoffset, reclength, i;
2272 int recoffset = offset + sizeof(INT);
2274 char *recbuf = heap_alloc(0xffff);
2275 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2276 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2278 TRACE_(typelib)("\n");
2280 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2282 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2283 ptfd = *pptfd;
2284 for ( i = 0; i < cFuncs ; i++ )
2286 int optional;
2288 /* name, eventually add to a hash table */
2289 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2290 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2292 /* read the function information record */
2293 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2295 reclength &= 0xffff;
2297 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2299 /* size without argument data */
2300 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2301 if (pFuncRec->FKCCIC & 0x1000)
2302 optional -= pFuncRec->nrargs * sizeof(INT);
2304 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2305 ptfd->helpcontext = pFuncRec->HelpContext;
2307 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2308 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2310 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2312 if (pFuncRec->FKCCIC & 0x2000 )
2314 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2315 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2316 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2318 else
2319 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2321 else
2322 ptfd->Entry = (TLBString*)-1;
2324 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2325 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2327 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2328 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2330 /* fill the FuncDesc Structure */
2331 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2332 offset + infolen + ( i + 1) * sizeof(INT));
2334 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2335 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2336 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2337 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2338 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2339 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2340 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2342 /* nameoffset is sometimes -1 on the second half of a propget/propput
2343 * pair of functions */
2344 if ((nameoffset == -1) && (i > 0) &&
2345 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2346 TLB_is_propgetput(ptfd->funcdesc.invkind))
2347 ptfd->Name = ptfd_prev->Name;
2348 else
2349 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2351 MSFT_GetTdesc(pcx,
2352 pFuncRec->DataType,
2353 &ptfd->funcdesc.elemdescFunc.tdesc,
2354 pTI);
2356 /* do the parameters/arguments */
2357 if(pFuncRec->nrargs)
2359 int j = 0;
2360 MSFT_ParameterInfo paraminfo;
2362 ptfd->funcdesc.lprgelemdescParam =
2363 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2365 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2367 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2368 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2370 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2372 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2374 MSFT_GetTdesc(pcx,
2375 paraminfo.DataType,
2376 &elemdesc->tdesc,
2377 pTI);
2379 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2381 /* name */
2382 if (paraminfo.oName != -1)
2383 ptfd->pParamDesc[j].Name =
2384 MSFT_ReadName( pcx, paraminfo.oName );
2385 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2387 /* default value */
2388 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2389 (pFuncRec->FKCCIC & 0x1000) )
2391 INT* pInt = (INT *)((char *)pFuncRec +
2392 reclength -
2393 (pFuncRec->nrargs * 4) * sizeof(INT) );
2395 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2397 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2398 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2400 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2401 pInt[j], pcx);
2403 else
2404 elemdesc->u.paramdesc.pparamdescex = NULL;
2406 /* custom info */
2407 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2408 j*sizeof(pFuncRec->oArgCustData[0])) &&
2409 pFuncRec->FKCCIC & 0x80 )
2411 MSFT_CustData(pcx,
2412 pFuncRec->oArgCustData[j],
2413 &ptfd->pParamDesc[j].custdata_list);
2416 /* SEEK value = jump to offset,
2417 * from there jump to the end of record,
2418 * go back by (j-1) arguments
2420 MSFT_ReadLEDWords( &paraminfo ,
2421 sizeof(MSFT_ParameterInfo), pcx,
2422 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2423 * sizeof(MSFT_ParameterInfo)));
2427 /* scode is not used: archaic win16 stuff FIXME: right? */
2428 ptfd->funcdesc.cScodes = 0 ;
2429 ptfd->funcdesc.lprgscode = NULL ;
2431 ptfd_prev = ptfd;
2432 ++ptfd;
2433 recoffset += reclength;
2435 heap_free(recbuf);
2438 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2439 int cVars, int offset, TLBVarDesc ** pptvd)
2441 int infolen, nameoffset, reclength;
2442 char recbuf[256];
2443 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2444 TLBVarDesc *ptvd;
2445 int i;
2446 int recoffset;
2448 TRACE_(typelib)("\n");
2450 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2451 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2452 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2453 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2454 recoffset += offset+sizeof(INT);
2455 for(i=0;i<cVars;i++, ++ptvd){
2456 /* name, eventually add to a hash table */
2457 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2458 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2459 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2460 /* read the variable information record */
2461 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2462 reclength &= 0xff;
2463 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2465 /* optional data */
2466 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2467 ptvd->HelpContext = pVarRec->HelpContext;
2469 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2470 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2472 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2473 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2475 /* fill the VarDesc Structure */
2476 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2477 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2478 ptvd->vardesc.varkind = pVarRec->VarKind;
2479 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2480 MSFT_GetTdesc(pcx, pVarRec->DataType,
2481 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2482 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2483 if(pVarRec->VarKind == VAR_CONST ){
2484 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2485 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2486 pVarRec->OffsValue, pcx);
2487 } else
2488 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2489 recoffset += reclength;
2493 /* process Implemented Interfaces of a com class */
2494 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2495 int offset)
2497 int i;
2498 MSFT_RefRecord refrec;
2499 TLBImplType *pImpl;
2501 TRACE_(typelib)("\n");
2503 pTI->impltypes = TLBImplType_Alloc(count);
2504 pImpl = pTI->impltypes;
2505 for(i=0;i<count;i++){
2506 if(offset<0) break; /* paranoia */
2507 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2508 pImpl->hRef = refrec.reftype;
2509 pImpl->implflags=refrec.flags;
2510 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2511 offset=refrec.onext;
2512 ++pImpl;
2516 * process a typeinfo record
2518 static ITypeInfoImpl * MSFT_DoTypeInfo(
2519 TLBContext *pcx,
2520 int count,
2521 ITypeLibImpl * pLibInfo)
2523 MSFT_TypeInfoBase tiBase;
2524 ITypeInfoImpl *ptiRet;
2526 TRACE_(typelib)("count=%u\n", count);
2528 ptiRet = ITypeInfoImpl_Constructor();
2529 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2530 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2532 /* this is where we are coming from */
2533 ptiRet->pTypeLib = pLibInfo;
2534 ptiRet->index=count;
2536 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2537 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2538 ptiRet->lpstrSchema=NULL; /* reserved */
2539 ptiRet->cbSizeInstance=tiBase.size;
2540 #ifdef _WIN64
2541 if(pLibInfo->syskind == SYS_WIN32)
2542 ptiRet->cbSizeInstance=sizeof(void*);
2543 #endif
2544 ptiRet->typekind=tiBase.typekind & 0xF;
2545 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2546 ptiRet->cVars=HIWORD(tiBase.cElement);
2547 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2548 #ifdef _WIN64
2549 if(pLibInfo->syskind == SYS_WIN32)
2550 ptiRet->cbAlignment = 8;
2551 #endif
2552 ptiRet->wTypeFlags=tiBase.flags;
2553 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2554 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2555 ptiRet->cImplTypes=tiBase.cImplTypes;
2556 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2557 if(ptiRet->typekind == TKIND_ALIAS)
2558 MSFT_GetTdesc(pcx, tiBase.datatype1,
2559 &ptiRet->tdescAlias, ptiRet);
2561 /* FIXME: */
2562 /* IDLDESC idldescType; *//* never saw this one != zero */
2564 /* name, eventually add to a hash table */
2565 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2566 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2567 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2568 /* help info */
2569 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2570 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2571 ptiRet->dwHelpContext=tiBase.helpcontext;
2573 if (ptiRet->typekind == TKIND_MODULE)
2574 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2576 /* note: InfoType's Help file and HelpStringDll come from the containing
2577 * library. Further HelpString and Docstring appear to be the same thing :(
2579 /* functions */
2580 if(ptiRet->cFuncs >0 )
2581 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2582 ptiRet->cVars,
2583 tiBase.memoffset, &ptiRet->funcdescs);
2584 /* variables */
2585 if(ptiRet->cVars >0 )
2586 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2587 ptiRet->cVars,
2588 tiBase.memoffset, &ptiRet->vardescs);
2589 if(ptiRet->cImplTypes >0 ) {
2590 switch(ptiRet->typekind)
2592 case TKIND_COCLASS:
2593 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2594 tiBase.datatype1);
2595 break;
2596 case TKIND_DISPATCH:
2597 /* This is not -1 when the interface is a non-base dual interface or
2598 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2599 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2600 not this interface.
2603 if (tiBase.datatype1 != -1)
2605 ptiRet->impltypes = TLBImplType_Alloc(1);
2606 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2608 break;
2609 default:
2610 ptiRet->impltypes = TLBImplType_Alloc(1);
2611 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2612 break;
2615 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2617 TRACE_(typelib)("%s guid: %s kind:%s\n",
2618 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2619 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2620 typekind_desc[ptiRet->typekind]);
2621 if (TRACE_ON(typelib))
2622 dump_TypeInfo(ptiRet);
2624 return ptiRet;
2627 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2629 char *string;
2630 INT16 len_str, len_piece;
2631 int offs = 0, lengthInChars;
2633 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2634 while (1) {
2635 TLBString *tlbstr;
2637 if (offs >= pcx->pTblDir->pStringtab.length)
2638 return S_OK;
2640 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2641 len_piece = len_str + sizeof(INT16);
2642 if(len_piece % 4)
2643 len_piece = (len_piece + 4) & ~0x3;
2644 if(len_piece < 8)
2645 len_piece = 8;
2647 string = heap_alloc(len_piece + 1);
2648 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2649 string[len_str] = '\0';
2651 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2652 string, -1, NULL, 0);
2653 if (!lengthInChars) {
2654 heap_free(string);
2655 return E_UNEXPECTED;
2658 tlbstr = heap_alloc(sizeof(TLBString));
2660 tlbstr->offset = offs;
2661 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2662 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2664 heap_free(string);
2666 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2668 offs += len_piece;
2672 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2674 TLBRefType *ref;
2675 int offs = 0;
2677 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2678 while (offs < pcx->pTblDir->pImpInfo.length) {
2679 MSFT_ImpInfo impinfo;
2680 TLBImpLib *pImpLib;
2682 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2684 ref = heap_alloc_zero(sizeof(TLBRefType));
2685 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2687 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2688 if(pImpLib->offset==impinfo.oImpFile)
2689 break;
2691 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2692 ref->reference = offs;
2693 ref->pImpTLInfo = pImpLib;
2694 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2695 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2696 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2697 ref->index = TLB_REF_USE_GUID;
2698 } else
2699 ref->index = impinfo.oGuid;
2700 }else{
2701 ERR("Cannot find a reference\n");
2702 ref->reference = -1;
2703 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2706 offs += sizeof(impinfo);
2709 return S_OK;
2712 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2713 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2714 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2715 * tradeoff here.
2717 static struct list tlb_cache = LIST_INIT(tlb_cache);
2718 static CRITICAL_SECTION cache_section;
2719 static CRITICAL_SECTION_DEBUG cache_section_debug =
2721 0, 0, &cache_section,
2722 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2723 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2725 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2728 typedef struct TLB_PEFile
2730 IUnknown IUnknown_iface;
2731 LONG refs;
2732 HMODULE dll;
2733 HRSRC typelib_resource;
2734 HGLOBAL typelib_global;
2735 LPVOID typelib_base;
2736 } TLB_PEFile;
2738 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2740 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2743 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2745 if (IsEqualIID(riid, &IID_IUnknown))
2747 *ppv = iface;
2748 IUnknown_AddRef(iface);
2749 return S_OK;
2751 *ppv = NULL;
2752 return E_NOINTERFACE;
2755 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2757 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2758 return InterlockedIncrement(&This->refs);
2761 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2763 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2764 ULONG refs = InterlockedDecrement(&This->refs);
2765 if (!refs)
2767 if (This->typelib_global)
2768 FreeResource(This->typelib_global);
2769 if (This->dll)
2770 FreeLibrary(This->dll);
2771 heap_free(This);
2773 return refs;
2776 static const IUnknownVtbl TLB_PEFile_Vtable =
2778 TLB_PEFile_QueryInterface,
2779 TLB_PEFile_AddRef,
2780 TLB_PEFile_Release
2783 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2785 TLB_PEFile *This;
2786 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2788 This = heap_alloc(sizeof(TLB_PEFile));
2789 if (!This)
2790 return E_OUTOFMEMORY;
2792 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2793 This->refs = 1;
2794 This->dll = NULL;
2795 This->typelib_resource = NULL;
2796 This->typelib_global = NULL;
2797 This->typelib_base = NULL;
2799 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2800 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2802 if (This->dll)
2804 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2805 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2806 if (This->typelib_resource)
2808 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2809 if (This->typelib_global)
2811 This->typelib_base = LockResource(This->typelib_global);
2813 if (This->typelib_base)
2815 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2816 *ppBase = This->typelib_base;
2817 *ppFile = &This->IUnknown_iface;
2818 return S_OK;
2823 TRACE("No TYPELIB resource found\n");
2824 hr = E_FAIL;
2827 TLB_PEFile_Release(&This->IUnknown_iface);
2828 return hr;
2831 typedef struct TLB_NEFile
2833 IUnknown IUnknown_iface;
2834 LONG refs;
2835 LPVOID typelib_base;
2836 } TLB_NEFile;
2838 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2840 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2843 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2845 if (IsEqualIID(riid, &IID_IUnknown))
2847 *ppv = iface;
2848 IUnknown_AddRef(iface);
2849 return S_OK;
2851 *ppv = NULL;
2852 return E_NOINTERFACE;
2855 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2857 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2858 return InterlockedIncrement(&This->refs);
2861 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2863 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2864 ULONG refs = InterlockedDecrement(&This->refs);
2865 if (!refs)
2867 heap_free(This->typelib_base);
2868 heap_free(This);
2870 return refs;
2873 static const IUnknownVtbl TLB_NEFile_Vtable =
2875 TLB_NEFile_QueryInterface,
2876 TLB_NEFile_AddRef,
2877 TLB_NEFile_Release
2880 /***********************************************************************
2881 * read_xx_header [internal]
2883 static int read_xx_header( HFILE lzfd )
2885 IMAGE_DOS_HEADER mzh;
2886 char magic[3];
2888 LZSeek( lzfd, 0, SEEK_SET );
2889 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2890 return 0;
2891 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2892 return 0;
2894 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2895 if ( 2 != LZRead( lzfd, magic, 2 ) )
2896 return 0;
2898 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2900 if ( magic[0] == 'N' && magic[1] == 'E' )
2901 return IMAGE_OS2_SIGNATURE;
2902 if ( magic[0] == 'P' && magic[1] == 'E' )
2903 return IMAGE_NT_SIGNATURE;
2905 magic[2] = '\0';
2906 WARN("Can't handle %s files.\n", magic );
2907 return 0;
2911 /***********************************************************************
2912 * find_ne_resource [internal]
2914 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2915 DWORD *resLen, DWORD *resOff )
2917 IMAGE_OS2_HEADER nehd;
2918 NE_TYPEINFO *typeInfo;
2919 NE_NAMEINFO *nameInfo;
2920 DWORD nehdoffset;
2921 LPBYTE resTab;
2922 DWORD resTabSize;
2923 int count;
2925 /* Read in NE header */
2926 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2927 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2929 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2930 if ( !resTabSize )
2932 TRACE("No resources in NE dll\n" );
2933 return FALSE;
2936 /* Read in resource table */
2937 resTab = heap_alloc( resTabSize );
2938 if ( !resTab ) return FALSE;
2940 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2941 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2943 heap_free( resTab );
2944 return FALSE;
2947 /* Find resource */
2948 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2950 if (!IS_INTRESOURCE(typeid)) /* named type */
2952 BYTE len = strlen( typeid );
2953 while (typeInfo->type_id)
2955 if (!(typeInfo->type_id & 0x8000))
2957 BYTE *p = resTab + typeInfo->type_id;
2958 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2960 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2961 typeInfo->count * sizeof(NE_NAMEINFO));
2964 else /* numeric type id */
2966 WORD id = LOWORD(typeid) | 0x8000;
2967 while (typeInfo->type_id)
2969 if (typeInfo->type_id == id) goto found_type;
2970 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2971 typeInfo->count * sizeof(NE_NAMEINFO));
2974 TRACE("No typeid entry found for %p\n", typeid );
2975 heap_free( resTab );
2976 return FALSE;
2978 found_type:
2979 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2981 if (!IS_INTRESOURCE(resid)) /* named resource */
2983 BYTE len = strlen( resid );
2984 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2986 BYTE *p = resTab + nameInfo->id;
2987 if (nameInfo->id & 0x8000) continue;
2988 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2991 else /* numeric resource id */
2993 WORD id = LOWORD(resid) | 0x8000;
2994 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2995 if (nameInfo->id == id) goto found_name;
2997 TRACE("No resid entry found for %p\n", typeid );
2998 heap_free( resTab );
2999 return FALSE;
3001 found_name:
3002 /* Return resource data */
3003 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3004 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3006 heap_free( resTab );
3007 return TRUE;
3010 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3012 HFILE lzfd = -1;
3013 OFSTRUCT ofs;
3014 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3015 TLB_NEFile *This;
3017 This = heap_alloc(sizeof(TLB_NEFile));
3018 if (!This) return E_OUTOFMEMORY;
3020 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3021 This->refs = 1;
3022 This->typelib_base = NULL;
3024 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3025 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3027 DWORD reslen, offset;
3028 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3030 This->typelib_base = heap_alloc(reslen);
3031 if( !This->typelib_base )
3032 hr = E_OUTOFMEMORY;
3033 else
3035 LZSeek( lzfd, offset, SEEK_SET );
3036 reslen = LZRead( lzfd, This->typelib_base, reslen );
3037 LZClose( lzfd );
3038 *ppBase = This->typelib_base;
3039 *pdwTLBLength = reslen;
3040 *ppFile = &This->IUnknown_iface;
3041 return S_OK;
3046 if( lzfd >= 0) LZClose( lzfd );
3047 TLB_NEFile_Release(&This->IUnknown_iface);
3048 return hr;
3051 typedef struct TLB_Mapping
3053 IUnknown IUnknown_iface;
3054 LONG refs;
3055 HANDLE file;
3056 HANDLE mapping;
3057 LPVOID typelib_base;
3058 } TLB_Mapping;
3060 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3062 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3065 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3067 if (IsEqualIID(riid, &IID_IUnknown))
3069 *ppv = iface;
3070 IUnknown_AddRef(iface);
3071 return S_OK;
3073 *ppv = NULL;
3074 return E_NOINTERFACE;
3077 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3079 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3080 return InterlockedIncrement(&This->refs);
3083 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3085 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3086 ULONG refs = InterlockedDecrement(&This->refs);
3087 if (!refs)
3089 if (This->typelib_base)
3090 UnmapViewOfFile(This->typelib_base);
3091 if (This->mapping)
3092 CloseHandle(This->mapping);
3093 if (This->file != INVALID_HANDLE_VALUE)
3094 CloseHandle(This->file);
3095 heap_free(This);
3097 return refs;
3100 static const IUnknownVtbl TLB_Mapping_Vtable =
3102 TLB_Mapping_QueryInterface,
3103 TLB_Mapping_AddRef,
3104 TLB_Mapping_Release
3107 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3109 TLB_Mapping *This;
3111 This = heap_alloc(sizeof(TLB_Mapping));
3112 if (!This)
3113 return E_OUTOFMEMORY;
3115 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3116 This->refs = 1;
3117 This->file = INVALID_HANDLE_VALUE;
3118 This->mapping = NULL;
3119 This->typelib_base = NULL;
3121 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3122 if (INVALID_HANDLE_VALUE != This->file)
3124 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3125 if (This->mapping)
3127 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3128 if(This->typelib_base)
3130 /* retrieve file size */
3131 *pdwTLBLength = GetFileSize(This->file, NULL);
3132 *ppBase = This->typelib_base;
3133 *ppFile = &This->IUnknown_iface;
3134 return S_OK;
3139 IUnknown_Release(&This->IUnknown_iface);
3140 return TYPE_E_CANTLOADLIBRARY;
3143 /****************************************************************************
3144 * TLB_ReadTypeLib
3146 * find the type of the typelib file and map the typelib resource into
3147 * the memory
3150 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3151 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3153 ITypeLibImpl *entry;
3154 HRESULT ret;
3155 INT index = 1;
3156 LPWSTR index_str, file = (LPWSTR)pszFileName;
3157 LPVOID pBase = NULL;
3158 DWORD dwTLBLength = 0;
3159 IUnknown *pFile = NULL;
3160 HANDLE h;
3162 *ppTypeLib = NULL;
3164 index_str = strrchrW(pszFileName, '\\');
3165 if(index_str && *++index_str != '\0')
3167 LPWSTR end_ptr;
3168 LONG idx = strtolW(index_str, &end_ptr, 10);
3169 if(*end_ptr == '\0')
3171 int str_len = index_str - pszFileName - 1;
3172 index = idx;
3173 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3174 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3175 file[str_len] = 0;
3179 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3181 if(strchrW(file, '\\'))
3183 lstrcpyW(pszPath, file);
3185 else
3187 int len = GetSystemDirectoryW(pszPath, cchPath);
3188 pszPath[len] = '\\';
3189 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3193 if(file != pszFileName) heap_free(file);
3195 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_ALWAYS,
3196 FILE_ATTRIBUTE_NORMAL, NULL);
3197 if(h != INVALID_HANDLE_VALUE){
3198 FILE_NAME_INFORMATION *info;
3199 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3200 BOOL br;
3202 info = (FILE_NAME_INFORMATION*)data;
3203 /* GetFileInformationByHandleEx returns the path of the file without
3204 * WOW64 redirection */
3205 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3206 if(br){
3207 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3208 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3210 CloseHandle(h);
3213 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3215 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3216 EnterCriticalSection(&cache_section);
3217 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3219 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3221 TRACE("cache hit\n");
3222 *ppTypeLib = &entry->ITypeLib2_iface;
3223 ITypeLib2_AddRef(*ppTypeLib);
3224 LeaveCriticalSection(&cache_section);
3225 return S_OK;
3228 LeaveCriticalSection(&cache_section);
3230 /* now actually load and parse the typelib */
3232 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3233 if (ret == TYPE_E_CANTLOADLIBRARY)
3234 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3235 if (ret == TYPE_E_CANTLOADLIBRARY)
3236 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3237 if (SUCCEEDED(ret))
3239 if (dwTLBLength >= 4)
3241 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3242 if (dwSignature == MSFT_SIGNATURE)
3243 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3244 else if (dwSignature == SLTG_SIGNATURE)
3245 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3246 else
3248 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3249 ret = TYPE_E_CANTLOADLIBRARY;
3252 else
3253 ret = TYPE_E_CANTLOADLIBRARY;
3254 IUnknown_Release(pFile);
3257 if(*ppTypeLib) {
3258 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3260 TRACE("adding to cache\n");
3261 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3262 lstrcpyW(impl->path, pszPath);
3263 /* We should really canonicalise the path here. */
3264 impl->index = index;
3266 /* FIXME: check if it has added already in the meantime */
3267 EnterCriticalSection(&cache_section);
3268 list_add_head(&tlb_cache, &impl->entry);
3269 LeaveCriticalSection(&cache_section);
3270 ret = S_OK;
3272 else
3274 if(ret != E_FAIL)
3275 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3277 ret = TYPE_E_CANTLOADLIBRARY;
3281 return ret;
3284 /*================== ITypeLib(2) Methods ===================================*/
3286 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3288 ITypeLibImpl* pTypeLibImpl;
3290 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3291 if (!pTypeLibImpl) return NULL;
3293 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3294 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3295 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3296 pTypeLibImpl->ref = 1;
3298 list_init(&pTypeLibImpl->implib_list);
3299 list_init(&pTypeLibImpl->custdata_list);
3300 list_init(&pTypeLibImpl->name_list);
3301 list_init(&pTypeLibImpl->string_list);
3302 list_init(&pTypeLibImpl->guid_list);
3303 list_init(&pTypeLibImpl->ref_list);
3304 pTypeLibImpl->dispatch_href = -1;
3306 return pTypeLibImpl;
3309 /****************************************************************************
3310 * ITypeLib2_Constructor_MSFT
3312 * loading an MSFT typelib from an in-memory image
3314 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3316 TLBContext cx;
3317 LONG lPSegDir;
3318 MSFT_Header tlbHeader;
3319 MSFT_SegDir tlbSegDir;
3320 ITypeLibImpl * pTypeLibImpl;
3322 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3324 pTypeLibImpl = TypeLibImpl_Constructor();
3325 if (!pTypeLibImpl) return NULL;
3327 /* get pointer to beginning of typelib data */
3328 cx.pos = 0;
3329 cx.oStart=0;
3330 cx.mapping = pLib;
3331 cx.pLibInfo = pTypeLibImpl;
3332 cx.length = dwTLBLength;
3334 /* read header */
3335 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3336 TRACE_(typelib)("header:\n");
3337 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3338 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3339 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3340 return NULL;
3342 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3344 /* there is a small amount of information here until the next important
3345 * part:
3346 * the segment directory . Try to calculate the amount of data */
3347 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3349 /* now read the segment directory */
3350 TRACE("read segment directory (at %d)\n",lPSegDir);
3351 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3352 cx.pTblDir = &tlbSegDir;
3354 /* just check two entries */
3355 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3357 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3358 heap_free(pTypeLibImpl);
3359 return NULL;
3362 MSFT_ReadAllNames(&cx);
3363 MSFT_ReadAllStrings(&cx);
3364 MSFT_ReadAllGuids(&cx);
3366 /* now fill our internal data */
3367 /* TLIBATTR fields */
3368 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3370 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3371 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3372 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3373 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3374 pTypeLibImpl->libflags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3376 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3377 pTypeLibImpl->lcid = tlbHeader.lcid;
3379 /* name, eventually add to a hash table */
3380 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3382 /* help info */
3383 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3384 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3386 if( tlbHeader.varflags & HELPDLLFLAG)
3388 int offset;
3389 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3390 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3393 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3395 /* custom data */
3396 if(tlbHeader.CustomDataOffset >= 0)
3398 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3401 /* fill in type descriptions */
3402 if(tlbSegDir.pTypdescTab.length > 0)
3404 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3405 INT16 td[4];
3406 pTypeLibImpl->ctTypeDesc = cTD;
3407 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3408 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3409 for(i=0; i<cTD; )
3411 /* FIXME: add several sanity checks here */
3412 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3413 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3415 /* FIXME: check safearray */
3416 if(td[3] < 0)
3417 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3418 else
3419 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3421 else if(td[0] == VT_CARRAY)
3423 /* array descr table here */
3424 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3426 else if(td[0] == VT_USERDEFINED)
3428 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3430 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3433 /* second time around to fill the array subscript info */
3434 for(i=0;i<cTD;i++)
3436 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3437 if(tlbSegDir.pArrayDescriptions.offset>0)
3439 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3440 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3442 if(td[1]<0)
3443 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3444 else
3445 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3447 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3449 for(j = 0; j<td[2]; j++)
3451 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3452 sizeof(INT), &cx, DO_NOT_SEEK);
3453 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3454 sizeof(INT), &cx, DO_NOT_SEEK);
3457 else
3459 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3460 ERR("didn't find array description data\n");
3465 /* imported type libs */
3466 if(tlbSegDir.pImpFiles.offset>0)
3468 TLBImpLib *pImpLib;
3469 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3470 UINT16 size;
3472 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3474 char *name;
3476 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3477 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3478 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3480 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3481 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3482 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3483 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3485 size >>= 2;
3486 name = heap_alloc_zero(size+1);
3487 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3488 pImpLib->name = TLB_MultiByteToBSTR(name);
3489 heap_free(name);
3491 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3492 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3494 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3498 MSFT_ReadAllRefs(&cx);
3500 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3502 /* type infos */
3503 if(tlbHeader.nrtypeinfos >= 0 )
3505 ITypeInfoImpl **ppTI;
3506 int i;
3508 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3510 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3512 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3514 ++ppTI;
3515 (pTypeLibImpl->TypeInfoCount)++;
3519 TRACE("(%p)\n", pTypeLibImpl);
3520 return &pTypeLibImpl->ITypeLib2_iface;
3524 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3526 char b[3];
3527 int i;
3528 short s;
3530 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3531 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3532 return FALSE;
3535 guid->Data4[0] = s >> 8;
3536 guid->Data4[1] = s & 0xff;
3538 b[2] = '\0';
3539 for(i = 0; i < 6; i++) {
3540 memcpy(b, str + 24 + 2 * i, 2);
3541 guid->Data4[i + 2] = strtol(b, NULL, 16);
3543 return TRUE;
3546 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3548 WORD bytelen;
3549 DWORD len;
3550 BSTR tmp_str;
3552 *pStr = NULL;
3553 bytelen = *(const WORD*)ptr;
3554 if(bytelen == 0xffff) return 2;
3556 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3557 tmp_str = SysAllocStringLen(NULL, len);
3558 if (tmp_str) {
3559 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3560 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3561 SysFreeString(tmp_str);
3563 return bytelen + 2;
3566 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3568 WORD bytelen;
3570 *str = NULL;
3571 bytelen = *(const WORD*)ptr;
3572 if(bytelen == 0xffff) return 2;
3573 *str = heap_alloc(bytelen + 1);
3574 memcpy(*str, ptr + 2, bytelen);
3575 (*str)[bytelen] = '\0';
3576 return bytelen + 2;
3579 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3581 BSTR tmp_str;
3582 TLBString *tlbstr;
3584 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3585 if (tlbstr->offset == offset)
3586 return tlbstr;
3589 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3590 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3591 SysFreeString(tmp_str);
3593 return tlbstr;
3596 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3598 char *ptr = pLibBlk;
3599 WORD w;
3601 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3602 FIXME("libblk magic = %04x\n", w);
3603 return 0;
3606 ptr += 6;
3607 if((w = *(WORD*)ptr) != 0xffff) {
3608 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3609 ptr += w;
3611 ptr += 2;
3613 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3615 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3617 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3618 ptr += 4;
3620 pTypeLibImpl->syskind = *(WORD*)ptr;
3621 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3622 ptr += 2;
3624 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3625 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3626 else
3627 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3628 ptr += 2;
3630 ptr += 4; /* skip res12 */
3632 pTypeLibImpl->libflags = *(WORD*)ptr;
3633 ptr += 2;
3635 pTypeLibImpl->ver_major = *(WORD*)ptr;
3636 ptr += 2;
3638 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3639 ptr += 2;
3641 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3642 ptr += sizeof(GUID);
3644 return ptr - (char*)pLibBlk;
3647 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3648 typedef struct
3650 unsigned int num;
3651 HREFTYPE refs[1];
3652 } sltg_ref_lookup_t;
3654 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3655 HREFTYPE *typelib_ref)
3657 if(table && typeinfo_ref < table->num)
3659 *typelib_ref = table->refs[typeinfo_ref];
3660 return S_OK;
3663 ERR_(typelib)("Unable to find reference\n");
3664 *typelib_ref = -1;
3665 return E_FAIL;
3668 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3670 BOOL done = FALSE;
3672 while(!done) {
3673 if((*pType & 0xe00) == 0xe00) {
3674 pTD->vt = VT_PTR;
3675 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3676 pTD = pTD->u.lptdesc;
3678 switch(*pType & 0x3f) {
3679 case VT_PTR:
3680 pTD->vt = VT_PTR;
3681 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3682 pTD = pTD->u.lptdesc;
3683 break;
3685 case VT_USERDEFINED:
3686 pTD->vt = VT_USERDEFINED;
3687 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3688 done = TRUE;
3689 break;
3691 case VT_CARRAY:
3693 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3694 array */
3696 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3698 pTD->vt = VT_CARRAY;
3699 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3700 pTD->u.lpadesc->cDims = pSA->cDims;
3701 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3702 pSA->cDims * sizeof(SAFEARRAYBOUND));
3704 pTD = &pTD->u.lpadesc->tdescElem;
3705 break;
3708 case VT_SAFEARRAY:
3710 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3711 useful? */
3713 pType++;
3714 pTD->vt = VT_SAFEARRAY;
3715 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3716 pTD = pTD->u.lptdesc;
3717 break;
3719 default:
3720 pTD->vt = *pType & 0x3f;
3721 done = TRUE;
3722 break;
3724 pType++;
3726 return pType;
3729 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3730 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3732 /* Handle [in/out] first */
3733 if((*pType & 0xc000) == 0xc000)
3734 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3735 else if(*pType & 0x8000)
3736 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3737 else if(*pType & 0x4000)
3738 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3739 else
3740 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3742 if(*pType & 0x2000)
3743 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3745 if(*pType & 0x80)
3746 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3748 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3752 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3753 char *pNameTable)
3755 unsigned int ref;
3756 char *name;
3757 TLBRefType *ref_type;
3758 sltg_ref_lookup_t *table;
3759 HREFTYPE typelib_ref;
3761 if(pRef->magic != SLTG_REF_MAGIC) {
3762 FIXME("Ref magic = %x\n", pRef->magic);
3763 return NULL;
3765 name = ( (char*)pRef->names + pRef->number);
3767 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3768 table->num = pRef->number >> 3;
3770 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3772 /* We don't want the first href to be 0 */
3773 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3775 for(ref = 0; ref < pRef->number >> 3; ref++) {
3776 char *refname;
3777 unsigned int lib_offs, type_num;
3779 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3781 name += SLTG_ReadStringA(name, &refname);
3782 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3783 FIXME_(typelib)("Can't sscanf ref\n");
3784 if(lib_offs != 0xffff) {
3785 TLBImpLib *import;
3787 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3788 if(import->offset == lib_offs)
3789 break;
3791 if(&import->entry == &pTL->implib_list) {
3792 char fname[MAX_PATH+1];
3793 int len;
3794 GUID tmpguid;
3796 import = heap_alloc_zero(sizeof(*import));
3797 import->offset = lib_offs;
3798 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3799 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3800 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3801 &import->wVersionMajor,
3802 &import->wVersionMinor,
3803 &import->lcid, fname) != 4) {
3804 FIXME_(typelib)("can't sscanf ref %s\n",
3805 pNameTable + lib_offs + 40);
3807 len = strlen(fname);
3808 if(fname[len-1] != '#')
3809 FIXME("fname = %s\n", fname);
3810 fname[len-1] = '\0';
3811 import->name = TLB_MultiByteToBSTR(fname);
3812 list_add_tail(&pTL->implib_list, &import->entry);
3814 ref_type->pImpTLInfo = import;
3816 /* Store a reference to IDispatch */
3817 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3818 pTL->dispatch_href = typelib_ref;
3820 } else { /* internal ref */
3821 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3823 ref_type->reference = typelib_ref;
3824 ref_type->index = type_num;
3826 heap_free(refname);
3827 list_add_tail(&pTL->ref_list, &ref_type->entry);
3829 table->refs[ref] = typelib_ref;
3830 typelib_ref += 4;
3832 if((BYTE)*name != SLTG_REF_MAGIC)
3833 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3834 dump_TLBRefType(pTL);
3835 return table;
3838 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3839 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3841 SLTG_ImplInfo *info;
3842 TLBImplType *pImplType;
3843 /* I don't really get this structure, usually it's 0x16 bytes
3844 long, but iuser.tlb contains some that are 0x18 bytes long.
3845 That's ok because we can use the next ptr to jump to the next
3846 one. But how do we know the length of the last one? The WORD
3847 at offs 0x8 might be the clue. For now I'm just assuming that
3848 the last one is the regular 0x16 bytes. */
3850 info = (SLTG_ImplInfo*)pBlk;
3851 while(1){
3852 pTI->cImplTypes++;
3853 if(info->next == 0xffff)
3854 break;
3855 info = (SLTG_ImplInfo*)(pBlk + info->next);
3858 info = (SLTG_ImplInfo*)pBlk;
3859 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
3860 pImplType = pTI->impltypes;
3861 while(1) {
3862 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3863 pImplType->implflags = info->impltypeflags;
3864 ++pImplType;
3866 if(info->next == 0xffff)
3867 break;
3868 if(OneOnly)
3869 FIXME_(typelib)("Interface inheriting more than one interface\n");
3870 info = (SLTG_ImplInfo*)(pBlk + info->next);
3872 info++; /* see comment at top of function */
3873 return (char*)info;
3876 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3877 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3879 TLBVarDesc *pVarDesc;
3880 const TLBString *prevName = NULL;
3881 SLTG_Variable *pItem;
3882 unsigned short i;
3883 WORD *pType;
3885 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
3887 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3888 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3890 pVarDesc->vardesc.memid = pItem->memid;
3892 if (pItem->magic != SLTG_VAR_MAGIC &&
3893 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3894 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3895 return;
3898 if (pItem->name == 0xfffe)
3899 pVarDesc->Name = prevName;
3900 else
3901 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
3903 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
3904 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3905 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3907 if(pItem->flags & 0x02)
3908 pType = &pItem->type;
3909 else
3910 pType = (WORD*)(pBlk + pItem->type);
3912 if (pItem->flags & ~0xda)
3913 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3915 SLTG_DoElem(pType, pBlk,
3916 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3918 if (TRACE_ON(typelib)) {
3919 char buf[300];
3920 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3921 TRACE_(typelib)("elemdescVar: %s\n", buf);
3924 if (pItem->flags & 0x40) {
3925 TRACE_(typelib)("VAR_DISPATCH\n");
3926 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3928 else if (pItem->flags & 0x10) {
3929 TRACE_(typelib)("VAR_CONST\n");
3930 pVarDesc->vardesc.varkind = VAR_CONST;
3931 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3932 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3933 if (pItem->flags & 0x08)
3934 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3935 else {
3936 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3938 case VT_LPSTR:
3939 case VT_LPWSTR:
3940 case VT_BSTR:
3942 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3943 BSTR str;
3944 TRACE_(typelib)("len = %u\n", len);
3945 if (len == 0xffff) {
3946 str = NULL;
3947 } else {
3948 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3949 str = SysAllocStringLen(NULL, alloc_len);
3950 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3952 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3953 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3954 break;
3956 case VT_I2:
3957 case VT_UI2:
3958 case VT_I4:
3959 case VT_UI4:
3960 case VT_INT:
3961 case VT_UINT:
3962 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3963 *(INT*)(pBlk + pItem->byte_offs);
3964 break;
3965 default:
3966 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3970 else {
3971 TRACE_(typelib)("VAR_PERINSTANCE\n");
3972 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3973 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3976 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3977 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3979 if (pItem->flags & 0x80)
3980 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3982 prevName = pVarDesc->Name;
3984 pTI->cVars = cVars;
3987 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3988 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3990 SLTG_Function *pFunc;
3991 unsigned short i;
3992 TLBFuncDesc *pFuncDesc;
3994 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
3996 pFuncDesc = pTI->funcdescs;
3997 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3998 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4000 int param;
4001 WORD *pType, *pArg;
4003 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4004 case SLTG_FUNCTION_MAGIC:
4005 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4006 break;
4007 case SLTG_DISPATCH_FUNCTION_MAGIC:
4008 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4009 break;
4010 case SLTG_STATIC_FUNCTION_MAGIC:
4011 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4012 break;
4013 default:
4014 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4015 continue;
4017 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4019 pFuncDesc->funcdesc.memid = pFunc->dispid;
4020 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4021 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4022 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4023 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4024 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4026 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4027 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4029 if(pFunc->retnextopt & 0x80)
4030 pType = &pFunc->rettype;
4031 else
4032 pType = (WORD*)(pBlk + pFunc->rettype);
4034 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4036 pFuncDesc->funcdesc.lprgelemdescParam =
4037 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4038 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4040 pArg = (WORD*)(pBlk + pFunc->arg_off);
4042 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4043 char *paramName = pNameTable + *pArg;
4044 BOOL HaveOffs;
4045 /* If arg type follows then paramName points to the 2nd
4046 letter of the name, else the next WORD is an offset to
4047 the arg type and paramName points to the first letter.
4048 So let's take one char off paramName and see if we're
4049 pointing at an alpha-numeric char. However if *pArg is
4050 0xffff or 0xfffe then the param has no name, the former
4051 meaning that the next WORD is the type, the latter
4052 meaning that the next WORD is an offset to the type. */
4054 HaveOffs = FALSE;
4055 if(*pArg == 0xffff)
4056 paramName = NULL;
4057 else if(*pArg == 0xfffe) {
4058 paramName = NULL;
4059 HaveOffs = TRUE;
4061 else if(paramName[-1] && !isalnum(paramName[-1]))
4062 HaveOffs = TRUE;
4064 pArg++;
4066 if(HaveOffs) { /* the next word is an offset to type */
4067 pType = (WORD*)(pBlk + *pArg);
4068 SLTG_DoElem(pType, pBlk,
4069 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4070 pArg++;
4071 } else {
4072 if(paramName)
4073 paramName--;
4074 pArg = SLTG_DoElem(pArg, pBlk,
4075 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4078 /* Are we an optional param ? */
4079 if(pFuncDesc->funcdesc.cParams - param <=
4080 pFuncDesc->funcdesc.cParamsOpt)
4081 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4083 if(paramName) {
4084 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4085 paramName - pNameTable, pTI->pTypeLib);
4086 } else {
4087 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4091 pTI->cFuncs = cFuncs;
4094 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4095 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4096 SLTG_TypeInfoTail *pTITail)
4098 char *pFirstItem;
4099 sltg_ref_lookup_t *ref_lookup = NULL;
4101 if(pTIHeader->href_table != 0xffffffff) {
4102 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4103 pNameTable);
4106 pFirstItem = pBlk;
4108 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4109 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4111 heap_free(ref_lookup);
4115 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4116 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4117 const SLTG_TypeInfoTail *pTITail)
4119 char *pFirstItem;
4120 sltg_ref_lookup_t *ref_lookup = NULL;
4122 if(pTIHeader->href_table != 0xffffffff) {
4123 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4124 pNameTable);
4127 pFirstItem = pBlk;
4129 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4130 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4133 if (pTITail->funcs_off != 0xffff)
4134 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4136 heap_free(ref_lookup);
4138 if (TRACE_ON(typelib))
4139 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4142 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4143 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4144 const SLTG_TypeInfoTail *pTITail)
4146 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4149 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4150 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4151 const SLTG_TypeInfoTail *pTITail)
4153 WORD *pType;
4154 sltg_ref_lookup_t *ref_lookup = NULL;
4156 if (pTITail->simple_alias) {
4157 /* if simple alias, no more processing required */
4158 pTI->tdescAlias.vt = pTITail->tdescalias_vt;
4159 return;
4162 if(pTIHeader->href_table != 0xffffffff) {
4163 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4164 pNameTable);
4167 /* otherwise it is an offset to a type */
4168 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4170 SLTG_DoType(pType, pBlk, &pTI->tdescAlias, ref_lookup);
4172 heap_free(ref_lookup);
4175 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4176 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4177 const SLTG_TypeInfoTail *pTITail)
4179 sltg_ref_lookup_t *ref_lookup = NULL;
4180 if (pTIHeader->href_table != 0xffffffff)
4181 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4182 pNameTable);
4184 if (pTITail->vars_off != 0xffff)
4185 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4187 if (pTITail->funcs_off != 0xffff)
4188 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4190 if (pTITail->impls_off != 0xffff)
4191 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4193 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4194 * of dispinterface functions including the IDispatch ones, so
4195 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4196 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4198 heap_free(ref_lookup);
4199 if (TRACE_ON(typelib))
4200 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4203 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4204 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4205 const SLTG_TypeInfoTail *pTITail)
4207 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4210 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4211 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4212 const SLTG_TypeInfoTail *pTITail)
4214 sltg_ref_lookup_t *ref_lookup = NULL;
4215 if (pTIHeader->href_table != 0xffffffff)
4216 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4217 pNameTable);
4219 if (pTITail->vars_off != 0xffff)
4220 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4222 if (pTITail->funcs_off != 0xffff)
4223 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4224 heap_free(ref_lookup);
4225 if (TRACE_ON(typelib))
4226 dump_TypeInfo(pTI);
4229 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4230 manageable copy of it into this */
4231 typedef struct {
4232 WORD small_no;
4233 char *index_name;
4234 char *other_name;
4235 WORD res1a;
4236 WORD name_offs;
4237 WORD more_bytes;
4238 char *extra;
4239 WORD res20;
4240 DWORD helpcontext;
4241 WORD res26;
4242 GUID uuid;
4243 } SLTG_InternalOtherTypeInfo;
4245 /****************************************************************************
4246 * ITypeLib2_Constructor_SLTG
4248 * loading a SLTG typelib from an in-memory image
4250 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4252 ITypeLibImpl *pTypeLibImpl;
4253 SLTG_Header *pHeader;
4254 SLTG_BlkEntry *pBlkEntry;
4255 SLTG_Magic *pMagic;
4256 SLTG_Index *pIndex;
4257 SLTG_Pad9 *pPad9;
4258 LPVOID pBlk, pFirstBlk;
4259 SLTG_LibBlk *pLibBlk;
4260 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4261 char *pAfterOTIBlks = NULL;
4262 char *pNameTable, *ptr;
4263 int i;
4264 DWORD len, order;
4265 ITypeInfoImpl **ppTypeInfoImpl;
4267 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4270 pTypeLibImpl = TypeLibImpl_Constructor();
4271 if (!pTypeLibImpl) return NULL;
4273 pHeader = pLib;
4275 TRACE_(typelib)("header:\n");
4276 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4277 pHeader->nrOfFileBlks );
4278 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4279 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4280 pHeader->SLTG_magic);
4281 return NULL;
4284 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4285 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4287 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4288 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4290 /* Next we have a magic block */
4291 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4293 /* Let's see if we're still in sync */
4294 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4295 sizeof(SLTG_COMPOBJ_MAGIC))) {
4296 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4297 return NULL;
4299 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4300 sizeof(SLTG_DIR_MAGIC))) {
4301 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4302 return NULL;
4305 pIndex = (SLTG_Index*)(pMagic+1);
4307 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4309 pFirstBlk = pPad9 + 1;
4311 /* We'll set up a ptr to the main library block, which is the last one. */
4313 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4314 pBlkEntry[order].next != 0;
4315 order = pBlkEntry[order].next - 1, i++) {
4316 pBlk = (char*)pBlk + pBlkEntry[order].len;
4318 pLibBlk = pBlk;
4320 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4322 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4323 interspersed */
4325 len += 0x40;
4327 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4329 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4332 ptr = (char*)pLibBlk + len;
4334 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4335 WORD w, extra;
4336 len = 0;
4338 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4340 w = *(WORD*)(ptr + 2);
4341 if(w != 0xffff) {
4342 len += w;
4343 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4344 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4345 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4347 w = *(WORD*)(ptr + 4 + len);
4348 if(w != 0xffff) {
4349 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4350 len += w;
4351 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4352 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4353 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4355 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4356 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4357 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4358 if(extra) {
4359 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4360 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4361 len += extra;
4363 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4364 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4365 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4366 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4367 len += sizeof(SLTG_OtherTypeInfo);
4368 ptr += len;
4371 pAfterOTIBlks = ptr;
4373 /* Skip this WORD and get the next DWORD */
4374 len = *(DWORD*)(pAfterOTIBlks + 2);
4376 /* Now add this to pLibBLk look at what we're pointing at and
4377 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4378 dust and we should be pointing at the beginning of the name
4379 table */
4381 pNameTable = (char*)pLibBlk + len;
4383 switch(*(WORD*)pNameTable) {
4384 case 0xffff:
4385 break;
4386 case 0x0200:
4387 pNameTable += 0x20;
4388 break;
4389 default:
4390 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4391 break;
4394 pNameTable += 0x216;
4396 pNameTable += 2;
4398 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4400 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4403 /* Hopefully we now have enough ptrs set up to actually read in
4404 some TypeInfos. It's not clear which order to do them in, so
4405 I'll just follow the links along the BlkEntry chain and read
4406 them in the order in which they are in the file */
4408 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4409 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4411 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4412 pBlkEntry[order].next != 0;
4413 order = pBlkEntry[order].next - 1, i++) {
4415 SLTG_TypeInfoHeader *pTIHeader;
4416 SLTG_TypeInfoTail *pTITail;
4417 SLTG_MemberHeader *pMemHeader;
4419 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4420 FIXME_(typelib)("Index strings don't match\n");
4421 heap_free(pOtherTypeInfoBlks);
4422 return NULL;
4425 pTIHeader = pBlk;
4426 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4427 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4428 heap_free(pOtherTypeInfoBlks);
4429 return NULL;
4431 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4432 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4433 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4435 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4436 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4437 (*ppTypeInfoImpl)->index = i;
4438 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4439 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4440 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4441 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4442 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4443 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4444 (*ppTypeInfoImpl)->wTypeFlags =
4445 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4447 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4448 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4450 if((pTIHeader->typeflags1 & 7) != 2)
4451 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4452 if(pTIHeader->typeflags3 != 2)
4453 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4455 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4456 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4457 typekind_desc[pTIHeader->typekind],
4458 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4459 (*ppTypeInfoImpl)->wTypeFlags);
4461 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4463 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4465 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4466 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4467 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4469 switch(pTIHeader->typekind) {
4470 case TKIND_ENUM:
4471 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4472 pTIHeader, pTITail);
4473 break;
4475 case TKIND_RECORD:
4476 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4477 pTIHeader, pTITail);
4478 break;
4480 case TKIND_INTERFACE:
4481 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4482 pTIHeader, pTITail);
4483 break;
4485 case TKIND_COCLASS:
4486 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4487 pTIHeader, pTITail);
4488 break;
4490 case TKIND_ALIAS:
4491 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4492 pTIHeader, pTITail);
4493 break;
4495 case TKIND_DISPATCH:
4496 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4497 pTIHeader, pTITail);
4498 break;
4500 case TKIND_MODULE:
4501 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4502 pTIHeader, pTITail);
4503 break;
4505 default:
4506 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4507 break;
4511 /* could get cFuncs, cVars and cImplTypes from here
4512 but we've already set those */
4513 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4514 X(06);
4515 X(16);
4516 X(18);
4517 X(1a);
4518 X(1e);
4519 X(24);
4520 X(26);
4521 X(2a);
4522 X(2c);
4523 X(2e);
4524 X(30);
4525 X(32);
4526 X(34);
4527 #undef X
4528 ++ppTypeInfoImpl;
4529 pBlk = (char*)pBlk + pBlkEntry[order].len;
4532 if(i != pTypeLibImpl->TypeInfoCount) {
4533 FIXME("Somehow processed %d TypeInfos\n", i);
4534 heap_free(pOtherTypeInfoBlks);
4535 return NULL;
4538 heap_free(pOtherTypeInfoBlks);
4539 return &pTypeLibImpl->ITypeLib2_iface;
4542 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4544 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4546 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4548 if(IsEqualIID(riid, &IID_IUnknown) ||
4549 IsEqualIID(riid,&IID_ITypeLib)||
4550 IsEqualIID(riid,&IID_ITypeLib2))
4552 *ppv = &This->ITypeLib2_iface;
4554 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4555 IsEqualIID(riid, &IID_ICreateTypeLib2))
4557 *ppv = &This->ICreateTypeLib2_iface;
4559 else
4561 *ppv = NULL;
4562 TRACE("-- Interface: E_NOINTERFACE\n");
4563 return E_NOINTERFACE;
4566 IUnknown_AddRef((IUnknown*)*ppv);
4567 return S_OK;
4570 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4572 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4573 ULONG ref = InterlockedIncrement(&This->ref);
4575 TRACE("(%p) ref=%u\n", This, ref);
4577 return ref;
4580 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4582 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4583 ULONG ref = InterlockedDecrement(&This->ref);
4585 TRACE("(%p) ref=%u\n",This, ref);
4587 if (!ref)
4589 TLBImpLib *pImpLib, *pImpLibNext;
4590 TLBRefType *ref_type;
4591 TLBString *tlbstr, *tlbstr_next;
4592 TLBGuid *tlbguid, *tlbguid_next;
4593 void *cursor2;
4594 int i;
4596 /* remove cache entry */
4597 if(This->path)
4599 TRACE("removing from cache list\n");
4600 EnterCriticalSection(&cache_section);
4601 if(This->entry.next)
4602 list_remove(&This->entry);
4603 LeaveCriticalSection(&cache_section);
4604 heap_free(This->path);
4606 TRACE(" destroying ITypeLib(%p)\n",This);
4608 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4609 list_remove(&tlbstr->entry);
4610 SysFreeString(tlbstr->str);
4611 heap_free(tlbstr);
4614 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4615 list_remove(&tlbstr->entry);
4616 SysFreeString(tlbstr->str);
4617 heap_free(tlbstr);
4620 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4621 list_remove(&tlbguid->entry);
4622 heap_free(tlbguid);
4625 TLB_FreeCustData(&This->custdata_list);
4627 for (i = 0; i < This->ctTypeDesc; i++)
4628 if (This->pTypeDesc[i].vt == VT_CARRAY)
4629 heap_free(This->pTypeDesc[i].u.lpadesc);
4631 heap_free(This->pTypeDesc);
4633 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4635 if (pImpLib->pImpTypeLib)
4636 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4637 SysFreeString(pImpLib->name);
4639 list_remove(&pImpLib->entry);
4640 heap_free(pImpLib);
4643 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4645 list_remove(&ref_type->entry);
4646 heap_free(ref_type);
4649 for (i = 0; i < This->TypeInfoCount; ++i)
4650 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4651 heap_free(This->typeinfos);
4652 heap_free(This);
4653 return 0;
4656 return ref;
4659 /* ITypeLib::GetTypeInfoCount
4661 * Returns the number of type descriptions in the type library
4663 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4665 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4666 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4667 return This->TypeInfoCount;
4670 /* ITypeLib::GetTypeInfo
4672 * retrieves the specified type description in the library.
4674 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4675 ITypeLib2 *iface,
4676 UINT index,
4677 ITypeInfo **ppTInfo)
4679 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4681 TRACE("%p %u %p\n", This, index, ppTInfo);
4683 if(!ppTInfo)
4684 return E_INVALIDARG;
4686 if(index >= This->TypeInfoCount)
4687 return TYPE_E_ELEMENTNOTFOUND;
4689 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4690 ITypeInfo_AddRef(*ppTInfo);
4692 return S_OK;
4696 /* ITypeLibs::GetTypeInfoType
4698 * Retrieves the type of a type description.
4700 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4701 ITypeLib2 *iface,
4702 UINT index,
4703 TYPEKIND *pTKind)
4705 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4707 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4709 if(!pTKind)
4710 return E_INVALIDARG;
4712 if(index >= This->TypeInfoCount)
4713 return TYPE_E_ELEMENTNOTFOUND;
4715 *pTKind = This->typeinfos[index]->typekind;
4717 return S_OK;
4720 /* ITypeLib::GetTypeInfoOfGuid
4722 * Retrieves the type description that corresponds to the specified GUID.
4725 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4726 ITypeLib2 *iface,
4727 REFGUID guid,
4728 ITypeInfo **ppTInfo)
4730 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4731 int i;
4733 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4735 for(i = 0; i < This->TypeInfoCount; ++i){
4736 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4737 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4738 ITypeInfo_AddRef(*ppTInfo);
4739 return S_OK;
4743 return TYPE_E_ELEMENTNOTFOUND;
4746 /* ITypeLib::GetLibAttr
4748 * Retrieves the structure that contains the library's attributes.
4751 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4752 ITypeLib2 *iface,
4753 LPTLIBATTR *attr)
4755 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4757 TRACE("(%p, %p)\n", This, attr);
4759 if (!attr) return E_INVALIDARG;
4761 *attr = heap_alloc(sizeof(**attr));
4762 if (!*attr) return E_OUTOFMEMORY;
4764 (*attr)->guid = *TLB_get_guid_null(This->guid);
4765 (*attr)->lcid = This->set_lcid;
4766 (*attr)->syskind = This->syskind;
4767 (*attr)->wMajorVerNum = This->ver_major;
4768 (*attr)->wMinorVerNum = This->ver_minor;
4769 (*attr)->wLibFlags = This->libflags;
4771 return S_OK;
4774 /* ITypeLib::GetTypeComp
4776 * Enables a client compiler to bind to a library's types, variables,
4777 * constants, and global functions.
4780 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4781 ITypeLib2 *iface,
4782 ITypeComp **ppTComp)
4784 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4786 TRACE("(%p)->(%p)\n",This,ppTComp);
4787 *ppTComp = &This->ITypeComp_iface;
4788 ITypeComp_AddRef(*ppTComp);
4790 return S_OK;
4793 /* ITypeLib::GetDocumentation
4795 * Retrieves the library's documentation string, the complete Help file name
4796 * and path, and the context identifier for the library Help topic in the Help
4797 * file.
4799 * On a successful return all non-null BSTR pointers will have been set,
4800 * possibly to NULL.
4802 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4803 ITypeLib2 *iface,
4804 INT index,
4805 BSTR *pBstrName,
4806 BSTR *pBstrDocString,
4807 DWORD *pdwHelpContext,
4808 BSTR *pBstrHelpFile)
4810 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4811 HRESULT result = E_INVALIDARG;
4812 ITypeInfo *pTInfo;
4814 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4815 This, index,
4816 pBstrName, pBstrDocString,
4817 pdwHelpContext, pBstrHelpFile);
4819 if(index<0)
4821 /* documentation for the typelib */
4822 if(pBstrName)
4824 if (This->Name)
4826 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4827 goto memerr1;
4829 else
4830 *pBstrName = NULL;
4832 if(pBstrDocString)
4834 if (This->DocString)
4836 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4837 goto memerr2;
4839 else
4840 *pBstrDocString = NULL;
4842 if(pdwHelpContext)
4844 *pdwHelpContext = This->dwHelpContext;
4846 if(pBstrHelpFile)
4848 if (This->HelpFile)
4850 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4851 goto memerr3;
4853 else
4854 *pBstrHelpFile = NULL;
4857 result = S_OK;
4859 else
4861 /* for a typeinfo */
4862 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4864 if(SUCCEEDED(result))
4866 result = ITypeInfo_GetDocumentation(pTInfo,
4867 MEMBERID_NIL,
4868 pBstrName,
4869 pBstrDocString,
4870 pdwHelpContext, pBstrHelpFile);
4872 ITypeInfo_Release(pTInfo);
4875 return result;
4876 memerr3:
4877 if (pBstrDocString) SysFreeString (*pBstrDocString);
4878 memerr2:
4879 if (pBstrName) SysFreeString (*pBstrName);
4880 memerr1:
4881 return STG_E_INSUFFICIENTMEMORY;
4884 /* ITypeLib::IsName
4886 * Indicates whether a passed-in string contains the name of a type or member
4887 * described in the library.
4890 static HRESULT WINAPI ITypeLib2_fnIsName(
4891 ITypeLib2 *iface,
4892 LPOLESTR szNameBuf,
4893 ULONG lHashVal,
4894 BOOL *pfName)
4896 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4897 int tic;
4898 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
4900 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4901 pfName);
4903 *pfName=TRUE;
4904 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4905 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4906 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4907 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4908 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4909 int pc;
4910 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4911 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
4912 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
4913 goto ITypeLib2_fnIsName_exit;
4916 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
4917 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4918 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4922 *pfName=FALSE;
4924 ITypeLib2_fnIsName_exit:
4925 TRACE("(%p)slow! search for %s: %s found!\n", This,
4926 debugstr_w(szNameBuf), *pfName?"NOT":"");
4928 return S_OK;
4931 /* ITypeLib::FindName
4933 * Finds occurrences of a type description in a type library. This may be used
4934 * to quickly verify that a name exists in a type library.
4937 static HRESULT WINAPI ITypeLib2_fnFindName(
4938 ITypeLib2 *iface,
4939 LPOLESTR name,
4940 ULONG hash,
4941 ITypeInfo **ppTInfo,
4942 MEMBERID *memid,
4943 UINT16 *found)
4945 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4946 int tic;
4947 UINT count = 0;
4948 UINT len;
4950 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4952 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4953 return E_INVALIDARG;
4955 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4956 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4957 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4958 TLBVarDesc *var;
4959 UINT fdc;
4961 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4962 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4963 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4964 int pc;
4966 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4967 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4968 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
4969 goto ITypeLib2_fnFindName_exit;
4973 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
4974 if (var)
4975 goto ITypeLib2_fnFindName_exit;
4977 continue;
4978 ITypeLib2_fnFindName_exit:
4979 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
4980 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
4981 count++;
4983 TRACE("found %d typeinfos\n", count);
4985 *found = count;
4987 return S_OK;
4990 /* ITypeLib::ReleaseTLibAttr
4992 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4995 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4996 ITypeLib2 *iface,
4997 TLIBATTR *pTLibAttr)
4999 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5000 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5001 heap_free(pTLibAttr);
5004 /* ITypeLib2::GetCustData
5006 * gets the custom data
5008 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5009 ITypeLib2 * iface,
5010 REFGUID guid,
5011 VARIANT *pVarVal)
5013 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5014 TLBCustData *pCData;
5016 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5018 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5019 if(!pCData)
5020 return TYPE_E_ELEMENTNOTFOUND;
5022 VariantInit(pVarVal);
5023 VariantCopy(pVarVal, &pCData->data);
5025 return S_OK;
5028 /* ITypeLib2::GetLibStatistics
5030 * Returns statistics about a type library that are required for efficient
5031 * sizing of hash tables.
5034 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5035 ITypeLib2 * iface,
5036 ULONG *pcUniqueNames,
5037 ULONG *pcchUniqueNames)
5039 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5041 FIXME("(%p): stub!\n", This);
5043 if(pcUniqueNames) *pcUniqueNames=1;
5044 if(pcchUniqueNames) *pcchUniqueNames=1;
5045 return S_OK;
5048 /* ITypeLib2::GetDocumentation2
5050 * Retrieves the library's documentation string, the complete Help file name
5051 * and path, the localization context to use, and the context ID for the
5052 * library Help topic in the Help file.
5055 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5056 ITypeLib2 * iface,
5057 INT index,
5058 LCID lcid,
5059 BSTR *pbstrHelpString,
5060 DWORD *pdwHelpStringContext,
5061 BSTR *pbstrHelpStringDll)
5063 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5064 HRESULT result;
5065 ITypeInfo *pTInfo;
5067 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5069 /* the help string should be obtained from the helpstringdll,
5070 * using the _DLLGetDocumentation function, based on the supplied
5071 * lcid. Nice to do sometime...
5073 if(index<0)
5075 /* documentation for the typelib */
5076 if(pbstrHelpString)
5077 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5078 if(pdwHelpStringContext)
5079 *pdwHelpStringContext=This->dwHelpContext;
5080 if(pbstrHelpStringDll)
5081 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5083 result = S_OK;
5085 else
5087 /* for a typeinfo */
5088 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5090 if(SUCCEEDED(result))
5092 ITypeInfo2 * pTInfo2;
5093 result = ITypeInfo_QueryInterface(pTInfo,
5094 &IID_ITypeInfo2,
5095 (LPVOID*) &pTInfo2);
5097 if(SUCCEEDED(result))
5099 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5100 MEMBERID_NIL,
5101 lcid,
5102 pbstrHelpString,
5103 pdwHelpStringContext,
5104 pbstrHelpStringDll);
5106 ITypeInfo2_Release(pTInfo2);
5109 ITypeInfo_Release(pTInfo);
5112 return result;
5115 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5117 TLBCustData *pCData;
5118 unsigned int ct;
5119 CUSTDATAITEM *cdi;
5121 ct = list_count(custdata_list);
5123 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5124 if(!pCustData->prgCustData)
5125 return E_OUTOFMEMORY;
5127 pCustData->cCustData = ct;
5129 cdi = pCustData->prgCustData;
5130 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5131 cdi->guid = *TLB_get_guid_null(pCData->guid);
5132 VariantCopy(&cdi->varValue, &pCData->data);
5133 ++cdi;
5136 return S_OK;
5140 /* ITypeLib2::GetAllCustData
5142 * Gets all custom data items for the library.
5145 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5146 ITypeLib2 * iface,
5147 CUSTDATA *pCustData)
5149 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5150 TRACE("(%p)->(%p)\n", This, pCustData);
5151 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5154 static const ITypeLib2Vtbl tlbvt = {
5155 ITypeLib2_fnQueryInterface,
5156 ITypeLib2_fnAddRef,
5157 ITypeLib2_fnRelease,
5158 ITypeLib2_fnGetTypeInfoCount,
5159 ITypeLib2_fnGetTypeInfo,
5160 ITypeLib2_fnGetTypeInfoType,
5161 ITypeLib2_fnGetTypeInfoOfGuid,
5162 ITypeLib2_fnGetLibAttr,
5163 ITypeLib2_fnGetTypeComp,
5164 ITypeLib2_fnGetDocumentation,
5165 ITypeLib2_fnIsName,
5166 ITypeLib2_fnFindName,
5167 ITypeLib2_fnReleaseTLibAttr,
5169 ITypeLib2_fnGetCustData,
5170 ITypeLib2_fnGetLibStatistics,
5171 ITypeLib2_fnGetDocumentation2,
5172 ITypeLib2_fnGetAllCustData
5176 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5178 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5180 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5183 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5185 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5187 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5190 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5192 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5194 return ITypeLib2_Release(&This->ITypeLib2_iface);
5197 static HRESULT WINAPI ITypeLibComp_fnBind(
5198 ITypeComp * iface,
5199 OLECHAR * szName,
5200 ULONG lHash,
5201 WORD wFlags,
5202 ITypeInfo ** ppTInfo,
5203 DESCKIND * pDescKind,
5204 BINDPTR * pBindPtr)
5206 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5207 int typemismatch=0, i;
5209 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5211 *pDescKind = DESCKIND_NONE;
5212 pBindPtr->lptcomp = NULL;
5213 *ppTInfo = NULL;
5215 for(i = 0; i < This->TypeInfoCount; ++i){
5216 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5217 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5219 /* FIXME: check wFlags here? */
5220 /* FIXME: we should use a hash table to look this info up using lHash
5221 * instead of an O(n) search */
5222 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5223 (pTypeInfo->typekind == TKIND_MODULE))
5225 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5227 *pDescKind = DESCKIND_TYPECOMP;
5228 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5229 ITypeComp_AddRef(pBindPtr->lptcomp);
5230 TRACE("module or enum: %s\n", debugstr_w(szName));
5231 return S_OK;
5235 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5236 (pTypeInfo->typekind == TKIND_ENUM))
5238 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5239 HRESULT hr;
5241 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5242 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5244 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5245 return S_OK;
5247 else if (hr == TYPE_E_TYPEMISMATCH)
5248 typemismatch = 1;
5251 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5252 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5254 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5255 HRESULT hr;
5256 ITypeInfo *subtypeinfo;
5257 BINDPTR subbindptr;
5258 DESCKIND subdesckind;
5260 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5261 &subtypeinfo, &subdesckind, &subbindptr);
5262 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5264 TYPEDESC tdesc_appobject;
5265 const VARDESC vardesc_appobject =
5267 -2, /* memid */
5268 NULL, /* lpstrSchema */
5270 0 /* oInst */
5273 /* ELEMDESC */
5275 /* TYPEDESC */
5277 &tdesc_appobject
5279 VT_PTR
5282 0, /* wVarFlags */
5283 VAR_STATIC /* varkind */
5286 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5287 tdesc_appobject.vt = VT_USERDEFINED;
5289 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5291 /* cleanup things filled in by Bind call so we can put our
5292 * application object data in there instead */
5293 switch (subdesckind)
5295 case DESCKIND_FUNCDESC:
5296 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5297 break;
5298 case DESCKIND_VARDESC:
5299 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5300 break;
5301 default:
5302 break;
5304 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5306 if (pTypeInfo->hreftype == -1)
5307 FIXME("no hreftype for interface %p\n", pTypeInfo);
5309 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5310 if (FAILED(hr))
5311 return hr;
5313 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5314 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5315 ITypeInfo_AddRef(*ppTInfo);
5316 return S_OK;
5318 else if (hr == TYPE_E_TYPEMISMATCH)
5319 typemismatch = 1;
5323 if (typemismatch)
5325 TRACE("type mismatch %s\n", debugstr_w(szName));
5326 return TYPE_E_TYPEMISMATCH;
5328 else
5330 TRACE("name not found %s\n", debugstr_w(szName));
5331 return S_OK;
5335 static HRESULT WINAPI ITypeLibComp_fnBindType(
5336 ITypeComp * iface,
5337 OLECHAR * szName,
5338 ULONG lHash,
5339 ITypeInfo ** ppTInfo,
5340 ITypeComp ** ppTComp)
5342 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5343 ITypeInfoImpl *info;
5345 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5347 if(!szName || !ppTInfo || !ppTComp)
5348 return E_INVALIDARG;
5350 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5351 if(!info){
5352 *ppTInfo = NULL;
5353 *ppTComp = NULL;
5354 return S_OK;
5357 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5358 ITypeInfo_AddRef(*ppTInfo);
5359 *ppTComp = &info->ITypeComp_iface;
5360 ITypeComp_AddRef(*ppTComp);
5362 return S_OK;
5365 static const ITypeCompVtbl tlbtcvt =
5368 ITypeLibComp_fnQueryInterface,
5369 ITypeLibComp_fnAddRef,
5370 ITypeLibComp_fnRelease,
5372 ITypeLibComp_fnBind,
5373 ITypeLibComp_fnBindType
5376 /*================== ITypeInfo(2) Methods ===================================*/
5377 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5379 ITypeInfoImpl *pTypeInfoImpl;
5381 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5382 if (pTypeInfoImpl)
5384 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5385 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5386 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5387 pTypeInfoImpl->ref = 0;
5388 pTypeInfoImpl->hreftype = -1;
5389 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5390 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5391 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5392 list_init(pTypeInfoImpl->pcustdata_list);
5394 TRACE("(%p)\n", pTypeInfoImpl);
5395 return pTypeInfoImpl;
5398 /* ITypeInfo::QueryInterface
5400 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5401 ITypeInfo2 *iface,
5402 REFIID riid,
5403 VOID **ppvObject)
5405 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5407 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5409 *ppvObject=NULL;
5410 if(IsEqualIID(riid, &IID_IUnknown) ||
5411 IsEqualIID(riid,&IID_ITypeInfo)||
5412 IsEqualIID(riid,&IID_ITypeInfo2))
5413 *ppvObject = This;
5414 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5415 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5416 *ppvObject = &This->ICreateTypeInfo2_iface;
5418 if(*ppvObject){
5419 ITypeInfo2_AddRef(iface);
5420 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5421 return S_OK;
5423 TRACE("-- Interface: E_NOINTERFACE\n");
5424 return E_NOINTERFACE;
5427 /* ITypeInfo::AddRef
5429 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5431 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5432 ULONG ref = InterlockedIncrement(&This->ref);
5434 TRACE("(%p)->ref is %u\n",This, ref);
5436 if (ref == 1 /* incremented from 0 */)
5437 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5439 return ref;
5442 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5444 UINT i;
5446 TRACE("destroying ITypeInfo(%p)\n",This);
5448 for (i = 0; i < This->cFuncs; ++i)
5450 int j;
5451 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5452 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5454 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5455 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5456 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5457 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5459 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5460 heap_free(pFInfo->pParamDesc);
5461 TLB_FreeCustData(&pFInfo->custdata_list);
5463 heap_free(This->funcdescs);
5465 for(i = 0; i < This->cVars; ++i)
5467 TLBVarDesc *pVInfo = &This->vardescs[i];
5468 if (pVInfo->vardesc_create) {
5469 TLB_FreeVarDesc(pVInfo->vardesc_create);
5470 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5471 VariantClear(pVInfo->vardesc.u.lpvarValue);
5472 heap_free(pVInfo->vardesc.u.lpvarValue);
5474 TLB_FreeCustData(&pVInfo->custdata_list);
5476 heap_free(This->vardescs);
5478 if(This->impltypes){
5479 for (i = 0; i < This->cImplTypes; ++i){
5480 TLBImplType *pImpl = &This->impltypes[i];
5481 TLB_FreeCustData(&pImpl->custdata_list);
5483 heap_free(This->impltypes);
5486 TLB_FreeCustData(&This->custdata_list);
5488 heap_free(This);
5491 /* ITypeInfo::Release
5493 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5495 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5496 ULONG ref = InterlockedDecrement(&This->ref);
5498 TRACE("(%p)->(%u)\n",This, ref);
5500 if (!ref)
5502 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5503 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5504 if (not_attached_to_typelib)
5505 heap_free(This);
5506 /* otherwise This will be freed when typelib is freed */
5509 return ref;
5512 /* ITypeInfo::GetTypeAttr
5514 * Retrieves a TYPEATTR structure that contains the attributes of the type
5515 * description.
5518 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5519 LPTYPEATTR *ppTypeAttr)
5521 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5522 SIZE_T size;
5524 TRACE("(%p)\n",This);
5526 size = sizeof(**ppTypeAttr);
5527 if (This->typekind == TKIND_ALIAS)
5528 size += TLB_SizeTypeDesc(&This->tdescAlias, FALSE);
5530 *ppTypeAttr = heap_alloc(size);
5531 if (!*ppTypeAttr)
5532 return E_OUTOFMEMORY;
5534 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5535 (*ppTypeAttr)->lcid = This->lcid;
5536 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5537 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5538 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5539 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5540 (*ppTypeAttr)->typekind = This->typekind;
5541 (*ppTypeAttr)->cFuncs = This->cFuncs;
5542 (*ppTypeAttr)->cVars = This->cVars;
5543 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5544 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5545 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5546 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5547 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5548 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5549 (*ppTypeAttr)->tdescAlias = This->tdescAlias;
5550 (*ppTypeAttr)->idldescType = This->idldescType;
5552 if (This->typekind == TKIND_ALIAS)
5553 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5554 &This->tdescAlias, *ppTypeAttr + 1);
5556 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5557 /* This should include all the inherited funcs */
5558 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5559 /* This is always the size of IDispatch's vtbl */
5560 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5561 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5563 return S_OK;
5566 /* ITypeInfo::GetTypeComp
5568 * Retrieves the ITypeComp interface for the type description, which enables a
5569 * client compiler to bind to the type description's members.
5572 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5573 ITypeComp * *ppTComp)
5575 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5577 TRACE("(%p)->(%p)\n", This, ppTComp);
5579 *ppTComp = &This->ITypeComp_iface;
5580 ITypeComp_AddRef(*ppTComp);
5581 return S_OK;
5584 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5586 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5587 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5588 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5589 return size;
5592 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5594 *dest = *src;
5595 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5596 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5598 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5599 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5600 *buffer += sizeof(PARAMDESCEX);
5601 *pparamdescex_dest = *pparamdescex_src;
5602 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5603 VariantInit(&pparamdescex_dest->varDefaultValue);
5604 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5605 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5607 else
5608 dest->u.paramdesc.pparamdescex = NULL;
5609 return S_OK;
5612 static HRESULT TLB_SanitizeBSTR(BSTR str)
5614 UINT len = SysStringLen(str), i;
5615 for (i = 0; i < len; ++i)
5616 if (str[i] > 0x7f)
5617 str[i] = '?';
5618 return S_OK;
5621 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5623 if (V_VT(var) == VT_INT)
5624 return VariantChangeType(var, var, 0, VT_I4);
5625 else if (V_VT(var) == VT_UINT)
5626 return VariantChangeType(var, var, 0, VT_UI4);
5627 else if (V_VT(var) == VT_BSTR)
5628 return TLB_SanitizeBSTR(V_BSTR(var));
5630 return S_OK;
5633 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5635 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5636 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5639 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5641 FUNCDESC *dest;
5642 char *buffer;
5643 SIZE_T size = sizeof(*src);
5644 SHORT i;
5645 HRESULT hr;
5647 size += sizeof(*src->lprgscode) * src->cScodes;
5648 size += TLB_SizeElemDesc(&src->elemdescFunc);
5649 for (i = 0; i < src->cParams; i++)
5651 size += sizeof(ELEMDESC);
5652 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5655 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5656 if (!dest) return E_OUTOFMEMORY;
5658 *dest = *src;
5659 if (dispinterface) /* overwrite funckind */
5660 dest->funckind = FUNC_DISPATCH;
5661 buffer = (char *)(dest + 1);
5663 dest->oVft = dest->oVft & 0xFFFC;
5665 if (dest->cScodes) {
5666 dest->lprgscode = (SCODE *)buffer;
5667 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5668 buffer += sizeof(*src->lprgscode) * src->cScodes;
5669 } else
5670 dest->lprgscode = NULL;
5672 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5673 if (FAILED(hr))
5675 SysFreeString((BSTR)dest);
5676 return hr;
5679 if (dest->cParams) {
5680 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5681 buffer += sizeof(ELEMDESC) * src->cParams;
5682 for (i = 0; i < src->cParams; i++)
5684 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5685 if (FAILED(hr))
5686 break;
5688 if (FAILED(hr))
5690 /* undo the above actions */
5691 for (i = i - 1; i >= 0; i--)
5692 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5693 TLB_FreeElemDesc(&dest->elemdescFunc);
5694 SysFreeString((BSTR)dest);
5695 return hr;
5697 } else
5698 dest->lprgelemdescParam = NULL;
5700 /* special treatment for dispinterfaces: this makes functions appear
5701 * to return their [retval] value when it is really returning an
5702 * HRESULT */
5703 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5705 if (dest->cParams &&
5706 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5708 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5709 if (elemdesc->tdesc.vt != VT_PTR)
5711 ERR("elemdesc should have started with VT_PTR instead of:\n");
5712 if (ERR_ON(ole))
5713 dump_ELEMDESC(elemdesc);
5714 return E_UNEXPECTED;
5717 /* copy last parameter to the return value. we are using a flat
5718 * buffer so there is no danger of leaking memory in
5719 * elemdescFunc */
5720 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5722 /* remove the last parameter */
5723 dest->cParams--;
5725 else
5726 /* otherwise this function is made to appear to have no return
5727 * value */
5728 dest->elemdescFunc.tdesc.vt = VT_VOID;
5732 *dest_ptr = dest;
5733 return S_OK;
5736 static void TLB_FreeVarDesc(VARDESC *var_desc)
5738 TLB_FreeElemDesc(&var_desc->elemdescVar);
5739 if (var_desc->varkind == VAR_CONST)
5740 VariantClear(var_desc->u.lpvarValue);
5741 SysFreeString((BSTR)var_desc);
5744 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5746 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5748 if (index >= This->cFuncs)
5749 return TYPE_E_ELEMENTNOTFOUND;
5751 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5752 return S_OK;
5755 /* internal function to make the inherited interfaces' methods appear
5756 * part of the interface */
5757 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5758 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5760 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5761 HRESULT hr;
5762 UINT implemented_funcs = 0;
5764 if (funcs)
5765 *funcs = 0;
5766 else
5767 *hrefoffset = DISPATCH_HREF_OFFSET;
5769 if(This->impltypes)
5771 ITypeInfo *pSubTypeInfo;
5772 UINT sub_funcs;
5774 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5775 if (FAILED(hr))
5776 return hr;
5778 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5779 index,
5780 ppFuncDesc,
5781 &sub_funcs, hrefoffset);
5782 implemented_funcs += sub_funcs;
5783 ITypeInfo_Release(pSubTypeInfo);
5784 if (SUCCEEDED(hr))
5785 return hr;
5786 *hrefoffset += DISPATCH_HREF_OFFSET;
5789 if (funcs)
5790 *funcs = implemented_funcs + This->cFuncs;
5791 else
5792 *hrefoffset = 0;
5794 if (index < implemented_funcs)
5795 return E_INVALIDARG;
5796 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5797 ppFuncDesc);
5800 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5802 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5803 while (TRUE)
5805 switch (pTypeDesc->vt)
5807 case VT_USERDEFINED:
5808 pTypeDesc->u.hreftype += hrefoffset;
5809 return;
5810 case VT_PTR:
5811 case VT_SAFEARRAY:
5812 pTypeDesc = pTypeDesc->u.lptdesc;
5813 break;
5814 case VT_CARRAY:
5815 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5816 break;
5817 default:
5818 return;
5823 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5825 SHORT i;
5826 for (i = 0; i < pFuncDesc->cParams; i++)
5827 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5828 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5831 /* ITypeInfo::GetFuncDesc
5833 * Retrieves the FUNCDESC structure that contains information about a
5834 * specified function.
5837 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5838 LPFUNCDESC *ppFuncDesc)
5840 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5841 const FUNCDESC *internal_funcdesc;
5842 HRESULT hr;
5843 UINT hrefoffset = 0;
5845 TRACE("(%p) index %d\n", This, index);
5847 if (!ppFuncDesc)
5848 return E_INVALIDARG;
5850 if (This->needs_layout)
5851 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5853 if (This->typekind == TKIND_DISPATCH)
5854 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5855 &internal_funcdesc, NULL,
5856 &hrefoffset);
5857 else
5858 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5859 &internal_funcdesc);
5860 if (FAILED(hr))
5862 WARN("description for function %d not found\n", index);
5863 return hr;
5866 hr = TLB_AllocAndInitFuncDesc(
5867 internal_funcdesc,
5868 ppFuncDesc,
5869 This->typekind == TKIND_DISPATCH);
5871 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
5872 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5874 TRACE("-- 0x%08x\n", hr);
5875 return hr;
5878 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5880 VARDESC *dest;
5881 char *buffer;
5882 SIZE_T size = sizeof(*src);
5883 HRESULT hr;
5885 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5886 if (src->varkind == VAR_CONST)
5887 size += sizeof(VARIANT);
5888 size += TLB_SizeElemDesc(&src->elemdescVar);
5890 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5891 if (!dest) return E_OUTOFMEMORY;
5893 *dest = *src;
5894 buffer = (char *)(dest + 1);
5895 if (src->lpstrSchema)
5897 int len;
5898 dest->lpstrSchema = (LPOLESTR)buffer;
5899 len = strlenW(src->lpstrSchema);
5900 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5901 buffer += (len + 1) * sizeof(WCHAR);
5904 if (src->varkind == VAR_CONST)
5906 HRESULT hr;
5908 dest->u.lpvarValue = (VARIANT *)buffer;
5909 *dest->u.lpvarValue = *src->u.lpvarValue;
5910 buffer += sizeof(VARIANT);
5911 VariantInit(dest->u.lpvarValue);
5912 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5913 if (FAILED(hr))
5915 SysFreeString((BSTR)dest);
5916 return hr;
5919 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5920 if (FAILED(hr))
5922 if (src->varkind == VAR_CONST)
5923 VariantClear(dest->u.lpvarValue);
5924 SysFreeString((BSTR)dest);
5925 return hr;
5927 *dest_ptr = dest;
5928 return S_OK;
5931 /* ITypeInfo::GetVarDesc
5933 * Retrieves a VARDESC structure that describes the specified variable.
5936 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5937 LPVARDESC *ppVarDesc)
5939 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5940 const TLBVarDesc *pVDesc = &This->vardescs[index];
5942 TRACE("(%p) index %d\n", This, index);
5944 if(index >= This->cVars)
5945 return TYPE_E_ELEMENTNOTFOUND;
5947 if (This->needs_layout)
5948 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5950 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5953 /* ITypeInfo_GetNames
5955 * Retrieves the variable with the specified member ID (or the name of the
5956 * property or method and its parameters) that correspond to the specified
5957 * function ID.
5959 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5960 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5962 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5963 const TLBFuncDesc *pFDesc;
5964 const TLBVarDesc *pVDesc;
5965 int i;
5966 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5968 if(!rgBstrNames)
5969 return E_INVALIDARG;
5971 *pcNames = 0;
5973 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
5974 if(pFDesc)
5976 if(!cMaxNames || !pFDesc->Name)
5977 return S_OK;
5979 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
5980 ++(*pcNames);
5982 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
5983 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
5984 return S_OK;
5985 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
5986 ++(*pcNames);
5988 return S_OK;
5991 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
5992 if(pVDesc)
5994 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
5995 *pcNames=1;
5997 else
5999 if(This->impltypes &&
6000 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
6001 /* recursive search */
6002 ITypeInfo *pTInfo;
6003 HRESULT result;
6004 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6005 if(SUCCEEDED(result))
6007 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6008 ITypeInfo_Release(pTInfo);
6009 return result;
6011 WARN("Could not search inherited interface!\n");
6013 else
6015 WARN("no names found\n");
6017 *pcNames=0;
6018 return TYPE_E_ELEMENTNOTFOUND;
6020 return S_OK;
6024 /* ITypeInfo::GetRefTypeOfImplType
6026 * If a type description describes a COM class, it retrieves the type
6027 * description of the implemented interface types. For an interface,
6028 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6029 * if any exist.
6032 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6033 ITypeInfo2 *iface,
6034 UINT index,
6035 HREFTYPE *pRefType)
6037 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6038 HRESULT hr = S_OK;
6040 TRACE("(%p) index %d\n", This, index);
6041 if (TRACE_ON(ole)) dump_TypeInfo(This);
6043 if(index==(UINT)-1)
6045 /* only valid on dual interfaces;
6046 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6049 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6051 *pRefType = -2;
6053 else
6055 hr = TYPE_E_ELEMENTNOTFOUND;
6058 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6060 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6061 *pRefType = This->pTypeLib->dispatch_href;
6063 else
6065 if(index >= This->cImplTypes)
6066 hr = TYPE_E_ELEMENTNOTFOUND;
6067 else{
6068 *pRefType = This->impltypes[index].hRef;
6069 if(This->typekind == TKIND_INTERFACE)
6070 *pRefType |= 0x2;
6074 if(TRACE_ON(ole))
6076 if(SUCCEEDED(hr))
6077 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6078 else
6079 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6082 return hr;
6085 /* ITypeInfo::GetImplTypeFlags
6087 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6088 * or base interface in a type description.
6090 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6091 UINT index, INT *pImplTypeFlags)
6093 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6095 TRACE("(%p) index %d\n", This, index);
6097 if(!pImplTypeFlags)
6098 return E_INVALIDARG;
6100 if(This->typekind == TKIND_DISPATCH && index == 0){
6101 *pImplTypeFlags = 0;
6102 return S_OK;
6105 if(index >= This->cImplTypes)
6106 return TYPE_E_ELEMENTNOTFOUND;
6108 *pImplTypeFlags = This->impltypes[index].implflags;
6110 return S_OK;
6113 /* GetIDsOfNames
6114 * Maps between member names and member IDs, and parameter names and
6115 * parameter IDs.
6117 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6118 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6120 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6121 const TLBVarDesc *pVDesc;
6122 HRESULT ret=S_OK;
6123 UINT i, fdc;
6125 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6126 cNames);
6128 /* init out parameters in case of failure */
6129 for (i = 0; i < cNames; i++)
6130 pMemId[i] = MEMBERID_NIL;
6132 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6133 int j;
6134 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6135 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6136 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6137 for(i=1; i < cNames; i++){
6138 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6139 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6140 break;
6141 if( j<pFDesc->funcdesc.cParams)
6142 pMemId[i]=j;
6143 else
6144 ret=DISP_E_UNKNOWNNAME;
6146 TRACE("-- 0x%08x\n", ret);
6147 return ret;
6150 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6151 if(pVDesc){
6152 if(cNames)
6153 *pMemId = pVDesc->vardesc.memid;
6154 return ret;
6156 /* not found, see if it can be found in an inherited interface */
6157 if(This->impltypes) {
6158 /* recursive search */
6159 ITypeInfo *pTInfo;
6160 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6161 if(SUCCEEDED(ret)){
6162 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6163 ITypeInfo_Release(pTInfo);
6164 return ret;
6166 WARN("Could not search inherited interface!\n");
6167 } else
6168 WARN("no names found\n");
6169 return DISP_E_UNKNOWNNAME;
6173 #ifdef __i386__
6175 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6176 __ASM_GLOBAL_FUNC( call_method,
6177 "pushl %ebp\n\t"
6178 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6179 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6180 "movl %esp,%ebp\n\t"
6181 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6182 "pushl %esi\n\t"
6183 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6184 "pushl %edi\n\t"
6185 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6186 "movl 12(%ebp),%edx\n\t"
6187 "movl %esp,%edi\n\t"
6188 "shll $2,%edx\n\t"
6189 "jz 1f\n\t"
6190 "subl %edx,%edi\n\t"
6191 "andl $~15,%edi\n\t"
6192 "movl %edi,%esp\n\t"
6193 "movl 12(%ebp),%ecx\n\t"
6194 "movl 16(%ebp),%esi\n\t"
6195 "cld\n\t"
6196 "rep; movsl\n"
6197 "1:\tcall *8(%ebp)\n\t"
6198 "subl %esp,%edi\n\t"
6199 "movl 20(%ebp),%ecx\n\t"
6200 "movl %edi,(%ecx)\n\t"
6201 "leal -8(%ebp),%esp\n\t"
6202 "popl %edi\n\t"
6203 __ASM_CFI(".cfi_same_value %edi\n\t")
6204 "popl %esi\n\t"
6205 __ASM_CFI(".cfi_same_value %esi\n\t")
6206 "popl %ebp\n\t"
6207 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6208 __ASM_CFI(".cfi_same_value %ebp\n\t")
6209 "ret" )
6211 /* same function but returning floating point */
6212 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6214 /* ITypeInfo::Invoke
6216 * Invokes a method, or accesses a property of an object, that implements the
6217 * interface described by the type description.
6219 DWORD
6220 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6221 DWORD res;
6222 int stack_offset;
6224 if (TRACE_ON(ole)) {
6225 int i;
6226 TRACE("Calling %p(",func);
6227 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6228 if (nrargs > 30) TRACE("...");
6229 TRACE(")\n");
6232 switch (callconv) {
6233 case CC_STDCALL:
6234 case CC_CDECL:
6235 res = call_method( func, nrargs, args, &stack_offset );
6236 break;
6237 default:
6238 FIXME("unsupported calling convention %d\n",callconv);
6239 res = -1;
6240 break;
6242 TRACE("returns %08x\n",res);
6243 return res;
6246 #elif defined(__x86_64__)
6248 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6249 __ASM_GLOBAL_FUNC( call_method,
6250 "pushq %rbp\n\t"
6251 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6252 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6253 "movq %rsp,%rbp\n\t"
6254 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6255 "pushq %rsi\n\t"
6256 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6257 "pushq %rdi\n\t"
6258 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6259 "movq %rcx,%rax\n\t"
6260 "movq $4,%rcx\n\t"
6261 "cmp %rcx,%rdx\n\t"
6262 "cmovgq %rdx,%rcx\n\t"
6263 "leaq 0(,%rcx,8),%rdx\n\t"
6264 "subq %rdx,%rsp\n\t"
6265 "andq $~15,%rsp\n\t"
6266 "movq %rsp,%rdi\n\t"
6267 "movq %r8,%rsi\n\t"
6268 "rep; movsq\n\t"
6269 "movq 0(%rsp),%rcx\n\t"
6270 "movq 8(%rsp),%rdx\n\t"
6271 "movq 16(%rsp),%r8\n\t"
6272 "movq 24(%rsp),%r9\n\t"
6273 "movq %rcx,%xmm0\n\t"
6274 "movq %rdx,%xmm1\n\t"
6275 "movq %r8,%xmm2\n\t"
6276 "movq %r9,%xmm3\n\t"
6277 "callq *%rax\n\t"
6278 "leaq -16(%rbp),%rsp\n\t"
6279 "popq %rdi\n\t"
6280 __ASM_CFI(".cfi_same_value %rdi\n\t")
6281 "popq %rsi\n\t"
6282 __ASM_CFI(".cfi_same_value %rsi\n\t")
6283 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6284 "popq %rbp\n\t"
6285 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6286 __ASM_CFI(".cfi_same_value %rbp\n\t")
6287 "ret")
6289 /* same function but returning floating point */
6290 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6292 #endif /* __x86_64__ */
6294 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6296 HRESULT hr = S_OK;
6297 ITypeInfo *tinfo2 = NULL;
6298 TYPEATTR *tattr = NULL;
6300 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6301 if (hr)
6303 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6304 "hr = 0x%08x\n",
6305 tdesc->u.hreftype, hr);
6306 return hr;
6308 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6309 if (hr)
6311 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6312 ITypeInfo_Release(tinfo2);
6313 return hr;
6316 switch (tattr->typekind)
6318 case TKIND_ENUM:
6319 *vt |= VT_I4;
6320 break;
6322 case TKIND_ALIAS:
6323 tdesc = &tattr->tdescAlias;
6324 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6325 break;
6327 case TKIND_INTERFACE:
6328 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6329 *vt |= VT_DISPATCH;
6330 else
6331 *vt |= VT_UNKNOWN;
6332 break;
6334 case TKIND_DISPATCH:
6335 *vt |= VT_DISPATCH;
6336 break;
6338 case TKIND_COCLASS:
6339 *vt |= VT_DISPATCH;
6340 break;
6342 case TKIND_RECORD:
6343 FIXME("TKIND_RECORD unhandled.\n");
6344 hr = E_NOTIMPL;
6345 break;
6347 case TKIND_UNION:
6348 FIXME("TKIND_UNION unhandled.\n");
6349 hr = E_NOTIMPL;
6350 break;
6352 default:
6353 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6354 hr = E_NOTIMPL;
6355 break;
6357 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6358 ITypeInfo_Release(tinfo2);
6359 return hr;
6362 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6364 HRESULT hr = S_OK;
6366 /* enforce only one level of pointer indirection */
6367 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6369 tdesc = tdesc->u.lptdesc;
6371 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6372 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6373 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6374 if ((tdesc->vt == VT_USERDEFINED) ||
6375 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6377 VARTYPE vt_userdefined = 0;
6378 const TYPEDESC *tdesc_userdefined = tdesc;
6379 if (tdesc->vt == VT_PTR)
6381 vt_userdefined = VT_BYREF;
6382 tdesc_userdefined = tdesc->u.lptdesc;
6384 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6385 if ((hr == S_OK) &&
6386 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6387 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6389 *vt |= vt_userdefined;
6390 return S_OK;
6393 *vt = VT_BYREF;
6396 switch (tdesc->vt)
6398 case VT_HRESULT:
6399 *vt |= VT_ERROR;
6400 break;
6401 case VT_USERDEFINED:
6402 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6403 break;
6404 case VT_VOID:
6405 case VT_CARRAY:
6406 case VT_PTR:
6407 case VT_LPSTR:
6408 case VT_LPWSTR:
6409 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6410 hr = DISP_E_BADVARTYPE;
6411 break;
6412 case VT_SAFEARRAY:
6413 *vt |= VT_ARRAY;
6414 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6415 break;
6416 case VT_INT:
6417 *vt |= VT_I4;
6418 break;
6419 case VT_UINT:
6420 *vt |= VT_UI4;
6421 break;
6422 default:
6423 *vt |= tdesc->vt;
6424 break;
6426 return hr;
6429 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6431 ITypeInfo *tinfo2;
6432 TYPEATTR *tattr;
6433 HRESULT hres;
6435 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6436 if(FAILED(hres))
6437 return hres;
6439 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6440 if(FAILED(hres)) {
6441 ITypeInfo_Release(tinfo2);
6442 return hres;
6445 switch(tattr->typekind) {
6446 case TKIND_ALIAS:
6447 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6448 break;
6450 case TKIND_INTERFACE:
6451 case TKIND_DISPATCH:
6452 *guid = tattr->guid;
6453 break;
6455 default:
6456 ERR("Unexpected typekind %d\n", tattr->typekind);
6457 hres = E_UNEXPECTED;
6460 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6461 ITypeInfo_Release(tinfo2);
6462 return hres;
6465 /***********************************************************************
6466 * DispCallFunc (OLEAUT32.@)
6468 * Invokes a function of the specified calling convention, passing the
6469 * specified arguments and returns the result.
6471 * PARAMS
6472 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6473 * oVft [I] The offset in the vtable. See notes.
6474 * cc [I] Calling convention of the function to call.
6475 * vtReturn [I] The return type of the function.
6476 * cActuals [I] Number of parameters.
6477 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6478 * prgpvarg [I] The arguments to pass.
6479 * pvargResult [O] The return value of the function. Can be NULL.
6481 * RETURNS
6482 * Success: S_OK.
6483 * Failure: HRESULT code.
6485 * NOTES
6486 * The HRESULT return value of this function is not affected by the return
6487 * value of the user supplied function, which is returned in pvargResult.
6489 * If pvInstance is NULL then a non-object function is to be called and oVft
6490 * is the address of the function to call.
6492 * The cc parameter can be one of the following values:
6493 *|CC_FASTCALL
6494 *|CC_CDECL
6495 *|CC_PASCAL
6496 *|CC_STDCALL
6497 *|CC_FPFASTCALL
6498 *|CC_SYSCALL
6499 *|CC_MPWCDECL
6500 *|CC_MPWPASCAL
6503 HRESULT WINAPI
6504 DispCallFunc(
6505 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6506 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6508 #ifdef __i386__
6509 int argspos, stack_offset;
6510 void *func;
6511 UINT i;
6512 DWORD *args;
6514 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6515 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6516 pvargResult, V_VT(pvargResult));
6518 if (cc != CC_STDCALL && cc != CC_CDECL)
6520 FIXME("unsupported calling convention %d\n",cc);
6521 return E_INVALIDARG;
6524 /* maximum size for an argument is sizeof(VARIANT) */
6525 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6527 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6528 argspos = 1;
6529 if (pvInstance)
6531 const FARPROC *vtable = *(FARPROC **)pvInstance;
6532 func = vtable[oVft/sizeof(void *)];
6533 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6535 else func = (void *)oVft;
6537 for (i = 0; i < cActuals; i++)
6539 VARIANT *arg = prgpvarg[i];
6541 switch (prgvt[i])
6543 case VT_EMPTY:
6544 break;
6545 case VT_I8:
6546 case VT_UI8:
6547 case VT_R8:
6548 case VT_DATE:
6549 case VT_CY:
6550 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6551 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6552 break;
6553 case VT_DECIMAL:
6554 case VT_VARIANT:
6555 memcpy( &args[argspos], arg, sizeof(*arg) );
6556 argspos += sizeof(*arg) / sizeof(DWORD);
6557 break;
6558 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6559 args[argspos++] = V_BOOL(arg);
6560 break;
6561 default:
6562 args[argspos++] = V_UI4(arg);
6563 break;
6565 TRACE("arg %u: type %d\n",i,prgvt[i]);
6566 dump_Variant(arg);
6569 switch (vtReturn)
6571 case VT_EMPTY:
6572 call_method( func, argspos - 1, args + 1, &stack_offset );
6573 break;
6574 case VT_R4:
6575 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6576 break;
6577 case VT_R8:
6578 case VT_DATE:
6579 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6580 break;
6581 case VT_DECIMAL:
6582 case VT_VARIANT:
6583 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6584 call_method( func, argspos, args, &stack_offset );
6585 break;
6586 case VT_I8:
6587 case VT_UI8:
6588 case VT_CY:
6589 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6590 break;
6591 case VT_HRESULT:
6592 WARN("invalid return type %u\n", vtReturn);
6593 heap_free( args );
6594 return E_INVALIDARG;
6595 default:
6596 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6597 break;
6599 heap_free( args );
6600 if (stack_offset && cc == CC_STDCALL)
6602 WARN( "stack pointer off by %d\n", stack_offset );
6603 return DISP_E_BADCALLEE;
6605 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6606 TRACE("retval: "); dump_Variant(pvargResult);
6607 return S_OK;
6609 #elif defined(__x86_64__)
6610 int argspos;
6611 UINT i;
6612 DWORD_PTR *args;
6613 void *func;
6615 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6616 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6617 pvargResult, V_VT(pvargResult));
6619 if (cc != CC_STDCALL && cc != CC_CDECL)
6621 FIXME("unsupported calling convention %d\n",cc);
6622 return E_INVALIDARG;
6625 /* maximum size for an argument is sizeof(DWORD_PTR) */
6626 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6628 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6629 argspos = 1;
6630 if (pvInstance)
6632 const FARPROC *vtable = *(FARPROC **)pvInstance;
6633 func = vtable[oVft/sizeof(void *)];
6634 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6636 else func = (void *)oVft;
6638 for (i = 0; i < cActuals; i++)
6640 VARIANT *arg = prgpvarg[i];
6642 switch (prgvt[i])
6644 case VT_DECIMAL:
6645 case VT_VARIANT:
6646 args[argspos++] = (ULONG_PTR)arg;
6647 break;
6648 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6649 args[argspos++] = V_BOOL(arg);
6650 break;
6651 default:
6652 args[argspos++] = V_UI8(arg);
6653 break;
6655 TRACE("arg %u: type %d\n",i,prgvt[i]);
6656 dump_Variant(arg);
6659 switch (vtReturn)
6661 case VT_R4:
6662 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6663 break;
6664 case VT_R8:
6665 case VT_DATE:
6666 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6667 break;
6668 case VT_DECIMAL:
6669 case VT_VARIANT:
6670 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6671 call_method( func, argspos, args );
6672 break;
6673 case VT_HRESULT:
6674 WARN("invalid return type %u\n", vtReturn);
6675 heap_free( args );
6676 return E_INVALIDARG;
6677 default:
6678 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6679 break;
6681 heap_free( args );
6682 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6683 TRACE("retval: "); dump_Variant(pvargResult);
6684 return S_OK;
6686 #else
6687 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6688 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6689 return E_NOTIMPL;
6690 #endif
6693 static inline BOOL func_restricted( const FUNCDESC *desc )
6695 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6698 #define INVBUF_ELEMENT_SIZE \
6699 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6700 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6701 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6702 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6703 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6704 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6705 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6706 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6708 static HRESULT WINAPI ITypeInfo_fnInvoke(
6709 ITypeInfo2 *iface,
6710 VOID *pIUnk,
6711 MEMBERID memid,
6712 UINT16 wFlags,
6713 DISPPARAMS *pDispParams,
6714 VARIANT *pVarResult,
6715 EXCEPINFO *pExcepInfo,
6716 UINT *pArgErr)
6718 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6719 int i;
6720 unsigned int var_index;
6721 TYPEKIND type_kind;
6722 HRESULT hres;
6723 const TLBFuncDesc *pFuncInfo;
6724 UINT fdc;
6726 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6727 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6730 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6731 return DISP_E_MEMBERNOTFOUND;
6733 if (!pDispParams)
6735 ERR("NULL pDispParams not allowed\n");
6736 return E_INVALIDARG;
6739 dump_DispParms(pDispParams);
6741 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6743 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6744 pDispParams->cNamedArgs, pDispParams->cArgs);
6745 return E_INVALIDARG;
6748 /* we do this instead of using GetFuncDesc since it will return a fake
6749 * FUNCDESC for dispinterfaces and we want the real function description */
6750 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6751 pFuncInfo = &This->funcdescs[fdc];
6752 if ((memid == pFuncInfo->funcdesc.memid) &&
6753 (wFlags & pFuncInfo->funcdesc.invkind) &&
6754 !func_restricted( &pFuncInfo->funcdesc ))
6755 break;
6758 if (fdc < This->cFuncs) {
6759 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6761 if (TRACE_ON(ole))
6763 TRACE("invoking:\n");
6764 dump_TLBFuncDescOne(pFuncInfo);
6767 switch (func_desc->funckind) {
6768 case FUNC_PUREVIRTUAL:
6769 case FUNC_VIRTUAL: {
6770 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6771 VARIANT varresult;
6772 VARIANT retval; /* pointer for storing byref retvals in */
6773 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6774 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6775 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6776 UINT cNamedArgs = pDispParams->cNamedArgs;
6777 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6778 UINT vargs_converted=0;
6780 hres = S_OK;
6782 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6784 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6786 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6787 hres = DISP_E_PARAMNOTFOUND;
6788 goto func_fail;
6792 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6794 ERR("functions with the vararg attribute do not support named arguments\n");
6795 hres = DISP_E_NONAMEDARGS;
6796 goto func_fail;
6799 for (i = 0; i < func_desc->cParams; i++)
6801 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6802 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6803 if (FAILED(hres))
6804 goto func_fail;
6807 TRACE("changing args\n");
6808 for (i = 0; i < func_desc->cParams; i++)
6810 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6811 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6812 VARIANTARG *src_arg;
6814 if (wParamFlags & PARAMFLAG_FLCID)
6816 VARIANTARG *arg;
6817 arg = prgpvarg[i] = &rgvarg[i];
6818 V_VT(arg) = VT_I4;
6819 V_I4(arg) = This->pTypeLib->lcid;
6820 continue;
6823 src_arg = NULL;
6825 if (cNamedArgs)
6827 USHORT j;
6828 for (j = 0; j < cNamedArgs; j++)
6829 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6831 src_arg = &pDispParams->rgvarg[j];
6832 break;
6836 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6838 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6839 vargs_converted++;
6842 if (wParamFlags & PARAMFLAG_FRETVAL)
6844 /* under most conditions the caller is not allowed to
6845 * pass in a dispparam arg in the index of what would be
6846 * the retval parameter. however, there is an exception
6847 * where the extra parameter is used in an extra
6848 * IDispatch::Invoke below */
6849 if ((i < pDispParams->cArgs) &&
6850 ((func_desc->cParams != 1) || !pVarResult ||
6851 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6853 hres = DISP_E_BADPARAMCOUNT;
6854 break;
6857 /* note: this check is placed so that if the caller passes
6858 * in a VARIANTARG for the retval we just ignore it, like
6859 * native does */
6860 if (i == func_desc->cParams - 1)
6862 VARIANTARG *arg;
6863 arg = prgpvarg[i] = &rgvarg[i];
6864 memset(arg, 0, sizeof(*arg));
6865 V_VT(arg) = rgvt[i];
6866 memset(&retval, 0, sizeof(retval));
6867 V_BYREF(arg) = &retval;
6869 else
6871 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6872 hres = E_UNEXPECTED;
6873 break;
6876 else if (src_arg)
6878 dump_Variant(src_arg);
6880 if(rgvt[i]!=V_VT(src_arg))
6882 if (rgvt[i] == VT_VARIANT)
6883 hres = VariantCopy(&rgvarg[i], src_arg);
6884 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6886 if (rgvt[i] == V_VT(src_arg))
6887 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6888 else
6890 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6891 if (wParamFlags & PARAMFLAG_FIN)
6892 hres = VariantCopy(&missing_arg[i], src_arg);
6893 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6895 V_VT(&rgvarg[i]) = rgvt[i];
6897 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6899 SAFEARRAY *a;
6900 SAFEARRAYBOUND bound;
6901 VARIANT *v;
6902 LONG j;
6903 bound.lLbound = 0;
6904 bound.cElements = pDispParams->cArgs-i;
6905 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6907 ERR("SafeArrayCreate failed\n");
6908 break;
6910 hres = SafeArrayAccessData(a, (LPVOID)&v);
6911 if (hres != S_OK)
6913 ERR("SafeArrayAccessData failed with %x\n", hres);
6914 SafeArrayDestroy(a);
6915 break;
6917 for (j = 0; j < bound.cElements; j++)
6918 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6919 hres = SafeArrayUnaccessData(a);
6920 if (hres != S_OK)
6922 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6923 SafeArrayDestroy(a);
6924 break;
6926 V_ARRAY(&rgvarg[i]) = a;
6927 V_VT(&rgvarg[i]) = rgvt[i];
6929 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6931 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6932 if (wParamFlags & PARAMFLAG_FIN)
6933 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6934 else
6935 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6936 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6937 V_VT(&rgvarg[i]) = rgvt[i];
6939 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6941 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6942 V_VT(&rgvarg[i]) = rgvt[i];
6944 else
6946 /* FIXME: this doesn't work for VT_BYREF arguments if
6947 * they are not the same type as in the paramdesc */
6948 V_VT(&rgvarg[i]) = V_VT(src_arg);
6949 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6950 V_VT(&rgvarg[i]) = rgvt[i];
6953 if (FAILED(hres))
6955 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6956 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6957 debugstr_VT(src_arg), debugstr_VF(src_arg));
6958 break;
6960 prgpvarg[i] = &rgvarg[i];
6962 else
6964 prgpvarg[i] = src_arg;
6967 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6968 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6969 && V_UNKNOWN(prgpvarg[i])) {
6970 IUnknown *userdefined_iface;
6971 GUID guid;
6973 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6974 if(FAILED(hres))
6975 break;
6977 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6978 if(FAILED(hres)) {
6979 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6980 break;
6983 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6984 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6987 else if (wParamFlags & PARAMFLAG_FOPT)
6989 VARIANTARG *arg;
6990 arg = prgpvarg[i] = &rgvarg[i];
6991 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6993 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6994 if (FAILED(hres))
6995 break;
6997 else
6999 VARIANTARG *missing_arg;
7000 /* if the function wants a pointer to a variant then
7001 * set that up, otherwise just pass the VT_ERROR in
7002 * the argument by value */
7003 if (rgvt[i] & VT_BYREF)
7005 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7006 V_VT(arg) = VT_VARIANT | VT_BYREF;
7007 V_VARIANTREF(arg) = missing_arg;
7009 else
7010 missing_arg = arg;
7011 V_VT(missing_arg) = VT_ERROR;
7012 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7015 else
7017 hres = DISP_E_BADPARAMCOUNT;
7018 break;
7021 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7023 /* VT_VOID is a special case for return types, so it is not
7024 * handled in the general function */
7025 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7026 V_VT(&varresult) = VT_EMPTY;
7027 else
7029 V_VT(&varresult) = 0;
7030 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7031 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7034 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7035 V_VT(&varresult), func_desc->cParams, rgvt,
7036 prgpvarg, &varresult);
7038 vargs_converted = 0;
7040 for (i = 0; i < func_desc->cParams; i++)
7042 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7043 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7045 if (wParamFlags & PARAMFLAG_FLCID)
7046 continue;
7047 else if (wParamFlags & PARAMFLAG_FRETVAL)
7049 if (TRACE_ON(ole))
7051 TRACE("[retval] value: ");
7052 dump_Variant(prgpvarg[i]);
7055 if (pVarResult)
7057 VariantInit(pVarResult);
7058 /* deref return value */
7059 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7062 VARIANT_ClearInd(prgpvarg[i]);
7064 else if (vargs_converted < pDispParams->cArgs)
7066 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7067 if (wParamFlags & PARAMFLAG_FOUT)
7069 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7071 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7073 if (FAILED(hres))
7075 ERR("failed to convert param %d to vt %d\n", i,
7076 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7077 break;
7081 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7082 func_desc->cParamsOpt < 0 &&
7083 i == func_desc->cParams-1)
7085 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7086 LONG j, ubound;
7087 VARIANT *v;
7088 hres = SafeArrayGetUBound(a, 1, &ubound);
7089 if (hres != S_OK)
7091 ERR("SafeArrayGetUBound failed with %x\n", hres);
7092 break;
7094 hres = SafeArrayAccessData(a, (LPVOID)&v);
7095 if (hres != S_OK)
7097 ERR("SafeArrayAccessData failed with %x\n", hres);
7098 break;
7100 for (j = 0; j <= ubound; j++)
7101 VariantClear(&v[j]);
7102 hres = SafeArrayUnaccessData(a);
7103 if (hres != S_OK)
7105 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7106 break;
7109 VariantClear(&rgvarg[i]);
7110 vargs_converted++;
7112 else if (wParamFlags & PARAMFLAG_FOPT)
7114 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7115 VariantClear(&rgvarg[i]);
7118 VariantClear(&missing_arg[i]);
7121 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7123 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7124 hres = DISP_E_EXCEPTION;
7125 if (pExcepInfo)
7127 IErrorInfo *pErrorInfo;
7128 pExcepInfo->scode = V_ERROR(&varresult);
7129 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7131 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7132 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7133 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7134 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7136 IErrorInfo_Release(pErrorInfo);
7140 if (V_VT(&varresult) != VT_ERROR)
7142 TRACE("varresult value: ");
7143 dump_Variant(&varresult);
7145 if (pVarResult)
7147 VariantClear(pVarResult);
7148 *pVarResult = varresult;
7150 else
7151 VariantClear(&varresult);
7154 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7155 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7156 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7157 (pDispParams->cArgs != 0))
7159 if (V_VT(pVarResult) == VT_DISPATCH)
7161 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7162 /* Note: not VariantClear; we still need the dispatch
7163 * pointer to be valid */
7164 VariantInit(pVarResult);
7165 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7166 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7167 pDispParams, pVarResult, pExcepInfo, pArgErr);
7168 IDispatch_Release(pDispatch);
7170 else
7172 VariantClear(pVarResult);
7173 hres = DISP_E_NOTACOLLECTION;
7177 func_fail:
7178 heap_free(buffer);
7179 break;
7181 case FUNC_DISPATCH: {
7182 IDispatch *disp;
7184 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7185 if (SUCCEEDED(hres)) {
7186 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7187 hres = IDispatch_Invoke(
7188 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7189 pVarResult,pExcepInfo,pArgErr
7191 if (FAILED(hres))
7192 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7193 IDispatch_Release(disp);
7194 } else
7195 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7196 break;
7198 default:
7199 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7200 hres = E_FAIL;
7201 break;
7204 TRACE("-- 0x%08x\n", hres);
7205 return hres;
7207 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7208 VARDESC *var_desc;
7210 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7211 if(FAILED(hres)) return hres;
7213 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7214 dump_VARDESC(var_desc);
7215 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7216 return E_NOTIMPL;
7219 /* not found, look for it in inherited interfaces */
7220 ITypeInfo2_GetTypeKind(iface, &type_kind);
7221 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7222 if(This->impltypes) {
7223 /* recursive search */
7224 ITypeInfo *pTInfo;
7225 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7226 if(SUCCEEDED(hres)){
7227 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7228 ITypeInfo_Release(pTInfo);
7229 return hres;
7231 WARN("Could not search inherited interface!\n");
7234 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7235 return DISP_E_MEMBERNOTFOUND;
7238 /* ITypeInfo::GetDocumentation
7240 * Retrieves the documentation string, the complete Help file name and path,
7241 * and the context ID for the Help topic for a specified type description.
7243 * (Can be tested by the Visual Basic Editor in Word for instance.)
7245 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7246 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7247 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7249 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7250 const TLBFuncDesc *pFDesc;
7251 const TLBVarDesc *pVDesc;
7252 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7253 " HelpContext(%p) HelpFile(%p)\n",
7254 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7255 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7256 if(pBstrName)
7257 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7258 if(pBstrDocString)
7259 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7260 if(pdwHelpContext)
7261 *pdwHelpContext=This->dwHelpContext;
7262 if(pBstrHelpFile)
7263 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7264 return S_OK;
7265 }else {/* for a member */
7266 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7267 if(pFDesc){
7268 if(pBstrName)
7269 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7270 if(pBstrDocString)
7271 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7272 if(pdwHelpContext)
7273 *pdwHelpContext=pFDesc->helpcontext;
7274 if(pBstrHelpFile)
7275 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7276 return S_OK;
7278 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7279 if(pVDesc){
7280 if(pBstrName)
7281 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7282 if(pBstrDocString)
7283 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7284 if(pdwHelpContext)
7285 *pdwHelpContext=pVDesc->HelpContext;
7286 if(pBstrHelpFile)
7287 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7288 return S_OK;
7292 if(This->impltypes &&
7293 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7294 /* recursive search */
7295 ITypeInfo *pTInfo;
7296 HRESULT result;
7297 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7298 if(SUCCEEDED(result)) {
7299 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7300 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7301 ITypeInfo_Release(pTInfo);
7302 return result;
7304 WARN("Could not search inherited interface!\n");
7307 WARN("member %d not found\n", memid);
7308 return TYPE_E_ELEMENTNOTFOUND;
7311 /* ITypeInfo::GetDllEntry
7313 * Retrieves a description or specification of an entry point for a function
7314 * in a DLL.
7316 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7317 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7318 WORD *pwOrdinal)
7320 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7321 const TLBFuncDesc *pFDesc;
7323 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7325 if (pBstrDllName) *pBstrDllName = NULL;
7326 if (pBstrName) *pBstrName = NULL;
7327 if (pwOrdinal) *pwOrdinal = 0;
7329 if (This->typekind != TKIND_MODULE)
7330 return TYPE_E_BADMODULEKIND;
7332 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7333 if(pFDesc){
7334 dump_TypeInfo(This);
7335 if (TRACE_ON(ole))
7336 dump_TLBFuncDescOne(pFDesc);
7338 if (pBstrDllName)
7339 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7341 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7342 if (pBstrName)
7343 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7344 if (pwOrdinal)
7345 *pwOrdinal = -1;
7346 return S_OK;
7348 if (pBstrName)
7349 *pBstrName = NULL;
7350 if (pwOrdinal)
7351 *pwOrdinal = LOWORD(pFDesc->Entry);
7352 return S_OK;
7354 return TYPE_E_ELEMENTNOTFOUND;
7357 /* internal function to make the inherited interfaces' methods appear
7358 * part of the interface */
7359 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7360 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7362 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7363 HRESULT hr;
7365 TRACE("%p, 0x%x\n", iface, *hRefType);
7367 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7369 ITypeInfo *pSubTypeInfo;
7371 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7372 if (FAILED(hr))
7373 return hr;
7375 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7376 hRefType, ppTInfo);
7377 ITypeInfo_Release(pSubTypeInfo);
7378 if (SUCCEEDED(hr))
7379 return hr;
7381 *hRefType -= DISPATCH_HREF_OFFSET;
7383 if (!(*hRefType & DISPATCH_HREF_MASK))
7384 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7385 else
7386 return E_FAIL;
7389 /* ITypeInfo::GetRefTypeInfo
7391 * If a type description references other type descriptions, it retrieves
7392 * the referenced type descriptions.
7394 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7395 ITypeInfo2 *iface,
7396 HREFTYPE hRefType,
7397 ITypeInfo **ppTInfo)
7399 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7400 HRESULT result = E_FAIL;
7402 if(!ppTInfo)
7403 return E_INVALIDARG;
7405 if ((INT)hRefType < 0) {
7406 ITypeInfoImpl *pTypeInfoImpl;
7408 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7409 !(This->typekind == TKIND_INTERFACE ||
7410 This->typekind == TKIND_DISPATCH))
7411 return TYPE_E_ELEMENTNOTFOUND;
7413 /* when we meet a DUAL typeinfo, we must create the alternate
7414 * version of it.
7416 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7418 *pTypeInfoImpl = *This;
7419 pTypeInfoImpl->ref = 0;
7420 list_init(&pTypeInfoImpl->custdata_list);
7422 if (This->typekind == TKIND_INTERFACE)
7423 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7424 else
7425 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7427 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7428 /* the AddRef implicitly adds a reference to the parent typelib, which
7429 * stops the copied data from being destroyed until the new typeinfo's
7430 * refcount goes to zero, but we need to signal to the new instance to
7431 * not free its data structures when it is destroyed */
7432 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7434 ITypeInfo_AddRef(*ppTInfo);
7436 result = S_OK;
7437 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7438 (This->typekind == TKIND_DISPATCH))
7440 HREFTYPE href_dispatch = hRefType;
7441 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7442 } else {
7443 TLBRefType *ref_type;
7444 ITypeLib *pTLib = NULL;
7445 UINT i;
7447 if(!(hRefType & 0x1)){
7448 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7450 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7452 result = S_OK;
7453 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7454 ITypeInfo_AddRef(*ppTInfo);
7455 goto end;
7460 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7462 if(ref_type->reference == (hRefType & (~0x3)))
7463 break;
7465 if(&ref_type->entry == &This->pTypeLib->ref_list)
7467 FIXME("Can't find pRefType for ref %x\n", hRefType);
7468 goto end;
7471 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7472 UINT Index;
7473 TRACE("internal reference\n");
7474 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7475 } else {
7476 if(ref_type->pImpTLInfo->pImpTypeLib) {
7477 TRACE("typeinfo in imported typelib that is already loaded\n");
7478 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7479 ITypeLib_AddRef(pTLib);
7480 result = S_OK;
7481 } else {
7482 BSTR libnam;
7484 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7486 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7487 ref_type->pImpTLInfo->wVersionMajor,
7488 ref_type->pImpTLInfo->wVersionMinor,
7489 This->pTypeLib->syskind,
7490 ref_type->pImpTLInfo->lcid, &libnam);
7491 if(FAILED(result))
7492 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7494 result = LoadTypeLib(libnam, &pTLib);
7495 SysFreeString(libnam);
7497 if(SUCCEEDED(result)) {
7498 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7499 ITypeLib_AddRef(pTLib);
7503 if(SUCCEEDED(result)) {
7504 if(ref_type->index == TLB_REF_USE_GUID)
7505 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7506 else
7507 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7509 if (pTLib != NULL)
7510 ITypeLib_Release(pTLib);
7513 end:
7514 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7515 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7516 return result;
7519 /* ITypeInfo::AddressOfMember
7521 * Retrieves the addresses of static functions or variables, such as those
7522 * defined in a DLL.
7524 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7525 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7527 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7528 HRESULT hr;
7529 BSTR dll, entry;
7530 WORD ordinal;
7531 HMODULE module;
7533 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7535 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7536 if (FAILED(hr))
7537 return hr;
7539 module = LoadLibraryW(dll);
7540 if (!module)
7542 ERR("couldn't load %s\n", debugstr_w(dll));
7543 SysFreeString(dll);
7544 SysFreeString(entry);
7545 return STG_E_FILENOTFOUND;
7547 /* FIXME: store library somewhere where we can free it */
7549 if (entry)
7551 LPSTR entryA;
7552 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7553 entryA = heap_alloc(len);
7554 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7556 *ppv = GetProcAddress(module, entryA);
7557 if (!*ppv)
7558 ERR("function not found %s\n", debugstr_a(entryA));
7560 heap_free(entryA);
7562 else
7564 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7565 if (!*ppv)
7566 ERR("function not found %d\n", ordinal);
7569 SysFreeString(dll);
7570 SysFreeString(entry);
7572 if (!*ppv)
7573 return TYPE_E_DLLFUNCTIONNOTFOUND;
7575 return S_OK;
7578 /* ITypeInfo::CreateInstance
7580 * Creates a new instance of a type that describes a component object class
7581 * (coclass).
7583 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7584 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7586 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7587 HRESULT hr;
7588 TYPEATTR *pTA;
7590 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7592 *ppvObj = NULL;
7594 if(pOuterUnk)
7596 WARN("Not able to aggregate\n");
7597 return CLASS_E_NOAGGREGATION;
7600 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7601 if(FAILED(hr)) return hr;
7603 if(pTA->typekind != TKIND_COCLASS)
7605 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7606 hr = E_INVALIDARG;
7607 goto end;
7610 hr = S_FALSE;
7611 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7613 IUnknown *pUnk;
7614 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7615 TRACE("GetActiveObject rets %08x\n", hr);
7616 if(hr == S_OK)
7618 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7619 IUnknown_Release(pUnk);
7623 if(hr != S_OK)
7624 hr = CoCreateInstance(&pTA->guid, NULL,
7625 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7626 riid, ppvObj);
7628 end:
7629 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7630 return hr;
7633 /* ITypeInfo::GetMops
7635 * Retrieves marshalling information.
7637 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7638 BSTR *pBstrMops)
7640 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7641 FIXME("(%p %d) stub!\n", This, memid);
7642 *pBstrMops = NULL;
7643 return S_OK;
7646 /* ITypeInfo::GetContainingTypeLib
7648 * Retrieves the containing type library and the index of the type description
7649 * within that type library.
7651 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7652 ITypeLib * *ppTLib, UINT *pIndex)
7654 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7656 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7657 if (pIndex) {
7658 *pIndex=This->index;
7659 TRACE("returning pIndex=%d\n", *pIndex);
7662 if (ppTLib) {
7663 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7664 ITypeLib_AddRef(*ppTLib);
7665 TRACE("returning ppTLib=%p\n", *ppTLib);
7668 return S_OK;
7671 /* ITypeInfo::ReleaseTypeAttr
7673 * Releases a TYPEATTR previously returned by Get
7676 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7677 TYPEATTR* pTypeAttr)
7679 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7680 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7681 heap_free(pTypeAttr);
7684 /* ITypeInfo::ReleaseFuncDesc
7686 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7688 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7689 ITypeInfo2 *iface,
7690 FUNCDESC *pFuncDesc)
7692 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7693 SHORT i;
7695 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7697 for (i = 0; i < pFuncDesc->cParams; i++)
7698 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7699 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7701 SysFreeString((BSTR)pFuncDesc);
7704 /* ITypeInfo::ReleaseVarDesc
7706 * Releases a VARDESC previously returned by GetVarDesc.
7708 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7709 VARDESC *pVarDesc)
7711 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7712 TRACE("(%p)->(%p)\n", This, pVarDesc);
7714 TLB_FreeVarDesc(pVarDesc);
7717 /* ITypeInfo2::GetTypeKind
7719 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7722 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7723 TYPEKIND *pTypeKind)
7725 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7726 *pTypeKind=This->typekind;
7727 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7728 return S_OK;
7731 /* ITypeInfo2::GetTypeFlags
7733 * Returns the type flags without any allocations. This returns a DWORD type
7734 * flag, which expands the type flags without growing the TYPEATTR (type
7735 * attribute).
7738 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7740 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7741 *pTypeFlags=This->wTypeFlags;
7742 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7743 return S_OK;
7746 /* ITypeInfo2::GetFuncIndexOfMemId
7747 * Binds to a specific member based on a known DISPID, where the member name
7748 * is not known (for example, when binding to a default member).
7751 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7752 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7754 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7755 UINT fdc;
7756 HRESULT result;
7758 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7759 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7760 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7761 break;
7763 if(fdc < This->cFuncs) {
7764 *pFuncIndex = fdc;
7765 result = S_OK;
7766 } else
7767 result = TYPE_E_ELEMENTNOTFOUND;
7769 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7770 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7771 return result;
7774 /* TypeInfo2::GetVarIndexOfMemId
7776 * Binds to a specific member based on a known DISPID, where the member name
7777 * is not known (for example, when binding to a default member).
7780 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7781 MEMBERID memid, UINT *pVarIndex)
7783 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7784 TLBVarDesc *pVarInfo;
7786 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7788 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7789 if(!pVarInfo)
7790 return TYPE_E_ELEMENTNOTFOUND;
7792 *pVarIndex = (pVarInfo - This->vardescs);
7794 return S_OK;
7797 /* ITypeInfo2::GetCustData
7799 * Gets the custom data
7801 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7802 ITypeInfo2 * iface,
7803 REFGUID guid,
7804 VARIANT *pVarVal)
7806 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7807 TLBCustData *pCData;
7809 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7811 if(!guid || !pVarVal)
7812 return E_INVALIDARG;
7814 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
7816 VariantInit( pVarVal);
7817 if (pCData)
7818 VariantCopy( pVarVal, &pCData->data);
7819 else
7820 VariantClear( pVarVal );
7821 return S_OK;
7824 /* ITypeInfo2::GetFuncCustData
7826 * Gets the custom data
7828 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7829 ITypeInfo2 * iface,
7830 UINT index,
7831 REFGUID guid,
7832 VARIANT *pVarVal)
7834 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7835 TLBCustData *pCData;
7836 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7838 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7840 if(index >= This->cFuncs)
7841 return TYPE_E_ELEMENTNOTFOUND;
7843 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7844 if(!pCData)
7845 return TYPE_E_ELEMENTNOTFOUND;
7847 VariantInit(pVarVal);
7848 VariantCopy(pVarVal, &pCData->data);
7850 return S_OK;
7853 /* ITypeInfo2::GetParamCustData
7855 * Gets the custom data
7857 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7858 ITypeInfo2 * iface,
7859 UINT indexFunc,
7860 UINT indexParam,
7861 REFGUID guid,
7862 VARIANT *pVarVal)
7864 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7865 TLBCustData *pCData;
7866 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7868 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7869 debugstr_guid(guid), pVarVal);
7871 if(indexFunc >= This->cFuncs)
7872 return TYPE_E_ELEMENTNOTFOUND;
7874 if(indexParam >= pFDesc->funcdesc.cParams)
7875 return TYPE_E_ELEMENTNOTFOUND;
7877 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7878 if(!pCData)
7879 return TYPE_E_ELEMENTNOTFOUND;
7881 VariantInit(pVarVal);
7882 VariantCopy(pVarVal, &pCData->data);
7884 return S_OK;
7887 /* ITypeInfo2::GetVarCustData
7889 * Gets the custom data
7891 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7892 ITypeInfo2 * iface,
7893 UINT index,
7894 REFGUID guid,
7895 VARIANT *pVarVal)
7897 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7898 TLBCustData *pCData;
7899 TLBVarDesc *pVDesc = &This->vardescs[index];
7901 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7903 if(index >= This->cVars)
7904 return TYPE_E_ELEMENTNOTFOUND;
7906 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7907 if(!pCData)
7908 return TYPE_E_ELEMENTNOTFOUND;
7910 VariantInit(pVarVal);
7911 VariantCopy(pVarVal, &pCData->data);
7913 return S_OK;
7916 /* ITypeInfo2::GetImplCustData
7918 * Gets the custom data
7920 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7921 ITypeInfo2 * iface,
7922 UINT index,
7923 REFGUID guid,
7924 VARIANT *pVarVal)
7926 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7927 TLBCustData *pCData;
7928 TLBImplType *pRDesc = &This->impltypes[index];
7930 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7932 if(index >= This->cImplTypes)
7933 return TYPE_E_ELEMENTNOTFOUND;
7935 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7936 if(!pCData)
7937 return TYPE_E_ELEMENTNOTFOUND;
7939 VariantInit(pVarVal);
7940 VariantCopy(pVarVal, &pCData->data);
7942 return S_OK;
7945 /* ITypeInfo2::GetDocumentation2
7947 * Retrieves the documentation string, the complete Help file name and path,
7948 * the localization context to use, and the context ID for the library Help
7949 * topic in the Help file.
7952 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7953 ITypeInfo2 * iface,
7954 MEMBERID memid,
7955 LCID lcid,
7956 BSTR *pbstrHelpString,
7957 DWORD *pdwHelpStringContext,
7958 BSTR *pbstrHelpStringDll)
7960 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7961 const TLBFuncDesc *pFDesc;
7962 const TLBVarDesc *pVDesc;
7963 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7964 "HelpStringContext(%p) HelpStringDll(%p)\n",
7965 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7966 pbstrHelpStringDll );
7967 /* the help string should be obtained from the helpstringdll,
7968 * using the _DLLGetDocumentation function, based on the supplied
7969 * lcid. Nice to do sometime...
7971 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7972 if(pbstrHelpString)
7973 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
7974 if(pdwHelpStringContext)
7975 *pdwHelpStringContext=This->dwHelpStringContext;
7976 if(pbstrHelpStringDll)
7977 *pbstrHelpStringDll=
7978 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7979 return S_OK;
7980 }else {/* for a member */
7981 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7982 if(pFDesc){
7983 if(pbstrHelpString)
7984 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7985 if(pdwHelpStringContext)
7986 *pdwHelpStringContext=pFDesc->HelpStringContext;
7987 if(pbstrHelpStringDll)
7988 *pbstrHelpStringDll=
7989 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7990 return S_OK;
7992 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7993 if(pVDesc){
7994 if(pbstrHelpString)
7995 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7996 if(pdwHelpStringContext)
7997 *pdwHelpStringContext=pVDesc->HelpStringContext;
7998 if(pbstrHelpStringDll)
7999 *pbstrHelpStringDll=
8000 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8001 return S_OK;
8004 return TYPE_E_ELEMENTNOTFOUND;
8007 /* ITypeInfo2::GetAllCustData
8009 * Gets all custom data items for the Type info.
8012 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8013 ITypeInfo2 * iface,
8014 CUSTDATA *pCustData)
8016 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8018 TRACE("%p %p\n", This, pCustData);
8020 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8023 /* ITypeInfo2::GetAllFuncCustData
8025 * Gets all custom data items for the specified Function
8028 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8029 ITypeInfo2 * iface,
8030 UINT index,
8031 CUSTDATA *pCustData)
8033 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8034 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8036 TRACE("%p %u %p\n", This, index, pCustData);
8038 if(index >= This->cFuncs)
8039 return TYPE_E_ELEMENTNOTFOUND;
8041 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8044 /* ITypeInfo2::GetAllParamCustData
8046 * Gets all custom data items for the Functions
8049 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8050 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8052 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8053 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8055 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8057 if(indexFunc >= This->cFuncs)
8058 return TYPE_E_ELEMENTNOTFOUND;
8060 if(indexParam >= pFDesc->funcdesc.cParams)
8061 return TYPE_E_ELEMENTNOTFOUND;
8063 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8066 /* ITypeInfo2::GetAllVarCustData
8068 * Gets all custom data items for the specified Variable
8071 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8072 UINT index, CUSTDATA *pCustData)
8074 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8075 TLBVarDesc * pVDesc = &This->vardescs[index];
8077 TRACE("%p %u %p\n", This, index, pCustData);
8079 if(index >= This->cVars)
8080 return TYPE_E_ELEMENTNOTFOUND;
8082 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8085 /* ITypeInfo2::GetAllImplCustData
8087 * Gets all custom data items for the specified implementation type
8090 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8091 ITypeInfo2 * iface,
8092 UINT index,
8093 CUSTDATA *pCustData)
8095 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8096 TLBImplType *pRDesc = &This->impltypes[index];
8098 TRACE("%p %u %p\n", This, index, pCustData);
8100 if(index >= This->cImplTypes)
8101 return TYPE_E_ELEMENTNOTFOUND;
8103 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8106 static const ITypeInfo2Vtbl tinfvt =
8109 ITypeInfo_fnQueryInterface,
8110 ITypeInfo_fnAddRef,
8111 ITypeInfo_fnRelease,
8113 ITypeInfo_fnGetTypeAttr,
8114 ITypeInfo_fnGetTypeComp,
8115 ITypeInfo_fnGetFuncDesc,
8116 ITypeInfo_fnGetVarDesc,
8117 ITypeInfo_fnGetNames,
8118 ITypeInfo_fnGetRefTypeOfImplType,
8119 ITypeInfo_fnGetImplTypeFlags,
8120 ITypeInfo_fnGetIDsOfNames,
8121 ITypeInfo_fnInvoke,
8122 ITypeInfo_fnGetDocumentation,
8123 ITypeInfo_fnGetDllEntry,
8124 ITypeInfo_fnGetRefTypeInfo,
8125 ITypeInfo_fnAddressOfMember,
8126 ITypeInfo_fnCreateInstance,
8127 ITypeInfo_fnGetMops,
8128 ITypeInfo_fnGetContainingTypeLib,
8129 ITypeInfo_fnReleaseTypeAttr,
8130 ITypeInfo_fnReleaseFuncDesc,
8131 ITypeInfo_fnReleaseVarDesc,
8133 ITypeInfo2_fnGetTypeKind,
8134 ITypeInfo2_fnGetTypeFlags,
8135 ITypeInfo2_fnGetFuncIndexOfMemId,
8136 ITypeInfo2_fnGetVarIndexOfMemId,
8137 ITypeInfo2_fnGetCustData,
8138 ITypeInfo2_fnGetFuncCustData,
8139 ITypeInfo2_fnGetParamCustData,
8140 ITypeInfo2_fnGetVarCustData,
8141 ITypeInfo2_fnGetImplTypeCustData,
8142 ITypeInfo2_fnGetDocumentation2,
8143 ITypeInfo2_fnGetAllCustData,
8144 ITypeInfo2_fnGetAllFuncCustData,
8145 ITypeInfo2_fnGetAllParamCustData,
8146 ITypeInfo2_fnGetAllVarCustData,
8147 ITypeInfo2_fnGetAllImplTypeCustData,
8150 /******************************************************************************
8151 * CreateDispTypeInfo [OLEAUT32.31]
8153 * Build type information for an object so it can be called through an
8154 * IDispatch interface.
8156 * RETURNS
8157 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8158 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8160 * NOTES
8161 * This call allows an objects methods to be accessed through IDispatch, by
8162 * building an ITypeInfo object that IDispatch can use to call through.
8164 HRESULT WINAPI CreateDispTypeInfo(
8165 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8166 LCID lcid, /* [I] Locale Id */
8167 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8169 ITypeInfoImpl *pTIClass, *pTIIface;
8170 ITypeLibImpl *pTypeLibImpl;
8171 unsigned int param, func;
8172 TLBFuncDesc *pFuncDesc;
8173 TLBRefType *ref;
8175 TRACE("\n");
8176 pTypeLibImpl = TypeLibImpl_Constructor();
8177 if (!pTypeLibImpl) return E_FAIL;
8179 pTypeLibImpl->TypeInfoCount = 2;
8180 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8182 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8183 pTIIface->pTypeLib = pTypeLibImpl;
8184 pTIIface->index = 0;
8185 pTIIface->Name = NULL;
8186 pTIIface->dwHelpContext = -1;
8187 pTIIface->guid = NULL;
8188 pTIIface->lcid = lcid;
8189 pTIIface->typekind = TKIND_INTERFACE;
8190 pTIIface->wMajorVerNum = 0;
8191 pTIIface->wMinorVerNum = 0;
8192 pTIIface->cbAlignment = 2;
8193 pTIIface->cbSizeInstance = -1;
8194 pTIIface->cbSizeVft = -1;
8195 pTIIface->cFuncs = 0;
8196 pTIIface->cImplTypes = 0;
8197 pTIIface->cVars = 0;
8198 pTIIface->wTypeFlags = 0;
8199 pTIIface->hreftype = 0;
8201 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8202 pFuncDesc = pTIIface->funcdescs;
8203 for(func = 0; func < pidata->cMembers; func++) {
8204 METHODDATA *md = pidata->pmethdata + func;
8205 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8206 pFuncDesc->funcdesc.memid = md->dispid;
8207 pFuncDesc->funcdesc.lprgscode = NULL;
8208 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8209 pFuncDesc->funcdesc.invkind = md->wFlags;
8210 pFuncDesc->funcdesc.callconv = md->cc;
8211 pFuncDesc->funcdesc.cParams = md->cArgs;
8212 pFuncDesc->funcdesc.cParamsOpt = 0;
8213 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8214 pFuncDesc->funcdesc.cScodes = 0;
8215 pFuncDesc->funcdesc.wFuncFlags = 0;
8216 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8217 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8218 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8219 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8220 md->cArgs * sizeof(ELEMDESC));
8221 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8222 for(param = 0; param < md->cArgs; param++) {
8223 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8224 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8226 pFuncDesc->helpcontext = 0;
8227 pFuncDesc->HelpStringContext = 0;
8228 pFuncDesc->HelpString = NULL;
8229 pFuncDesc->Entry = NULL;
8230 list_init(&pFuncDesc->custdata_list);
8231 pTIIface->cFuncs++;
8232 ++pFuncDesc;
8235 dump_TypeInfo(pTIIface);
8237 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8238 pTIClass->pTypeLib = pTypeLibImpl;
8239 pTIClass->index = 1;
8240 pTIClass->Name = NULL;
8241 pTIClass->dwHelpContext = -1;
8242 pTIClass->guid = NULL;
8243 pTIClass->lcid = lcid;
8244 pTIClass->typekind = TKIND_COCLASS;
8245 pTIClass->wMajorVerNum = 0;
8246 pTIClass->wMinorVerNum = 0;
8247 pTIClass->cbAlignment = 2;
8248 pTIClass->cbSizeInstance = -1;
8249 pTIClass->cbSizeVft = -1;
8250 pTIClass->cFuncs = 0;
8251 pTIClass->cImplTypes = 1;
8252 pTIClass->cVars = 0;
8253 pTIClass->wTypeFlags = 0;
8254 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8256 pTIClass->impltypes = TLBImplType_Alloc(1);
8258 ref = heap_alloc_zero(sizeof(*ref));
8259 ref->pImpTLInfo = TLB_REF_INTERNAL;
8260 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8262 dump_TypeInfo(pTIClass);
8264 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8266 ITypeInfo_AddRef(*pptinfo);
8267 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8269 return S_OK;
8273 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8275 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8277 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8280 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8282 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8284 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8287 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8289 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8291 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8294 static HRESULT WINAPI ITypeComp_fnBind(
8295 ITypeComp * iface,
8296 OLECHAR * szName,
8297 ULONG lHash,
8298 WORD wFlags,
8299 ITypeInfo ** ppTInfo,
8300 DESCKIND * pDescKind,
8301 BINDPTR * pBindPtr)
8303 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8304 const TLBFuncDesc *pFDesc;
8305 const TLBVarDesc *pVDesc;
8306 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8307 UINT fdc;
8309 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8311 *pDescKind = DESCKIND_NONE;
8312 pBindPtr->lpfuncdesc = NULL;
8313 *ppTInfo = NULL;
8315 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8316 pFDesc = &This->funcdescs[fdc];
8317 if (!strcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8318 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8319 break;
8320 else
8321 /* name found, but wrong flags */
8322 hr = TYPE_E_TYPEMISMATCH;
8326 if (fdc < This->cFuncs)
8328 HRESULT hr = TLB_AllocAndInitFuncDesc(
8329 &pFDesc->funcdesc,
8330 &pBindPtr->lpfuncdesc,
8331 This->typekind == TKIND_DISPATCH);
8332 if (FAILED(hr))
8333 return hr;
8334 *pDescKind = DESCKIND_FUNCDESC;
8335 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8336 ITypeInfo_AddRef(*ppTInfo);
8337 return S_OK;
8338 } else {
8339 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8340 if(pVDesc){
8341 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8342 if (FAILED(hr))
8343 return hr;
8344 *pDescKind = DESCKIND_VARDESC;
8345 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8346 ITypeInfo_AddRef(*ppTInfo);
8347 return S_OK;
8350 /* FIXME: search each inherited interface, not just the first */
8351 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8352 /* recursive search */
8353 ITypeInfo *pTInfo;
8354 ITypeComp *pTComp;
8355 HRESULT hr;
8356 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8357 if (SUCCEEDED(hr))
8359 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8360 ITypeInfo_Release(pTInfo);
8362 if (SUCCEEDED(hr))
8364 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8365 ITypeComp_Release(pTComp);
8366 return hr;
8368 WARN("Could not search inherited interface!\n");
8370 if (hr == DISP_E_MEMBERNOTFOUND)
8371 hr = S_OK;
8372 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8373 return hr;
8376 static HRESULT WINAPI ITypeComp_fnBindType(
8377 ITypeComp * iface,
8378 OLECHAR * szName,
8379 ULONG lHash,
8380 ITypeInfo ** ppTInfo,
8381 ITypeComp ** ppTComp)
8383 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8385 /* strange behaviour (does nothing) but like the
8386 * original */
8388 if (!ppTInfo || !ppTComp)
8389 return E_POINTER;
8391 *ppTInfo = NULL;
8392 *ppTComp = NULL;
8394 return S_OK;
8397 static const ITypeCompVtbl tcompvt =
8400 ITypeComp_fnQueryInterface,
8401 ITypeComp_fnAddRef,
8402 ITypeComp_fnRelease,
8404 ITypeComp_fnBind,
8405 ITypeComp_fnBindType
8408 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8409 ICreateTypeLib2** ppctlib)
8411 ITypeLibImpl *This;
8412 HRESULT hres;
8414 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8416 if (!szFile) return E_INVALIDARG;
8418 This = TypeLibImpl_Constructor();
8419 if (!This)
8420 return E_OUTOFMEMORY;
8422 This->lcid = GetSystemDefaultLCID();
8423 This->syskind = syskind;
8424 This->ptr_size = get_ptr_size(syskind);
8426 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8427 if (!This->path) {
8428 ITypeLib2_Release(&This->ITypeLib2_iface);
8429 return E_OUTOFMEMORY;
8431 lstrcpyW(This->path, szFile);
8433 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8434 ITypeLib2_Release(&This->ITypeLib2_iface);
8435 return hres;
8438 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8439 REFIID riid, void **object)
8441 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8443 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8446 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8448 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8450 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8453 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8455 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8457 return ITypeLib2_Release(&This->ITypeLib2_iface);
8460 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8461 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8463 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8464 ITypeInfoImpl *info;
8465 HRESULT hres;
8467 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8469 if (!ctinfo || !name)
8470 return E_INVALIDARG;
8472 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8473 if (info)
8474 return TYPE_E_NAMECONFLICT;
8476 if (This->typeinfos)
8477 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8478 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8479 else
8480 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8482 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8484 info->pTypeLib = This;
8485 info->Name = TLB_append_str(&This->name_list, name);
8486 info->index = This->TypeInfoCount;
8487 info->typekind = kind;
8488 info->cbAlignment = 4;
8490 switch(info->typekind) {
8491 case TKIND_ENUM:
8492 case TKIND_INTERFACE:
8493 case TKIND_DISPATCH:
8494 case TKIND_COCLASS:
8495 info->cbSizeInstance = This->ptr_size;
8496 break;
8497 case TKIND_RECORD:
8498 case TKIND_UNION:
8499 info->cbSizeInstance = 0;
8500 break;
8501 case TKIND_MODULE:
8502 info->cbSizeInstance = 2;
8503 break;
8504 case TKIND_ALIAS:
8505 info->cbSizeInstance = -0x75;
8506 break;
8507 default:
8508 FIXME("unrecognized typekind %d\n", info->typekind);
8509 info->cbSizeInstance = 0xdeadbeef;
8510 break;
8513 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8514 &IID_ICreateTypeInfo, (void **)ctinfo);
8515 if (FAILED(hres)) {
8516 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8517 return hres;
8520 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8522 ++This->TypeInfoCount;
8524 return S_OK;
8527 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8528 LPOLESTR name)
8530 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8532 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8534 if (!name)
8535 return E_INVALIDARG;
8537 This->Name = TLB_append_str(&This->name_list, name);
8539 return S_OK;
8542 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8543 WORD majorVerNum, WORD minorVerNum)
8545 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8547 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8549 This->ver_major = majorVerNum;
8550 This->ver_minor = minorVerNum;
8552 return S_OK;
8555 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8556 REFGUID guid)
8558 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8560 TRACE("%p %s\n", This, debugstr_guid(guid));
8562 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8564 return S_OK;
8567 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8568 LPOLESTR doc)
8570 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8572 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8574 if (!doc)
8575 return E_INVALIDARG;
8577 This->DocString = TLB_append_str(&This->string_list, doc);
8579 return S_OK;
8582 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8583 LPOLESTR helpFileName)
8585 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8587 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8589 if (!helpFileName)
8590 return E_INVALIDARG;
8592 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8594 return S_OK;
8597 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8598 DWORD helpContext)
8600 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8602 TRACE("%p %d\n", This, helpContext);
8604 This->dwHelpContext = helpContext;
8606 return S_OK;
8609 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8610 LCID lcid)
8612 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8614 TRACE("%p %x\n", This, lcid);
8616 This->set_lcid = lcid;
8618 return S_OK;
8621 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8622 UINT libFlags)
8624 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8626 TRACE("%p %x\n", This, libFlags);
8628 This->libflags = libFlags;
8630 return S_OK;
8633 typedef struct tagWMSFT_SegContents {
8634 DWORD len;
8635 void *data;
8636 } WMSFT_SegContents;
8638 typedef struct tagWMSFT_TLBFile {
8639 MSFT_Header header;
8640 WMSFT_SegContents typeinfo_seg;
8641 WMSFT_SegContents impfile_seg;
8642 WMSFT_SegContents impinfo_seg;
8643 WMSFT_SegContents ref_seg;
8644 WMSFT_SegContents guidhash_seg;
8645 WMSFT_SegContents guid_seg;
8646 WMSFT_SegContents namehash_seg;
8647 WMSFT_SegContents name_seg;
8648 WMSFT_SegContents string_seg;
8649 WMSFT_SegContents typdesc_seg;
8650 WMSFT_SegContents arraydesc_seg;
8651 WMSFT_SegContents custdata_seg;
8652 WMSFT_SegContents cdguids_seg;
8653 MSFT_SegDir segdir;
8654 WMSFT_SegContents aux_seg;
8655 } WMSFT_TLBFile;
8657 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8658 WMSFT_TLBFile *file)
8660 TLBString *str;
8661 UINT last_offs;
8662 char *data;
8664 file->string_seg.len = 0;
8665 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8666 int size;
8668 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8669 if (size == 0)
8670 return E_UNEXPECTED;
8672 size += sizeof(INT16);
8673 if (size % 4)
8674 size = (size + 4) & ~0x3;
8675 if (size < 8)
8676 size = 8;
8678 file->string_seg.len += size;
8680 /* temporarily use str->offset to store the length of the aligned,
8681 * converted string */
8682 str->offset = size;
8685 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8687 last_offs = 0;
8688 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8689 int size;
8691 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8692 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8693 if (size == 0) {
8694 heap_free(file->string_seg.data);
8695 return E_UNEXPECTED;
8698 *((INT16*)data) = size;
8700 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8702 size = str->offset;
8703 data += size;
8704 str->offset = last_offs;
8705 last_offs += size;
8708 return S_OK;
8711 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8712 WMSFT_TLBFile *file)
8714 TLBString *str;
8715 UINT last_offs;
8716 char *data;
8717 MSFT_NameIntro *last_intro = NULL;
8719 file->header.nametablecount = 0;
8720 file->header.nametablechars = 0;
8722 file->name_seg.len = 0;
8723 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8724 int size;
8726 size = strlenW(str->str);
8727 file->header.nametablechars += size;
8728 file->header.nametablecount++;
8730 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8731 if (size == 0)
8732 return E_UNEXPECTED;
8734 size += sizeof(MSFT_NameIntro);
8735 if (size % 4)
8736 size = (size + 4) & ~0x3;
8737 if (size < 8)
8738 size = 8;
8740 file->name_seg.len += size;
8742 /* temporarily use str->offset to store the length of the aligned,
8743 * converted string */
8744 str->offset = size;
8747 file->name_seg.data = data = heap_alloc(file->name_seg.len);
8749 last_offs = 0;
8750 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8751 int size, hash;
8752 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8754 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8755 data + sizeof(MSFT_NameIntro),
8756 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8757 if (size == 0) {
8758 heap_free(file->name_seg.data);
8759 return E_UNEXPECTED;
8761 data[sizeof(MSFT_NameIntro) + size] = '\0';
8763 intro->hreftype = -1; /* TODO? */
8764 intro->namelen = size & 0xFF;
8765 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8766 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
8767 intro->namelen |= hash << 16;
8768 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
8769 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
8771 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8772 str->offset - size - sizeof(MSFT_NameIntro));
8774 /* update str->offset to actual value to use in other
8775 * compilation functions that require positions within
8776 * the string table */
8777 last_intro = intro;
8778 size = str->offset;
8779 data += size;
8780 str->offset = last_offs;
8781 last_offs += size;
8784 if(last_intro)
8785 last_intro->hreftype = 0; /* last one is 0? */
8787 return S_OK;
8790 static inline int hash_guid(GUID *guid)
8792 int i, hash = 0;
8794 for (i = 0; i < 8; i ++)
8795 hash ^= ((const short *)guid)[i];
8797 return hash & 0x1f;
8800 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
8802 TLBGuid *guid;
8803 MSFT_GuidEntry *entry;
8804 DWORD offs;
8805 int hash_key, *guidhashtab;
8807 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
8808 file->guid_seg.data = heap_alloc(file->guid_seg.len);
8810 entry = file->guid_seg.data;
8811 offs = 0;
8812 guidhashtab = file->guidhash_seg.data;
8813 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
8814 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
8815 entry->hreftype = guid->hreftype;
8817 hash_key = hash_guid(&guid->guid);
8818 entry->next_hash = guidhashtab[hash_key];
8819 guidhashtab[hash_key] = offs;
8821 guid->offset = offs;
8822 offs += sizeof(MSFT_GuidEntry);
8823 ++entry;
8826 return S_OK;
8829 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
8831 VARIANT v = *value;
8832 VARTYPE arg_type = V_VT(value);
8833 int mask = 0;
8834 HRESULT hres;
8835 DWORD ret = file->custdata_seg.len;
8837 if(arg_type == VT_INT)
8838 arg_type = VT_I4;
8839 if(arg_type == VT_UINT)
8840 arg_type = VT_UI4;
8842 v = *value;
8843 if(V_VT(value) != arg_type) {
8844 hres = VariantChangeType(&v, value, 0, arg_type);
8845 if(FAILED(hres)){
8846 ERR("VariantChangeType failed: %08x\n", hres);
8847 return -1;
8851 /* Check if default value can be stored in-place */
8852 switch(arg_type){
8853 case VT_I4:
8854 case VT_UI4:
8855 mask = 0x3ffffff;
8856 if(V_UI4(&v) > 0x3ffffff)
8857 break;
8858 /* fall through */
8859 case VT_I1:
8860 case VT_UI1:
8861 case VT_BOOL:
8862 if(!mask)
8863 mask = 0xff;
8864 /* fall through */
8865 case VT_I2:
8866 case VT_UI2:
8867 if(!mask)
8868 mask = 0xffff;
8869 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
8872 /* have to allocate space in custdata_seg */
8873 switch(arg_type) {
8874 case VT_I4:
8875 case VT_R4:
8876 case VT_UI4:
8877 case VT_INT:
8878 case VT_UINT:
8879 case VT_HRESULT:
8880 case VT_PTR: {
8881 /* Construct the data to be allocated */
8882 int *data;
8884 if(file->custdata_seg.data){
8885 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
8886 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
8887 file->custdata_seg.len += sizeof(int) * 2;
8888 }else{
8889 file->custdata_seg.len = sizeof(int) * 2;
8890 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
8893 data[0] = V_VT(value) + (V_UI4(&v) << 16);
8894 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
8896 /* TODO: Check if the encoded data is already present in custdata_seg */
8898 return ret;
8901 case VT_BSTR: {
8902 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
8903 char *data;
8905 if(file->custdata_seg.data){
8906 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
8907 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
8908 file->custdata_seg.len += len;
8909 }else{
8910 file->custdata_seg.len = len;
8911 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
8914 *((unsigned short *)data) = V_VT(value);
8915 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
8916 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
8917 if(V_BSTR(&v)[i] <= 0x7f)
8918 data[i+6] = V_BSTR(&v)[i];
8919 else
8920 data[i+6] = '?';
8922 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
8923 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
8924 data[i] = 0x57;
8926 /* TODO: Check if the encoded data is already present in custdata_seg */
8928 return ret;
8930 default:
8931 FIXME("Argument type not yet handled\n");
8932 return -1;
8936 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
8938 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
8940 DWORD offs = file->arraydesc_seg.len;
8941 DWORD *encoded;
8942 USHORT i;
8944 /* TODO: we should check for duplicates, but that's harder because each
8945 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
8946 * at the library-level) */
8948 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
8949 if(!file->arraydesc_seg.data)
8950 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
8951 else
8952 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
8953 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
8955 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
8956 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
8957 for(i = 0; i < desc->cDims; ++i){
8958 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
8959 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
8962 return offs;
8965 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
8967 DWORD junk;
8968 INT16 junk2;
8969 DWORD offs = 0;
8970 DWORD encoded[2];
8971 VARTYPE vt = desc->vt & VT_TYPEMASK, subtype;
8972 char *data;
8974 if(!out_mix)
8975 out_mix = &junk;
8976 if(!out_size)
8977 out_size = &junk2;
8979 switch(vt){
8980 case VT_INT:
8981 subtype = VT_I4;
8982 break;
8983 case VT_UINT:
8984 subtype = VT_UI4;
8985 break;
8986 case VT_VOID:
8987 subtype = VT_EMPTY;
8988 break;
8989 default:
8990 subtype = vt;
8991 break;
8994 switch(vt){
8995 case VT_INT:
8996 case VT_UINT:
8997 case VT_I1:
8998 case VT_UI1:
8999 case VT_I2:
9000 case VT_UI2:
9001 case VT_I4:
9002 case VT_UI4:
9003 case VT_BOOL:
9004 case VT_R4:
9005 case VT_ERROR:
9006 case VT_BSTR:
9007 case VT_HRESULT:
9008 case VT_CY:
9009 case VT_VOID:
9010 case VT_VARIANT:
9011 *out_mix = subtype;
9012 return 0x80000000 | (subtype << 16) | desc->vt;
9015 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9016 DWORD mix;
9017 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9018 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9019 *out_mix = 0x7FFF;
9020 *out_size += 2 * sizeof(DWORD);
9021 }else if(vt == VT_CARRAY){
9022 encoded[0] = desc->vt | (0x7FFE << 16);
9023 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9024 *out_mix = 0x7FFE;
9025 }else if(vt == VT_USERDEFINED){
9026 encoded[0] = desc->vt | (0x7FFF << 16);
9027 encoded[1] = desc->u.hreftype;
9028 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9029 }else{
9030 FIXME("Don't know what to do! VT: 0x%x\n", desc->vt);
9031 *out_mix = desc->vt;
9032 return 0x80000000 | (desc->vt << 16) | desc->vt;
9035 data = file->typdesc_seg.data;
9036 while(offs < file->typdesc_seg.len){
9037 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9038 return offs;
9039 offs += sizeof(encoded);
9042 file->typdesc_seg.len += sizeof(encoded);
9043 if(!file->typdesc_seg.data)
9044 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9045 else
9046 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9048 memcpy(&data[offs], encoded, sizeof(encoded));
9050 return offs;
9053 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9055 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9056 DWORD ret = cdguids_seg->len, offs;
9057 MSFT_CDGuid *cdguid = cdguids_seg->data;
9058 TLBCustData *cd;
9060 if(list_empty(custdata_list))
9061 return -1;
9063 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9064 if(!cdguids_seg->data){
9065 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9066 }else
9067 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9069 offs = ret + sizeof(MSFT_CDGuid);
9070 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9071 cdguid->GuidOffset = cd->guid->offset;
9072 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9073 cdguid->next = offs;
9074 offs += sizeof(MSFT_CDGuid);
9075 ++cdguid;
9078 --cdguid;
9079 cdguid->next = -1;
9081 return ret;
9084 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9085 WMSFT_TLBFile *file)
9087 WMSFT_SegContents *aux_seg = &file->aux_seg;
9088 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9089 MSFT_VarRecord *varrecord;
9090 MSFT_FuncRecord *funcrecord;
9091 MEMBERID *memid;
9092 DWORD *name, *offsets, offs;
9094 for(i = 0; i < info->cFuncs; ++i){
9095 TLBFuncDesc *desc = &info->funcdescs[i];
9097 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9099 /* optional fields */
9100 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9101 if(!list_empty(&desc->custdata_list))
9102 recorded_size += 7 * sizeof(INT);
9103 else if(desc->HelpStringContext != 0)
9104 recorded_size += 6 * sizeof(INT);
9105 /* res9? resA? */
9106 else if(desc->Entry)
9107 recorded_size += 3 * sizeof(INT);
9108 else if(desc->HelpString)
9109 recorded_size += 2 * sizeof(INT);
9110 else if(desc->helpcontext)
9111 recorded_size += sizeof(INT);
9113 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9115 for(j = 0; j < desc->funcdesc.cParams; ++j){
9116 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9117 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9118 break;
9122 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9125 for(i = 0; i < info->cVars; ++i){
9126 TLBVarDesc *desc = &info->vardescs[i];
9128 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9130 /* optional fields */
9131 if(desc->HelpStringContext != 0)
9132 recorded_size += 5 * sizeof(INT);
9133 else if(!list_empty(&desc->custdata_list))
9134 recorded_size += 4 * sizeof(INT);
9135 /* res9? */
9136 else if(desc->HelpString)
9137 recorded_size += 2 * sizeof(INT);
9138 else if(desc->HelpContext != 0)
9139 recorded_size += sizeof(INT);
9141 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9144 if(!recorded_size && !extra_size)
9145 return ret;
9147 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9149 aux_seg->len += recorded_size + extra_size;
9151 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9153 if(aux_seg->data)
9154 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9155 else
9156 aux_seg->data = heap_alloc(aux_seg->len);
9158 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9160 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9161 offs = 0;
9163 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9164 for(i = 0; i < info->cFuncs; ++i){
9165 TLBFuncDesc *desc = &info->funcdescs[i];
9166 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9168 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9169 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9170 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9171 funcrecord->VtableOffset = desc->funcdesc.oVft;
9173 /* FKCCIC:
9174 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9175 * ^^^funckind
9176 * ^^^ ^invkind
9177 * ^has_cust_data
9178 * ^^^^callconv
9179 * ^has_param_defaults
9180 * ^oEntry_is_intresource
9182 funcrecord->FKCCIC =
9183 desc->funcdesc.funckind |
9184 (desc->funcdesc.invkind << 3) |
9185 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9186 (desc->funcdesc.callconv << 8);
9188 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9189 funcrecord->FKCCIC |= 0x2000;
9191 for(j = 0; j < desc->funcdesc.cParams; ++j){
9192 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9193 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9194 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9197 if(paramdefault_size > 0)
9198 funcrecord->FKCCIC |= 0x1000;
9200 funcrecord->nrargs = desc->funcdesc.cParams;
9201 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9203 /* optional fields */
9204 /* res9? resA? */
9205 if(!list_empty(&desc->custdata_list)){
9206 size += 7 * sizeof(INT);
9207 funcrecord->HelpContext = desc->helpcontext;
9208 if(desc->HelpString)
9209 funcrecord->oHelpString = desc->HelpString->offset;
9210 else
9211 funcrecord->oHelpString = -1;
9212 if(!desc->Entry)
9213 funcrecord->oEntry = -1;
9214 else if(IS_INTRESOURCE(desc->Entry))
9215 funcrecord->oEntry = LOWORD(desc->Entry);
9216 else
9217 funcrecord->oEntry = desc->Entry->offset;
9218 funcrecord->res9 = -1;
9219 funcrecord->resA = -1;
9220 funcrecord->HelpStringContext = desc->HelpStringContext;
9221 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9222 }else if(desc->HelpStringContext != 0){
9223 size += 6 * sizeof(INT);
9224 funcrecord->HelpContext = desc->helpcontext;
9225 if(desc->HelpString)
9226 funcrecord->oHelpString = desc->HelpString->offset;
9227 else
9228 funcrecord->oHelpString = -1;
9229 if(!desc->Entry)
9230 funcrecord->oEntry = -1;
9231 else if(IS_INTRESOURCE(desc->Entry))
9232 funcrecord->oEntry = LOWORD(desc->Entry);
9233 else
9234 funcrecord->oEntry = desc->Entry->offset;
9235 funcrecord->res9 = -1;
9236 funcrecord->resA = -1;
9237 funcrecord->HelpStringContext = desc->HelpStringContext;
9238 }else if(desc->Entry){
9239 size += 3 * sizeof(INT);
9240 funcrecord->HelpContext = desc->helpcontext;
9241 if(desc->HelpString)
9242 funcrecord->oHelpString = desc->HelpString->offset;
9243 else
9244 funcrecord->oHelpString = -1;
9245 if(!desc->Entry)
9246 funcrecord->oEntry = -1;
9247 else if(IS_INTRESOURCE(desc->Entry))
9248 funcrecord->oEntry = LOWORD(desc->Entry);
9249 else
9250 funcrecord->oEntry = desc->Entry->offset;
9251 }else if(desc->HelpString){
9252 size += 2 * sizeof(INT);
9253 funcrecord->HelpContext = desc->helpcontext;
9254 funcrecord->oHelpString = desc->HelpString->offset;
9255 }else if(desc->helpcontext){
9256 size += sizeof(INT);
9257 funcrecord->HelpContext = desc->helpcontext;
9260 paramdefault = (DWORD*)((char *)funcrecord + size);
9261 size += paramdefault_size;
9263 for(j = 0; j < desc->funcdesc.cParams; ++j){
9264 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9266 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9267 if(desc->pParamDesc[j].Name)
9268 info->oName = desc->pParamDesc[j].Name->offset;
9269 else
9270 info->oName = -1;
9271 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9273 if(paramdefault_size){
9274 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9275 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9276 else if(paramdefault_size)
9277 *paramdefault = -1;
9278 ++paramdefault;
9281 size += sizeof(MSFT_ParameterInfo);
9284 funcrecord->Info = size | (i << 16); /* is it just the index? */
9286 *offsets = offs;
9287 offs += size;
9288 ++offsets;
9290 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9293 varrecord = (MSFT_VarRecord*)funcrecord;
9294 for(i = 0; i < info->cVars; ++i){
9295 TLBVarDesc *desc = &info->vardescs[i];
9296 DWORD size = 5 * sizeof(INT);
9298 varrecord->vardescsize = sizeof(desc->vardesc);
9299 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9300 varrecord->Flags = desc->vardesc.wVarFlags;
9301 varrecord->VarKind = desc->vardesc.varkind;
9303 if(desc->vardesc.varkind == VAR_CONST){
9304 varrecord->vardescsize += sizeof(VARIANT);
9305 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9306 }else
9307 varrecord->OffsValue = desc->vardesc.u.oInst;
9309 /* res9? */
9310 if(desc->HelpStringContext != 0){
9311 size += 5 * sizeof(INT);
9312 varrecord->HelpContext = desc->HelpContext;
9313 if(desc->HelpString)
9314 varrecord->HelpString = desc->HelpString->offset;
9315 else
9316 varrecord->HelpString = -1;
9317 varrecord->res9 = -1;
9318 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9319 varrecord->HelpStringContext = desc->HelpStringContext;
9320 }else if(!list_empty(&desc->custdata_list)){
9321 size += 4 * sizeof(INT);
9322 varrecord->HelpContext = desc->HelpContext;
9323 if(desc->HelpString)
9324 varrecord->HelpString = desc->HelpString->offset;
9325 else
9326 varrecord->HelpString = -1;
9327 varrecord->res9 = -1;
9328 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9329 }else if(desc->HelpString){
9330 size += 2 * sizeof(INT);
9331 varrecord->HelpContext = desc->HelpContext;
9332 if(desc->HelpString)
9333 varrecord->HelpString = desc->HelpString->offset;
9334 else
9335 varrecord->HelpString = -1;
9336 }else if(desc->HelpContext != 0){
9337 size += sizeof(INT);
9338 varrecord->HelpContext = desc->HelpContext;
9341 varrecord->Info = size | (i << 16);
9343 *offsets = offs;
9344 offs += size;
9345 ++offsets;
9347 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9350 memid = (MEMBERID*)varrecord;
9351 for(i = 0; i < info->cFuncs; ++i){
9352 TLBFuncDesc *desc = &info->funcdescs[i];
9353 *memid = desc->funcdesc.memid;
9354 ++memid;
9356 for(i = 0; i < info->cVars; ++i){
9357 TLBVarDesc *desc = &info->vardescs[i];
9358 *memid = desc->vardesc.memid;
9359 ++memid;
9362 name = (UINT*)memid;
9363 for(i = 0; i < info->cFuncs; ++i){
9364 TLBFuncDesc *desc = &info->funcdescs[i];
9365 if(desc->Name)
9366 *name = desc->Name->offset;
9367 else
9368 *name = -1;
9369 ++name;
9371 for(i = 0; i < info->cVars; ++i){
9372 TLBVarDesc *desc = &info->vardescs[i];
9373 if(desc->Name)
9374 *name = desc->Name->offset;
9375 else
9376 *name = -1;
9377 ++name;
9380 return ret;
9383 typedef struct tagWMSFT_RefChunk {
9384 DWORD href;
9385 DWORD res04;
9386 DWORD res08;
9387 DWORD next;
9388 } WMSFT_RefChunk;
9390 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9392 DWORD offs = file->ref_seg.len, i;
9393 WMSFT_RefChunk *chunk;
9395 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9396 if(!file->ref_seg.data)
9397 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9398 else
9399 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9401 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9403 for(i = 0; i < info->cImplTypes; ++i){
9404 chunk->href = info->impltypes[i].hRef;
9405 chunk->res04 = info->impltypes[i].implflags;
9406 chunk->res08 = -1;
9407 if(i < info->cImplTypes - 1)
9408 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9409 else
9410 chunk->next = -1;
9411 ++chunk;
9414 return offs;
9417 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9419 DWORD size;
9421 size = sizeof(MSFT_TypeInfoBase);
9423 if(data){
9424 MSFT_TypeInfoBase *base = (void*)data;
9425 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9426 base->typekind = TKIND_DISPATCH;
9427 else
9428 base->typekind = info->typekind;
9429 base->typekind |= index << 16; /* TODO: There are some other flags here */
9430 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9431 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9432 base->res2 = 0;
9433 base->res3 = 0;
9434 base->res4 = 3;
9435 base->res5 = 0;
9436 base->cElement = (info->cVars << 16) | info->cFuncs;
9437 base->res7 = 0;
9438 base->res8 = 0;
9439 base->res9 = 0;
9440 base->resA = 0;
9441 if(info->guid)
9442 base->posguid = info->guid->offset;
9443 else
9444 base->posguid = -1;
9445 base->flags = info->wTypeFlags;
9446 if(info->Name) {
9447 base->NameOffset = info->Name->offset;
9449 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9450 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9451 }else {
9452 base->NameOffset = -1;
9454 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9455 if(info->DocString)
9456 base->docstringoffs = info->DocString->offset;
9457 else
9458 base->docstringoffs = -1;
9459 base->helpstringcontext = info->dwHelpStringContext;
9460 base->helpcontext = info->dwHelpContext;
9461 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9462 base->cImplTypes = info->cImplTypes;
9463 base->cbSizeVft = info->cbSizeVft;
9464 base->size = info->cbSizeInstance;
9465 if(info->typekind == TKIND_COCLASS){
9466 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9467 }else if(info->typekind == TKIND_ALIAS){
9468 base->datatype1 = WMSFT_append_typedesc(&info->tdescAlias, file, NULL, NULL);
9469 }else if(info->typekind == TKIND_MODULE){
9470 if(info->DllName)
9471 base->datatype1 = info->DllName->offset;
9472 else
9473 base->datatype1 = -1;
9474 }else{
9475 if(info->cImplTypes > 0)
9476 base->datatype1 = info->impltypes[0].hRef;
9477 else
9478 base->datatype1 = -1;
9480 base->datatype2 = index; /* FIXME: i think there's more here */
9481 base->res18 = 0;
9482 base->res19 = -1;
9485 return size;
9488 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9490 UINT i;
9492 file->typeinfo_seg.len = 0;
9493 for(i = 0; i < This->TypeInfoCount; ++i){
9494 ITypeInfoImpl *info = This->typeinfos[i];
9495 *junk = file->typeinfo_seg.len;
9496 ++junk;
9497 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9500 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9501 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9503 file->aux_seg.len = 0;
9504 file->aux_seg.data = NULL;
9506 file->typeinfo_seg.len = 0;
9507 for(i = 0; i < This->TypeInfoCount; ++i){
9508 ITypeInfoImpl *info = This->typeinfos[i];
9509 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9510 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9514 typedef struct tagWMSFT_ImpFile {
9515 INT guid_offs;
9516 LCID lcid;
9517 DWORD version;
9518 } WMSFT_ImpFile;
9520 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9522 TLBImpLib *implib;
9523 WMSFT_ImpFile *impfile;
9524 char *data;
9525 DWORD last_offs = 0;
9527 file->impfile_seg.len = 0;
9528 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9529 int size = 0;
9531 if(implib->name){
9532 WCHAR *path = strrchrW(implib->name, '\\');
9533 if(path)
9534 ++path;
9535 else
9536 path = implib->name;
9537 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9538 if (size == 0)
9539 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9542 size += sizeof(INT16);
9543 if (size % 4)
9544 size = (size + 4) & ~0x3;
9545 if (size < 8)
9546 size = 8;
9548 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9551 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9553 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9554 int strlen = 0, size;
9556 impfile = (WMSFT_ImpFile*)data;
9557 impfile->guid_offs = implib->guid->offset;
9558 impfile->lcid = implib->lcid;
9559 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9561 data += sizeof(WMSFT_ImpFile);
9563 if(implib->name){
9564 WCHAR *path= strrchrW(implib->name, '\\');
9565 if(path)
9566 ++path;
9567 else
9568 path = implib->name;
9569 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9570 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9571 if (strlen == 0)
9572 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9575 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9577 size = strlen + sizeof(INT16);
9578 if (size % 4)
9579 size = (size + 4) & ~0x3;
9580 if (size < 8)
9581 size = 8;
9582 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9584 data += size;
9585 implib->offset = last_offs;
9586 last_offs += size + sizeof(WMSFT_ImpFile);
9590 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9592 MSFT_ImpInfo *info;
9593 TLBRefType *ref_type;
9594 UINT i = 0;
9596 WMSFT_compile_impfile(This, file);
9598 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9599 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9601 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9602 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9603 if(ref_type->index == TLB_REF_USE_GUID){
9604 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9605 info->oGuid = ref_type->guid->offset;
9606 }else
9607 info->oGuid = ref_type->index;
9608 info->oImpFile = ref_type->pImpTLInfo->offset;
9609 ++i;
9610 ++info;
9614 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9616 file->guidhash_seg.len = 0x80;
9617 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9618 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9621 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9623 file->namehash_seg.len = 0x200;
9624 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9625 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9628 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9630 if(contents && contents->len){
9631 segdir->offset = *running_offset;
9632 segdir->length = contents->len;
9633 *running_offset += segdir->length;
9634 }else{
9635 segdir->offset = -1;
9636 segdir->length = 0;
9639 /* TODO: do these ever change? */
9640 segdir->res08 = -1;
9641 segdir->res0c = 0xf;
9644 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9646 DWORD written;
9647 if(segment)
9648 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9651 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9652 DWORD file_len)
9654 DWORD i;
9655 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9657 for(i = 0; i < This->TypeInfoCount; ++i){
9658 base->memoffset += file_len;
9659 ++base;
9662 return S_OK;
9665 static void WMSFT_free_file(WMSFT_TLBFile *file)
9667 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9668 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9669 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9670 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9671 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9672 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9673 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9674 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9675 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9676 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9677 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9678 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9679 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9680 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9683 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9685 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9686 WMSFT_TLBFile file;
9687 DWORD written, junk_size, junk_offs, running_offset;
9688 BOOL br;
9689 HANDLE outfile;
9690 HRESULT hres;
9691 DWORD *junk;
9693 TRACE("%p\n", This);
9695 memset(&file, 0, sizeof(file));
9697 file.header.magic1 = 0x5446534D;
9698 file.header.magic2 = 0x00010002;
9699 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9700 file.header.lcid2 = This->set_lcid;
9701 file.header.varflags = 0x40 | This->syskind;
9702 if (This->HelpFile)
9703 file.header.varflags |= 0x10;
9704 if (This->HelpStringDll)
9705 file.header.varflags |= HELPDLLFLAG;
9706 file.header.version = (This->ver_minor << 16) | This->ver_major;
9707 file.header.flags = This->libflags;
9708 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9709 file.header.helpcontext = This->dwHelpContext;
9710 file.header.res44 = 0x20;
9711 file.header.res48 = 0x80;
9712 file.header.dispatchpos = This->dispatch_href;
9714 WMSFT_compile_namehash(This, &file);
9715 /* do name and string compilation to get offsets for other compilations */
9716 hres = WMSFT_compile_names(This, &file);
9717 if (FAILED(hres)){
9718 WMSFT_free_file(&file);
9719 return hres;
9722 hres = WMSFT_compile_strings(This, &file);
9723 if (FAILED(hres)){
9724 WMSFT_free_file(&file);
9725 return hres;
9728 WMSFT_compile_guidhash(This, &file);
9729 hres = WMSFT_compile_guids(This, &file);
9730 if (FAILED(hres)){
9731 WMSFT_free_file(&file);
9732 return hres;
9735 if(This->HelpFile)
9736 file.header.helpfile = This->HelpFile->offset;
9737 else
9738 file.header.helpfile = -1;
9740 if(This->DocString)
9741 file.header.helpstring = This->DocString->offset;
9742 else
9743 file.header.helpstring = -1;
9745 /* do some more segment compilation */
9746 file.header.nimpinfos = list_count(&This->ref_list);
9747 file.header.nrtypeinfos = This->TypeInfoCount;
9749 if(This->Name)
9750 file.header.NameOffset = This->Name->offset;
9751 else
9752 file.header.NameOffset = -1;
9754 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9756 if(This->guid)
9757 file.header.posguid = This->guid->offset;
9758 else
9759 file.header.posguid = -1;
9761 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9762 if(file.header.varflags & HELPDLLFLAG)
9763 junk_size += sizeof(DWORD);
9764 if(junk_size){
9765 junk = heap_alloc_zero(junk_size);
9766 if(file.header.varflags & HELPDLLFLAG){
9767 *junk = This->HelpStringDll->offset;
9768 junk_offs = 1;
9769 }else
9770 junk_offs = 0;
9771 }else{
9772 junk = NULL;
9773 junk_offs = 0;
9776 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9777 WMSFT_compile_impinfo(This, &file);
9779 running_offset = 0;
9781 TRACE("header at: 0x%x\n", running_offset);
9782 running_offset += sizeof(file.header);
9784 TRACE("junk at: 0x%x\n", running_offset);
9785 running_offset += junk_size;
9787 TRACE("segdir at: 0x%x\n", running_offset);
9788 running_offset += sizeof(file.segdir);
9790 TRACE("typeinfo at: 0x%x\n", running_offset);
9791 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
9793 TRACE("guidhashtab at: 0x%x\n", running_offset);
9794 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
9796 TRACE("guidtab at: 0x%x\n", running_offset);
9797 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
9799 TRACE("reftab at: 0x%x\n", running_offset);
9800 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
9802 TRACE("impinfo at: 0x%x\n", running_offset);
9803 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
9805 TRACE("impfiles at: 0x%x\n", running_offset);
9806 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
9808 TRACE("namehashtab at: 0x%x\n", running_offset);
9809 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
9811 TRACE("nametab at: 0x%x\n", running_offset);
9812 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
9814 TRACE("stringtab at: 0x%x\n", running_offset);
9815 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
9817 TRACE("typdesc at: 0x%x\n", running_offset);
9818 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
9820 TRACE("arraydescriptions at: 0x%x\n", running_offset);
9821 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
9823 TRACE("custdata at: 0x%x\n", running_offset);
9824 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
9826 TRACE("cdguids at: 0x%x\n", running_offset);
9827 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
9829 TRACE("res0e at: 0x%x\n", running_offset);
9830 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
9832 TRACE("res0f at: 0x%x\n", running_offset);
9833 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
9835 TRACE("aux_seg at: 0x%x\n", running_offset);
9837 WMSFT_fixup_typeinfos(This, &file, running_offset);
9839 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
9840 FILE_ATTRIBUTE_NORMAL, 0);
9841 if (outfile == INVALID_HANDLE_VALUE){
9842 WMSFT_free_file(&file);
9843 heap_free(junk);
9844 return TYPE_E_IOERROR;
9847 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
9848 if (!br) {
9849 WMSFT_free_file(&file);
9850 CloseHandle(outfile);
9851 heap_free(junk);
9852 return TYPE_E_IOERROR;
9855 br = WriteFile(outfile, junk, junk_size, &written, NULL);
9856 heap_free(junk);
9857 if (!br) {
9858 WMSFT_free_file(&file);
9859 CloseHandle(outfile);
9860 return TYPE_E_IOERROR;
9863 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
9864 if (!br) {
9865 WMSFT_free_file(&file);
9866 CloseHandle(outfile);
9867 return TYPE_E_IOERROR;
9870 WMSFT_write_segment(outfile, &file.typeinfo_seg);
9871 WMSFT_write_segment(outfile, &file.guidhash_seg);
9872 WMSFT_write_segment(outfile, &file.guid_seg);
9873 WMSFT_write_segment(outfile, &file.ref_seg);
9874 WMSFT_write_segment(outfile, &file.impinfo_seg);
9875 WMSFT_write_segment(outfile, &file.impfile_seg);
9876 WMSFT_write_segment(outfile, &file.namehash_seg);
9877 WMSFT_write_segment(outfile, &file.name_seg);
9878 WMSFT_write_segment(outfile, &file.string_seg);
9879 WMSFT_write_segment(outfile, &file.typdesc_seg);
9880 WMSFT_write_segment(outfile, &file.arraydesc_seg);
9881 WMSFT_write_segment(outfile, &file.custdata_seg);
9882 WMSFT_write_segment(outfile, &file.cdguids_seg);
9883 WMSFT_write_segment(outfile, &file.aux_seg);
9885 WMSFT_free_file(&file);
9887 CloseHandle(outfile);
9889 return S_OK;
9892 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
9893 LPOLESTR name)
9895 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9896 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
9897 return E_NOTIMPL;
9900 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
9901 REFGUID guid, VARIANT *varVal)
9903 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9904 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
9905 return E_NOTIMPL;
9908 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
9909 ULONG helpStringContext)
9911 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9912 FIXME("%p %u - stub\n", This, helpStringContext);
9913 return E_NOTIMPL;
9916 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
9917 LPOLESTR filename)
9919 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9920 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
9922 if (!filename)
9923 return E_INVALIDARG;
9925 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
9927 return S_OK;
9930 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
9931 ICreateTypeLib2_fnQueryInterface,
9932 ICreateTypeLib2_fnAddRef,
9933 ICreateTypeLib2_fnRelease,
9934 ICreateTypeLib2_fnCreateTypeInfo,
9935 ICreateTypeLib2_fnSetName,
9936 ICreateTypeLib2_fnSetVersion,
9937 ICreateTypeLib2_fnSetGuid,
9938 ICreateTypeLib2_fnSetDocString,
9939 ICreateTypeLib2_fnSetHelpFileName,
9940 ICreateTypeLib2_fnSetHelpContext,
9941 ICreateTypeLib2_fnSetLcid,
9942 ICreateTypeLib2_fnSetLibFlags,
9943 ICreateTypeLib2_fnSaveAllChanges,
9944 ICreateTypeLib2_fnDeleteTypeInfo,
9945 ICreateTypeLib2_fnSetCustData,
9946 ICreateTypeLib2_fnSetHelpStringContext,
9947 ICreateTypeLib2_fnSetHelpStringDll
9950 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
9951 REFIID riid, void **object)
9953 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9955 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
9958 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
9960 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9962 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
9965 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
9967 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9969 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
9972 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
9973 REFGUID guid)
9975 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9977 TRACE("%p %s\n", This, debugstr_guid(guid));
9979 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
9981 return S_OK;
9984 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
9985 UINT typeFlags)
9987 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9988 WORD old_flags;
9989 HRESULT hres;
9991 TRACE("%p %x\n", This, typeFlags);
9993 if (typeFlags & TYPEFLAG_FDUAL) {
9994 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
9995 ITypeLib *stdole;
9996 ITypeInfo *dispatch;
9997 HREFTYPE hreftype;
9998 HRESULT hres;
10000 hres = LoadTypeLib(stdole2tlb, &stdole);
10001 if(FAILED(hres))
10002 return hres;
10004 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10005 ITypeLib_Release(stdole);
10006 if(FAILED(hres))
10007 return hres;
10009 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10010 ITypeInfo_Release(dispatch);
10011 if(FAILED(hres))
10012 return hres;
10015 old_flags = This->wTypeFlags;
10016 This->wTypeFlags = typeFlags;
10018 hres = ICreateTypeInfo2_LayOut(iface);
10019 if (FAILED(hres)) {
10020 This->wTypeFlags = old_flags;
10021 return hres;
10024 return S_OK;
10027 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10028 LPOLESTR doc)
10030 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10032 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10034 if (!doc)
10035 return E_INVALIDARG;
10037 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10039 return S_OK;
10042 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10043 DWORD helpContext)
10045 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10047 TRACE("%p %d\n", This, helpContext);
10049 This->dwHelpContext = helpContext;
10051 return S_OK;
10054 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10055 WORD majorVerNum, WORD minorVerNum)
10057 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10059 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10061 This->wMajorVerNum = majorVerNum;
10062 This->wMinorVerNum = minorVerNum;
10064 return S_OK;
10067 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10068 ITypeInfo *typeInfo, HREFTYPE *refType)
10070 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10071 UINT index;
10072 ITypeLib *container;
10073 TLBRefType *ref_type;
10074 TLBImpLib *implib;
10075 TYPEATTR *typeattr;
10076 TLIBATTR *libattr;
10077 HRESULT hres;
10079 TRACE("%p %p %p\n", This, typeInfo, refType);
10081 if (!typeInfo || !refType)
10082 return E_INVALIDARG;
10084 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10085 if (FAILED(hres))
10086 return hres;
10088 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10089 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10091 ITypeLib_Release(container);
10093 *refType = target->hreftype;
10095 return S_OK;
10098 hres = ITypeLib_GetLibAttr(container, &libattr);
10099 if (FAILED(hres)) {
10100 ITypeLib_Release(container);
10101 return hres;
10104 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10105 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10106 implib->lcid == libattr->lcid &&
10107 implib->wVersionMajor == libattr->wMajorVerNum &&
10108 implib->wVersionMinor == libattr->wMinorVerNum)
10109 break;
10112 if(&implib->entry == &This->pTypeLib->implib_list){
10113 implib = heap_alloc_zero(sizeof(TLBImpLib));
10115 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10116 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10117 implib->name = SysAllocString(our_container->path);
10118 }else{
10119 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10120 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10121 if(FAILED(hres)){
10122 implib->name = NULL;
10123 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10127 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10128 implib->lcid = libattr->lcid;
10129 implib->wVersionMajor = libattr->wMajorVerNum;
10130 implib->wVersionMinor = libattr->wMinorVerNum;
10132 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10135 ITypeLib_ReleaseTLibAttr(container, libattr);
10136 ITypeLib_Release(container);
10138 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10139 if (FAILED(hres))
10140 return hres;
10142 index = 0;
10143 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10144 if(ref_type->index == TLB_REF_USE_GUID &&
10145 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10146 ref_type->tkind == typeattr->typekind)
10147 break;
10148 ++index;
10151 if(&ref_type->entry == &This->pTypeLib->ref_list){
10152 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10154 ref_type->tkind = typeattr->typekind;
10155 ref_type->pImpTLInfo = implib;
10156 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10158 ref_type->index = TLB_REF_USE_GUID;
10160 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10162 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10165 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10167 *refType = ref_type->reference | 0x1;
10169 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10170 This->pTypeLib->dispatch_href = *refType;
10172 return S_OK;
10175 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10176 UINT index, FUNCDESC *funcDesc)
10178 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10179 TLBFuncDesc tmp_func_desc, *func_desc;
10180 int buf_size, i;
10181 char *buffer;
10182 HRESULT hres;
10184 TRACE("%p %u %p\n", This, index, funcDesc);
10186 if (!funcDesc || funcDesc->oVft & 3)
10187 return E_INVALIDARG;
10189 switch (This->typekind) {
10190 case TKIND_MODULE:
10191 if (funcDesc->funckind != FUNC_STATIC)
10192 return TYPE_E_BADMODULEKIND;
10193 break;
10194 case TKIND_DISPATCH:
10195 if (funcDesc->funckind != FUNC_DISPATCH)
10196 return TYPE_E_BADMODULEKIND;
10197 break;
10198 default:
10199 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10200 return TYPE_E_BADMODULEKIND;
10203 if (index > This->cFuncs)
10204 return TYPE_E_ELEMENTNOTFOUND;
10206 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10207 !funcDesc->cParams)
10208 return TYPE_E_INCONSISTENTPROPFUNCS;
10210 #ifdef _WIN64
10211 if(This->pTypeLib->syskind == SYS_WIN64 &&
10212 funcDesc->oVft % 8 != 0)
10213 return E_INVALIDARG;
10214 #endif
10216 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10217 TLBFuncDesc_Constructor(&tmp_func_desc);
10219 tmp_func_desc.funcdesc = *funcDesc;
10221 if (tmp_func_desc.funcdesc.oVft != 0)
10222 tmp_func_desc.funcdesc.oVft |= 1;
10224 if (funcDesc->cScodes) {
10225 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10226 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10227 } else
10228 tmp_func_desc.funcdesc.lprgscode = NULL;
10230 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10231 for (i = 0; i < funcDesc->cParams; ++i) {
10232 buf_size += sizeof(ELEMDESC);
10233 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10235 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10236 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10238 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10239 if (FAILED(hres)) {
10240 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10241 heap_free(tmp_func_desc.funcdesc.lprgscode);
10242 return hres;
10245 for (i = 0; i < funcDesc->cParams; ++i) {
10246 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10247 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10248 if (FAILED(hres)) {
10249 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10250 heap_free(tmp_func_desc.funcdesc.lprgscode);
10251 return hres;
10253 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10254 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10255 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10256 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10257 if (FAILED(hres)) {
10258 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10259 heap_free(tmp_func_desc.funcdesc.lprgscode);
10260 return hres;
10265 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10267 if (This->funcdescs) {
10268 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10269 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10271 if (index < This->cFuncs) {
10272 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10273 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10274 func_desc = This->funcdescs + index;
10275 } else
10276 func_desc = This->funcdescs + This->cFuncs;
10278 /* move custdata lists to the new memory location */
10279 for(i = 0; i < This->cFuncs + 1; ++i){
10280 if(index != i){
10281 TLBFuncDesc *fd = &This->funcdescs[i];
10282 if(fd->custdata_list.prev == fd->custdata_list.next)
10283 list_init(&fd->custdata_list);
10284 else{
10285 fd->custdata_list.prev->next = &fd->custdata_list;
10286 fd->custdata_list.next->prev = &fd->custdata_list;
10290 } else
10291 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10293 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10294 list_init(&func_desc->custdata_list);
10296 ++This->cFuncs;
10298 This->needs_layout = TRUE;
10300 return S_OK;
10303 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10304 UINT index, HREFTYPE refType)
10306 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10307 TLBImplType *impl_type;
10308 HRESULT hres;
10310 TRACE("%p %u %d\n", This, index, refType);
10312 switch(This->typekind){
10313 case TKIND_COCLASS: {
10314 if (index == -1) {
10315 FIXME("Unhandled index: -1\n");
10316 return E_NOTIMPL;
10319 if(index != This->cImplTypes)
10320 return TYPE_E_ELEMENTNOTFOUND;
10322 break;
10324 case TKIND_INTERFACE:
10325 case TKIND_DISPATCH:
10326 if (index != 0 || This->cImplTypes)
10327 return TYPE_E_ELEMENTNOTFOUND;
10328 break;
10329 default:
10330 FIXME("Unimplemented typekind: %d\n", This->typekind);
10331 return E_NOTIMPL;
10334 if (This->impltypes){
10335 UINT i;
10337 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10338 sizeof(TLBImplType) * (This->cImplTypes + 1));
10340 if (index < This->cImplTypes) {
10341 memmove(This->impltypes + index + 1, This->impltypes + index,
10342 (This->cImplTypes - index) * sizeof(TLBImplType));
10343 impl_type = This->impltypes + index;
10344 } else
10345 impl_type = This->impltypes + This->cImplTypes;
10347 /* move custdata lists to the new memory location */
10348 for(i = 0; i < This->cImplTypes + 1; ++i){
10349 if(index != i){
10350 TLBImplType *it = &This->impltypes[i];
10351 if(it->custdata_list.prev == it->custdata_list.next)
10352 list_init(&it->custdata_list);
10353 else{
10354 it->custdata_list.prev->next = &it->custdata_list;
10355 it->custdata_list.next->prev = &it->custdata_list;
10359 } else
10360 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10362 memset(impl_type, 0, sizeof(TLBImplType));
10363 TLBImplType_Constructor(impl_type);
10364 impl_type->hRef = refType;
10366 ++This->cImplTypes;
10368 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10369 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10371 hres = ICreateTypeInfo2_LayOut(iface);
10372 if (FAILED(hres))
10373 return hres;
10375 return S_OK;
10378 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10379 UINT index, INT implTypeFlags)
10381 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10382 TLBImplType *impl_type = &This->impltypes[index];
10384 TRACE("%p %u %x\n", This, index, implTypeFlags);
10386 if (This->typekind != TKIND_COCLASS)
10387 return TYPE_E_BADMODULEKIND;
10389 if (index >= This->cImplTypes)
10390 return TYPE_E_ELEMENTNOTFOUND;
10392 impl_type->implflags = implTypeFlags;
10394 return S_OK;
10397 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10398 WORD alignment)
10400 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10402 TRACE("%p %d\n", This, alignment);
10404 This->cbAlignment = alignment;
10406 return S_OK;
10409 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10410 LPOLESTR schema)
10412 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10414 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10416 if (!schema)
10417 return E_INVALIDARG;
10419 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10421 This->lpstrSchema = This->Schema->str;
10423 return S_OK;
10426 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10427 UINT index, VARDESC *varDesc)
10429 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10430 TLBVarDesc *var_desc;
10432 TRACE("%p %u %p\n", This, index, varDesc);
10434 if (This->vardescs){
10435 UINT i;
10437 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10438 sizeof(TLBVarDesc) * (This->cVars + 1));
10440 if (index < This->cVars) {
10441 memmove(This->vardescs + index + 1, This->vardescs + index,
10442 (This->cVars - index) * sizeof(TLBVarDesc));
10443 var_desc = This->vardescs + index;
10444 } else
10445 var_desc = This->vardescs + This->cVars;
10447 /* move custdata lists to the new memory location */
10448 for(i = 0; i < This->cVars + 1; ++i){
10449 if(index != i){
10450 TLBVarDesc *var = &This->vardescs[i];
10451 if(var->custdata_list.prev == var->custdata_list.next)
10452 list_init(&var->custdata_list);
10453 else{
10454 var->custdata_list.prev->next = &var->custdata_list;
10455 var->custdata_list.next->prev = &var->custdata_list;
10459 } else
10460 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10462 TLBVarDesc_Constructor(var_desc);
10463 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10464 var_desc->vardesc = *var_desc->vardesc_create;
10466 ++This->cVars;
10468 This->needs_layout = TRUE;
10470 return S_OK;
10473 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10474 UINT index, LPOLESTR *names, UINT numNames)
10476 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10477 TLBFuncDesc *func_desc = &This->funcdescs[index];
10478 int i;
10480 TRACE("%p %u %p %u\n", This, index, names, numNames);
10482 if (!names)
10483 return E_INVALIDARG;
10485 if (index >= This->cFuncs || numNames == 0)
10486 return TYPE_E_ELEMENTNOTFOUND;
10488 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10489 if(numNames > func_desc->funcdesc.cParams)
10490 return TYPE_E_ELEMENTNOTFOUND;
10491 } else
10492 if(numNames > func_desc->funcdesc.cParams + 1)
10493 return TYPE_E_ELEMENTNOTFOUND;
10495 for(i = 0; i < This->cFuncs; ++i) {
10496 TLBFuncDesc *iter = &This->funcdescs[i];
10497 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10498 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10499 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10500 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10501 continue;
10502 return TYPE_E_AMBIGUOUSNAME;
10506 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10508 for (i = 1; i < numNames; ++i) {
10509 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10510 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10513 return S_OK;
10516 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10517 UINT index, LPOLESTR name)
10519 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10520 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(name));
10521 return E_NOTIMPL;
10524 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10525 TYPEDESC *tdescAlias)
10527 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10528 FIXME("%p %p - stub\n", This, tdescAlias);
10529 return E_NOTIMPL;
10532 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10533 UINT index, LPOLESTR dllName, LPOLESTR procName)
10535 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10536 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10537 return E_NOTIMPL;
10540 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10541 UINT index, LPOLESTR docString)
10543 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10544 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
10545 return E_NOTIMPL;
10548 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10549 UINT index, LPOLESTR docString)
10551 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10552 TLBVarDesc *var_desc = &This->vardescs[index];
10554 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10556 if(!docString)
10557 return E_INVALIDARG;
10559 if(index >= This->cVars)
10560 return TYPE_E_ELEMENTNOTFOUND;
10562 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10564 return S_OK;
10567 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10568 UINT index, DWORD helpContext)
10570 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10571 TLBFuncDesc *func_desc = &This->funcdescs[index];
10573 TRACE("%p %u %d\n", This, index, helpContext);
10575 if(index >= This->cFuncs)
10576 return TYPE_E_ELEMENTNOTFOUND;
10578 func_desc->helpcontext = helpContext;
10580 return S_OK;
10583 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10584 UINT index, DWORD helpContext)
10586 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10587 TLBVarDesc *var_desc = &This->vardescs[index];
10589 TRACE("%p %u %d\n", This, index, helpContext);
10591 if(index >= This->cVars)
10592 return TYPE_E_ELEMENTNOTFOUND;
10594 var_desc->HelpContext = helpContext;
10596 return S_OK;
10599 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10600 UINT index, BSTR bstrMops)
10602 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10603 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10604 return E_NOTIMPL;
10607 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10608 IDLDESC *idlDesc)
10610 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10612 TRACE("%p %p\n", This, idlDesc);
10614 if (!idlDesc)
10615 return E_INVALIDARG;
10617 This->idldescType.dwReserved = idlDesc->dwReserved;
10618 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10620 return S_OK;
10623 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10625 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10626 ITypeInfo *tinfo;
10627 TLBFuncDesc *func_desc;
10628 UINT user_vft = 0, i, depth = 0;
10629 HRESULT hres = S_OK;
10631 TRACE("%p\n", This);
10633 This->needs_layout = FALSE;
10635 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10636 if (FAILED(hres))
10637 return hres;
10639 if (This->typekind == TKIND_INTERFACE) {
10640 ITypeInfo *inh;
10641 TYPEATTR *attr;
10642 HREFTYPE inh_href;
10644 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10646 if (SUCCEEDED(hres)) {
10647 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10649 if (SUCCEEDED(hres)) {
10650 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10651 if (FAILED(hres)) {
10652 ITypeInfo_Release(inh);
10653 ITypeInfo_Release(tinfo);
10654 return hres;
10656 This->cbSizeVft = attr->cbSizeVft;
10657 ITypeInfo_ReleaseTypeAttr(inh, attr);
10660 ++depth;
10661 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10662 if(SUCCEEDED(hres)){
10663 ITypeInfo *next;
10664 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10665 if(SUCCEEDED(hres)){
10666 ITypeInfo_Release(inh);
10667 inh = next;
10670 }while(SUCCEEDED(hres));
10671 hres = S_OK;
10673 ITypeInfo_Release(inh);
10674 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10675 This->cbSizeVft = 0;
10676 hres = S_OK;
10677 } else {
10678 ITypeInfo_Release(tinfo);
10679 return hres;
10681 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10682 This->cbSizeVft = 0;
10683 hres = S_OK;
10684 } else {
10685 ITypeInfo_Release(tinfo);
10686 return hres;
10688 } else if (This->typekind == TKIND_DISPATCH)
10689 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10690 else
10691 This->cbSizeVft = 0;
10693 func_desc = This->funcdescs;
10694 i = 0;
10695 while (i < This->cFuncs) {
10696 if (!(func_desc->funcdesc.oVft & 0x1))
10697 func_desc->funcdesc.oVft = This->cbSizeVft;
10699 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10700 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10702 This->cbSizeVft += This->pTypeLib->ptr_size;
10704 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10705 TLBFuncDesc *iter;
10706 UINT j = 0;
10707 BOOL reset = FALSE;
10709 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10711 iter = This->funcdescs;
10712 while (j < This->cFuncs) {
10713 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10714 if (!reset) {
10715 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10716 reset = TRUE;
10717 } else
10718 ++func_desc->funcdesc.memid;
10719 iter = This->funcdescs;
10720 j = 0;
10721 } else {
10722 ++iter;
10723 ++j;
10728 ++func_desc;
10729 ++i;
10732 if (user_vft > This->cbSizeVft)
10733 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10735 ITypeInfo_Release(tinfo);
10736 return hres;
10739 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
10740 UINT index)
10742 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10743 FIXME("%p %u - stub\n", This, index);
10744 return E_NOTIMPL;
10747 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
10748 MEMBERID memid, INVOKEKIND invKind)
10750 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10751 FIXME("%p %x %d - stub\n", This, memid, invKind);
10752 return E_NOTIMPL;
10755 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
10756 UINT index)
10758 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10759 FIXME("%p %u - stub\n", This, index);
10760 return E_NOTIMPL;
10763 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
10764 MEMBERID memid)
10766 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10767 FIXME("%p %x - stub\n", This, memid);
10768 return E_NOTIMPL;
10771 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
10772 UINT index)
10774 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10775 FIXME("%p %u - stub\n", This, index);
10776 return E_NOTIMPL;
10779 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
10780 REFGUID guid, VARIANT *varVal)
10782 TLBGuid *tlbguid;
10784 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10786 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10788 if (!guid || !varVal)
10789 return E_INVALIDARG;
10791 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
10793 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
10796 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
10797 UINT index, REFGUID guid, VARIANT *varVal)
10799 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10800 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10801 return E_NOTIMPL;
10804 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
10805 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
10807 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10808 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
10809 return E_NOTIMPL;
10812 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
10813 UINT index, REFGUID guid, VARIANT *varVal)
10815 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10816 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10817 return E_NOTIMPL;
10820 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
10821 UINT index, REFGUID guid, VARIANT *varVal)
10823 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10824 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10825 return E_NOTIMPL;
10828 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
10829 ULONG helpStringContext)
10831 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10833 TRACE("%p %u\n", This, helpStringContext);
10835 This->dwHelpStringContext = helpStringContext;
10837 return S_OK;
10840 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
10841 UINT index, ULONG helpStringContext)
10843 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10844 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
10845 return E_NOTIMPL;
10848 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
10849 UINT index, ULONG helpStringContext)
10851 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10852 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
10853 return E_NOTIMPL;
10856 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
10858 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10859 FIXME("%p - stub\n", This);
10860 return E_NOTIMPL;
10863 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
10864 LPOLESTR name)
10866 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10868 TRACE("%p %s\n", This, wine_dbgstr_w(name));
10870 if (!name)
10871 return E_INVALIDARG;
10873 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
10875 return S_OK;
10878 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
10879 ICreateTypeInfo2_fnQueryInterface,
10880 ICreateTypeInfo2_fnAddRef,
10881 ICreateTypeInfo2_fnRelease,
10882 ICreateTypeInfo2_fnSetGuid,
10883 ICreateTypeInfo2_fnSetTypeFlags,
10884 ICreateTypeInfo2_fnSetDocString,
10885 ICreateTypeInfo2_fnSetHelpContext,
10886 ICreateTypeInfo2_fnSetVersion,
10887 ICreateTypeInfo2_fnAddRefTypeInfo,
10888 ICreateTypeInfo2_fnAddFuncDesc,
10889 ICreateTypeInfo2_fnAddImplType,
10890 ICreateTypeInfo2_fnSetImplTypeFlags,
10891 ICreateTypeInfo2_fnSetAlignment,
10892 ICreateTypeInfo2_fnSetSchema,
10893 ICreateTypeInfo2_fnAddVarDesc,
10894 ICreateTypeInfo2_fnSetFuncAndParamNames,
10895 ICreateTypeInfo2_fnSetVarName,
10896 ICreateTypeInfo2_fnSetTypeDescAlias,
10897 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
10898 ICreateTypeInfo2_fnSetFuncDocString,
10899 ICreateTypeInfo2_fnSetVarDocString,
10900 ICreateTypeInfo2_fnSetFuncHelpContext,
10901 ICreateTypeInfo2_fnSetVarHelpContext,
10902 ICreateTypeInfo2_fnSetMops,
10903 ICreateTypeInfo2_fnSetTypeIdldesc,
10904 ICreateTypeInfo2_fnLayOut,
10905 ICreateTypeInfo2_fnDeleteFuncDesc,
10906 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
10907 ICreateTypeInfo2_fnDeleteVarDesc,
10908 ICreateTypeInfo2_fnDeleteVarDescByMemId,
10909 ICreateTypeInfo2_fnDeleteImplType,
10910 ICreateTypeInfo2_fnSetCustData,
10911 ICreateTypeInfo2_fnSetFuncCustData,
10912 ICreateTypeInfo2_fnSetParamCustData,
10913 ICreateTypeInfo2_fnSetVarCustData,
10914 ICreateTypeInfo2_fnSetImplTypeCustData,
10915 ICreateTypeInfo2_fnSetHelpStringContext,
10916 ICreateTypeInfo2_fnSetFuncHelpStringContext,
10917 ICreateTypeInfo2_fnSetVarHelpStringContext,
10918 ICreateTypeInfo2_fnInvalidate,
10919 ICreateTypeInfo2_fnSetName
10922 /******************************************************************************
10923 * ClearCustData (OLEAUT32.171)
10925 * Clear a custom data type's data.
10927 * PARAMS
10928 * lpCust [I] The custom data type instance
10930 * RETURNS
10931 * Nothing.
10933 void WINAPI ClearCustData(CUSTDATA *lpCust)
10935 if (lpCust && lpCust->cCustData)
10937 if (lpCust->prgCustData)
10939 DWORD i;
10941 for (i = 0; i < lpCust->cCustData; i++)
10942 VariantClear(&lpCust->prgCustData[i].varValue);
10944 /* FIXME - Should be using a per-thread IMalloc */
10945 heap_free(lpCust->prgCustData);
10946 lpCust->prgCustData = NULL;
10948 lpCust->cCustData = 0;