include: Fix off-by-one error in EmfPlusRecordType enumeration.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob812612ac99c47a734090fe8da7b667d62d191047
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);
289 struct tlibredirect_data
291 ULONG size;
292 DWORD res;
293 ULONG name_len;
294 ULONG name_offset;
295 LANGID langid;
296 WORD flags;
297 ULONG help_len;
298 ULONG help_offset;
299 WORD major_version;
300 WORD minor_version;
303 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
304 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
305 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
307 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
308 LCID myLCID = lcid;
309 HKEY hkey;
310 WCHAR buffer[60];
311 WCHAR Path[MAX_PATH];
312 LONG res;
314 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
316 if (redir)
318 ACTCTX_SECTION_KEYED_DATA data;
320 data.cbSize = sizeof(data);
321 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
323 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
324 WCHAR *nameW;
325 DWORD len;
327 if (tlib->major_version != wMaj || tlib->minor_version < wMin)
328 return TYPE_E_LIBNOTREGISTERED;
330 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
331 len = SearchPathW( NULL, nameW, NULL, sizeof(Path)/sizeof(WCHAR), Path, NULL );
332 if (!len) return TYPE_E_LIBNOTREGISTERED;
334 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
335 *path = SysAllocString( Path );
336 return S_OK;
340 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
341 get_typelib_key( guid, wMaj, wMin, buffer );
343 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
344 if (res == ERROR_FILE_NOT_FOUND)
346 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
347 return TYPE_E_LIBNOTREGISTERED;
349 else if (res != ERROR_SUCCESS)
351 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
352 return TYPE_E_REGISTRYACCESS;
355 while (hr != S_OK)
357 LONG dwPathLen = sizeof(Path);
359 get_lcid_subkey( myLCID, syskind, buffer );
361 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
363 if (!lcid)
364 break;
365 else if (myLCID == lcid)
367 /* try with sub-langid */
368 myLCID = SUBLANGID(lcid);
370 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
372 /* try with system langid */
373 myLCID = 0;
375 else
377 break;
380 else
382 *path = SysAllocString( Path );
383 hr = S_OK;
386 RegCloseKey( hkey );
387 TRACE_(typelib)("-- 0x%08x\n", hr);
388 return hr;
391 /****************************************************************************
392 * QueryPathOfRegTypeLib [OLEAUT32.164]
394 * Gets the path to a registered type library.
396 * PARAMS
397 * guid [I] referenced guid
398 * wMaj [I] major version
399 * wMin [I] minor version
400 * lcid [I] locale id
401 * path [O] path of typelib
403 * RETURNS
404 * Success: S_OK.
405 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
406 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
407 * opened.
409 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
411 BOOL redir = TRUE;
412 #ifdef _WIN64
413 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
414 if(SUCCEEDED(hres))
415 return hres;
416 redir = FALSE;
417 #endif
418 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
421 /******************************************************************************
422 * CreateTypeLib [OLEAUT32.160] creates a typelib
424 * RETURNS
425 * Success: S_OK
426 * Failure: Status
428 HRESULT WINAPI CreateTypeLib(
429 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
431 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
432 return E_FAIL;
435 /******************************************************************************
436 * LoadTypeLib [OLEAUT32.161]
438 * Loads a type library
440 * PARAMS
441 * szFile [I] Name of file to load from.
442 * pptLib [O] Pointer that receives ITypeLib object on success.
444 * RETURNS
445 * Success: S_OK
446 * Failure: Status
448 * SEE
449 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
451 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
453 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
454 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
457 /******************************************************************************
458 * LoadTypeLibEx [OLEAUT32.183]
460 * Loads and optionally registers a type library
462 * RETURNS
463 * Success: S_OK
464 * Failure: Status
466 HRESULT WINAPI LoadTypeLibEx(
467 LPCOLESTR szFile, /* [in] Name of file to load from */
468 REGKIND regkind, /* [in] Specify kind of registration */
469 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
471 WCHAR szPath[MAX_PATH+1];
472 HRESULT res;
474 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
476 *pptLib = NULL;
478 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
480 if (SUCCEEDED(res))
481 switch(regkind)
483 case REGKIND_DEFAULT:
484 /* don't register typelibs supplied with full path. Experimentation confirms the following */
485 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
486 (szFile[0] && (szFile[1] == ':'))) break;
487 /* else fall-through */
489 case REGKIND_REGISTER:
490 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
492 ITypeLib_Release(*pptLib);
493 *pptLib = 0;
495 break;
496 case REGKIND_NONE:
497 break;
500 TRACE(" returns %08x\n",res);
501 return res;
504 /******************************************************************************
505 * LoadRegTypeLib [OLEAUT32.162]
507 * Loads a registered type library.
509 * PARAMS
510 * rguid [I] GUID of the registered type library.
511 * wVerMajor [I] major version.
512 * wVerMinor [I] minor version.
513 * lcid [I] locale ID.
514 * ppTLib [O] pointer that receives an ITypeLib object on success.
516 * RETURNS
517 * Success: S_OK.
518 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
519 * LoadTypeLib.
521 HRESULT WINAPI LoadRegTypeLib(
522 REFGUID rguid,
523 WORD wVerMajor,
524 WORD wVerMinor,
525 LCID lcid,
526 ITypeLib **ppTLib)
528 BSTR bstr=NULL;
529 HRESULT res;
531 *ppTLib = NULL;
533 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
535 if(SUCCEEDED(res))
537 res= LoadTypeLib(bstr, ppTLib);
538 SysFreeString(bstr);
540 if (*ppTLib)
542 TLIBATTR *attr;
544 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
545 if (res == S_OK && (attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor))
547 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
548 ITypeLib_Release(*ppTLib);
549 *ppTLib = NULL;
550 res = TYPE_E_LIBNOTREGISTERED;
555 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
557 return res;
561 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
562 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
563 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
564 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
565 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
566 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
568 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
570 WCHAR keyName[60];
571 HKEY key, subKey;
573 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
574 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
575 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
577 get_interface_key( &tattr->guid, keyName );
578 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
579 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
581 if (name)
582 RegSetValueExW(key, NULL, 0, REG_SZ,
583 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
585 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
586 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
587 RegSetValueExW(subKey, NULL, 0, REG_SZ,
588 (const BYTE *)PSOA, sizeof PSOA);
589 RegCloseKey(subKey);
592 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
593 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
594 RegSetValueExW(subKey, NULL, 0, REG_SZ,
595 (const BYTE *)PSOA, sizeof PSOA);
596 RegCloseKey(subKey);
599 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
600 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
602 WCHAR buffer[40];
603 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
604 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
606 StringFromGUID2(&libattr->guid, buffer, 40);
607 RegSetValueExW(subKey, NULL, 0, REG_SZ,
608 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
609 sprintfW(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
610 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
611 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
612 RegCloseKey(subKey);
615 RegCloseKey(key);
619 /******************************************************************************
620 * RegisterTypeLib [OLEAUT32.163]
621 * Adds information about a type library to the System Registry
622 * NOTES
623 * Docs: ITypeLib FAR * ptlib
624 * Docs: OLECHAR FAR* szFullPath
625 * Docs: OLECHAR FAR* szHelpDir
627 * RETURNS
628 * Success: S_OK
629 * Failure: Status
631 HRESULT WINAPI RegisterTypeLib(
632 ITypeLib * ptlib, /* [in] Pointer to the library*/
633 OLECHAR * szFullPath, /* [in] full Path of the library*/
634 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
635 may be NULL*/
637 HRESULT res;
638 TLIBATTR *attr;
639 WCHAR keyName[60];
640 WCHAR tmp[16];
641 HKEY key, subKey;
642 UINT types, tidx;
643 TYPEKIND kind;
644 DWORD disposition;
646 if (ptlib == NULL || szFullPath == NULL)
647 return E_INVALIDARG;
649 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
650 return E_FAIL;
652 #ifndef _WIN64
653 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
654 #endif
656 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
658 res = S_OK;
659 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
660 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
662 LPOLESTR doc;
664 /* Set the human-readable name of the typelib */
665 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
666 res = E_FAIL;
667 else if (doc)
669 if (RegSetValueExW(key, NULL, 0, REG_SZ,
670 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
671 res = E_FAIL;
673 SysFreeString(doc);
676 /* Make up the name of the typelib path subkey */
677 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
679 /* Create the typelib path subkey */
680 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
681 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
683 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
684 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
685 res = E_FAIL;
687 RegCloseKey(subKey);
689 else
690 res = E_FAIL;
692 /* Create the flags subkey */
693 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
694 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
696 /* FIXME: is %u correct? */
697 static const WCHAR formatW[] = {'%','u',0};
698 WCHAR buf[20];
699 sprintfW(buf, formatW, attr->wLibFlags);
700 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
701 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
702 res = E_FAIL;
704 RegCloseKey(subKey);
706 else
707 res = E_FAIL;
709 /* create the helpdir subkey */
710 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
711 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
713 BOOL freeHelpDir = FALSE;
714 OLECHAR* pIndexStr;
716 /* if we created a new key, and helpDir was null, set the helpdir
717 to the directory which contains the typelib. However,
718 if we just opened an existing key, we leave the helpdir alone */
719 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
720 szHelpDir = SysAllocString(szFullPath);
721 pIndexStr = strrchrW(szHelpDir, '\\');
722 if (pIndexStr) {
723 *pIndexStr = 0;
725 freeHelpDir = TRUE;
728 /* if we have an szHelpDir, set it! */
729 if (szHelpDir != NULL) {
730 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
731 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
732 res = E_FAIL;
736 /* tidy up */
737 if (freeHelpDir) SysFreeString(szHelpDir);
738 RegCloseKey(subKey);
740 } else {
741 res = E_FAIL;
744 RegCloseKey(key);
746 else
747 res = E_FAIL;
749 /* register OLE Automation-compatible interfaces for this typelib */
750 types = ITypeLib_GetTypeInfoCount(ptlib);
751 for (tidx=0; tidx<types; tidx++) {
752 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
753 LPOLESTR name = NULL;
754 ITypeInfo *tinfo = NULL;
756 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
758 switch (kind) {
759 case TKIND_INTERFACE:
760 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
761 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
762 break;
764 case TKIND_DISPATCH:
765 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
766 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
767 break;
769 default:
770 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
771 break;
774 if (tinfo) {
775 TYPEATTR *tattr = NULL;
776 ITypeInfo_GetTypeAttr(tinfo, &tattr);
778 if (tattr) {
779 TRACE_(typelib)("guid=%s, flags=%04x (",
780 debugstr_guid(&tattr->guid),
781 tattr->wTypeFlags);
783 if (TRACE_ON(typelib)) {
784 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
785 XX(FAPPOBJECT);
786 XX(FCANCREATE);
787 XX(FLICENSED);
788 XX(FPREDECLID);
789 XX(FHIDDEN);
790 XX(FCONTROL);
791 XX(FDUAL);
792 XX(FNONEXTENSIBLE);
793 XX(FOLEAUTOMATION);
794 XX(FRESTRICTED);
795 XX(FAGGREGATABLE);
796 XX(FREPLACEABLE);
797 XX(FDISPATCHABLE);
798 XX(FREVERSEBIND);
799 XX(FPROXY);
800 #undef XX
801 MESSAGE("\n");
804 /* Register all dispinterfaces (which includes dual interfaces) and
805 oleautomation interfaces */
806 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
807 kind == TKIND_DISPATCH)
809 BOOL is_wow64;
810 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
812 /* register interface<->typelib coupling */
813 TLB_register_interface(attr, name, tattr, 0);
815 /* register TLBs into the opposite registry view, too */
816 if(opposite == KEY_WOW64_32KEY ||
817 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
818 TLB_register_interface(attr, name, tattr, opposite);
821 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
824 ITypeInfo_Release(tinfo);
827 SysFreeString(name);
831 ITypeLib_ReleaseTLibAttr(ptlib, attr);
833 return res;
837 /******************************************************************************
838 * UnRegisterTypeLib [OLEAUT32.186]
839 * Removes information about a type library from the System Registry
840 * NOTES
842 * RETURNS
843 * Success: S_OK
844 * Failure: Status
846 HRESULT WINAPI UnRegisterTypeLib(
847 REFGUID libid, /* [in] Guid of the library */
848 WORD wVerMajor, /* [in] major version */
849 WORD wVerMinor, /* [in] minor version */
850 LCID lcid, /* [in] locale id */
851 SYSKIND syskind)
853 BSTR tlibPath = NULL;
854 DWORD tmpLength;
855 WCHAR keyName[60];
856 WCHAR subKeyName[50];
857 int result = S_OK;
858 DWORD i = 0;
859 BOOL deleteOtherStuff;
860 HKEY key = NULL;
861 HKEY subKey = NULL;
862 TYPEATTR* typeAttr = NULL;
863 TYPEKIND kind;
864 ITypeInfo* typeInfo = NULL;
865 ITypeLib* typeLib = NULL;
866 int numTypes;
868 TRACE("(IID: %s)\n",debugstr_guid(libid));
870 /* Create the path to the key */
871 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
873 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
875 TRACE("Unsupported syskind %i\n", syskind);
876 result = E_INVALIDARG;
877 goto end;
880 /* get the path to the typelib on disk */
881 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
882 result = E_INVALIDARG;
883 goto end;
886 /* Try and open the key to the type library. */
887 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
888 result = E_INVALIDARG;
889 goto end;
892 /* Try and load the type library */
893 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
894 result = TYPE_E_INVALIDSTATE;
895 goto end;
898 /* remove any types registered with this typelib */
899 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
900 for (i=0; i<numTypes; i++) {
901 /* get the kind of type */
902 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
903 goto enddeleteloop;
906 /* skip non-interfaces, and get type info for the type */
907 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
908 goto enddeleteloop;
910 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
911 goto enddeleteloop;
913 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
914 goto enddeleteloop;
917 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
918 kind == TKIND_DISPATCH)
920 /* the path to the type */
921 get_interface_key( &typeAttr->guid, subKeyName );
923 /* Delete its bits */
924 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
925 goto enddeleteloop;
927 RegDeleteKeyW(subKey, ProxyStubClsidW);
928 RegDeleteKeyW(subKey, ProxyStubClsid32W);
929 RegDeleteKeyW(subKey, TypeLibW);
930 RegCloseKey(subKey);
931 subKey = NULL;
932 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
935 enddeleteloop:
936 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
937 typeAttr = NULL;
938 if (typeInfo) ITypeInfo_Release(typeInfo);
939 typeInfo = NULL;
942 /* Now, delete the type library path subkey */
943 get_lcid_subkey( lcid, syskind, subKeyName );
944 RegDeleteKeyW(key, subKeyName);
945 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
946 RegDeleteKeyW(key, subKeyName);
948 /* check if there is anything besides the FLAGS/HELPDIR keys.
949 If there is, we don't delete them */
950 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
951 deleteOtherStuff = TRUE;
952 i = 0;
953 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
954 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
956 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
957 if (!strcmpW(subKeyName, FLAGSW)) continue;
958 if (!strcmpW(subKeyName, HELPDIRW)) continue;
959 deleteOtherStuff = FALSE;
960 break;
963 /* only delete the other parts of the key if we're absolutely sure */
964 if (deleteOtherStuff) {
965 RegDeleteKeyW(key, FLAGSW);
966 RegDeleteKeyW(key, HELPDIRW);
967 RegCloseKey(key);
968 key = NULL;
970 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
971 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
972 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
975 end:
976 SysFreeString(tlibPath);
977 if (typeLib) ITypeLib_Release(typeLib);
978 if (subKey) RegCloseKey(subKey);
979 if (key) RegCloseKey(key);
980 return result;
983 /******************************************************************************
984 * RegisterTypeLibForUser [OLEAUT32.442]
985 * Adds information about a type library to the user registry
986 * NOTES
987 * Docs: ITypeLib FAR * ptlib
988 * Docs: OLECHAR FAR* szFullPath
989 * Docs: OLECHAR FAR* szHelpDir
991 * RETURNS
992 * Success: S_OK
993 * Failure: Status
995 HRESULT WINAPI RegisterTypeLibForUser(
996 ITypeLib * ptlib, /* [in] Pointer to the library*/
997 OLECHAR * szFullPath, /* [in] full Path of the library*/
998 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
999 may be NULL*/
1001 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1002 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1003 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1006 /******************************************************************************
1007 * UnRegisterTypeLibForUser [OLEAUT32.443]
1008 * Removes information about a type library from the user registry
1010 * RETURNS
1011 * Success: S_OK
1012 * Failure: Status
1014 HRESULT WINAPI UnRegisterTypeLibForUser(
1015 REFGUID libid, /* [in] GUID of the library */
1016 WORD wVerMajor, /* [in] major version */
1017 WORD wVerMinor, /* [in] minor version */
1018 LCID lcid, /* [in] locale id */
1019 SYSKIND syskind)
1021 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1022 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1023 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1026 /*======================= ITypeLib implementation =======================*/
1028 typedef struct tagTLBGuid {
1029 GUID guid;
1030 INT hreftype;
1031 UINT offset;
1032 struct list entry;
1033 } TLBGuid;
1035 typedef struct tagTLBCustData
1037 TLBGuid *guid;
1038 VARIANT data;
1039 struct list entry;
1040 } TLBCustData;
1042 /* data structure for import typelibs */
1043 typedef struct tagTLBImpLib
1045 int offset; /* offset in the file (MSFT)
1046 offset in nametable (SLTG)
1047 just used to identify library while reading
1048 data from file */
1049 TLBGuid *guid; /* libid */
1050 BSTR name; /* name */
1052 LCID lcid; /* lcid of imported typelib */
1054 WORD wVersionMajor; /* major version number */
1055 WORD wVersionMinor; /* minor version number */
1057 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1058 NULL if not yet loaded */
1059 struct list entry;
1060 } TLBImpLib;
1062 typedef struct tagTLBString {
1063 BSTR str;
1064 UINT offset;
1065 struct list entry;
1066 } TLBString;
1068 /* internal ITypeLib data */
1069 typedef struct tagITypeLibImpl
1071 ITypeLib2 ITypeLib2_iface;
1072 ITypeComp ITypeComp_iface;
1073 ICreateTypeLib2 ICreateTypeLib2_iface;
1074 LONG ref;
1075 TLBGuid *guid;
1076 LCID lcid;
1077 SYSKIND syskind;
1078 int ptr_size;
1079 WORD ver_major;
1080 WORD ver_minor;
1081 WORD libflags;
1082 LCID set_lcid;
1084 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1085 * exported to the application as a UNICODE string.
1087 struct list string_list;
1088 struct list name_list;
1089 struct list guid_list;
1091 const TLBString *Name;
1092 const TLBString *DocString;
1093 const TLBString *HelpFile;
1094 const TLBString *HelpStringDll;
1095 DWORD dwHelpContext;
1096 int TypeInfoCount; /* nr of typeinfo's in librarry */
1097 struct tagITypeInfoImpl **typeinfos;
1098 struct list custdata_list;
1099 struct list implib_list;
1100 int ctTypeDesc; /* number of items in type desc array */
1101 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1102 library. Only used while reading MSFT
1103 typelibs */
1104 struct list ref_list; /* list of ref types in this typelib */
1105 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1108 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1109 struct list entry;
1110 WCHAR *path;
1111 INT index;
1112 } ITypeLibImpl;
1114 static const ITypeLib2Vtbl tlbvt;
1115 static const ITypeCompVtbl tlbtcvt;
1116 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1118 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1120 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1123 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1125 return impl_from_ITypeLib2((ITypeLib2*)iface);
1128 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1130 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1133 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1135 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1138 /* ITypeLib methods */
1139 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1140 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1142 /*======================= ITypeInfo implementation =======================*/
1144 /* data for referenced types */
1145 typedef struct tagTLBRefType
1147 INT index; /* Type index for internal ref or for external ref
1148 it the format is SLTG. -2 indicates to
1149 use guid */
1151 TYPEKIND tkind;
1152 TLBGuid *guid; /* guid of the referenced type */
1153 /* if index == TLB_REF_USE_GUID */
1155 HREFTYPE reference; /* The href of this ref */
1156 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1157 TLB_REF_INTERNAL for internal refs
1158 TLB_REF_NOT_FOUND for broken refs */
1160 struct list entry;
1161 } TLBRefType;
1163 #define TLB_REF_USE_GUID -2
1165 #define TLB_REF_INTERNAL (void*)-2
1166 #define TLB_REF_NOT_FOUND (void*)-1
1168 /* internal Parameter data */
1169 typedef struct tagTLBParDesc
1171 const TLBString *Name;
1172 struct list custdata_list;
1173 } TLBParDesc;
1175 /* internal Function data */
1176 typedef struct tagTLBFuncDesc
1178 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1179 const TLBString *Name; /* the name of this function */
1180 TLBParDesc *pParamDesc; /* array with param names and custom data */
1181 int helpcontext;
1182 int HelpStringContext;
1183 const TLBString *HelpString;
1184 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1185 struct list custdata_list;
1186 } TLBFuncDesc;
1188 /* internal Variable data */
1189 typedef struct tagTLBVarDesc
1191 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1192 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1193 const TLBString *Name; /* the name of this variable */
1194 int HelpContext;
1195 int HelpStringContext;
1196 const TLBString *HelpString;
1197 struct list custdata_list;
1198 } TLBVarDesc;
1200 /* internal implemented interface data */
1201 typedef struct tagTLBImplType
1203 HREFTYPE hRef; /* hRef of interface */
1204 int implflags; /* IMPLFLAG_*s */
1205 struct list custdata_list;
1206 } TLBImplType;
1208 /* internal TypeInfo data */
1209 typedef struct tagITypeInfoImpl
1211 ITypeInfo2 ITypeInfo2_iface;
1212 ITypeComp ITypeComp_iface;
1213 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1214 LONG ref;
1215 BOOL not_attached_to_typelib;
1216 BOOL needs_layout;
1218 TLBGuid *guid;
1219 LCID lcid;
1220 MEMBERID memidConstructor;
1221 MEMBERID memidDestructor;
1222 LPOLESTR lpstrSchema;
1223 ULONG cbSizeInstance;
1224 TYPEKIND typekind;
1225 WORD cFuncs;
1226 WORD cVars;
1227 WORD cImplTypes;
1228 WORD cbSizeVft;
1229 WORD cbAlignment;
1230 WORD wTypeFlags;
1231 WORD wMajorVerNum;
1232 WORD wMinorVerNum;
1233 TYPEDESC *tdescAlias;
1234 IDLDESC idldescType;
1236 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1237 int index; /* index in this typelib; */
1238 HREFTYPE hreftype; /* hreftype for app object binding */
1239 /* type libs seem to store the doc strings in ascii
1240 * so why should we do it in unicode?
1242 const TLBString *Name;
1243 const TLBString *DocString;
1244 const TLBString *DllName;
1245 const TLBString *Schema;
1246 DWORD dwHelpContext;
1247 DWORD dwHelpStringContext;
1249 /* functions */
1250 TLBFuncDesc *funcdescs;
1252 /* variables */
1253 TLBVarDesc *vardescs;
1255 /* Implemented Interfaces */
1256 TLBImplType *impltypes;
1258 struct list *pcustdata_list;
1259 struct list custdata_list;
1260 } ITypeInfoImpl;
1262 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1264 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1267 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1269 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1272 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1274 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1277 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1279 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1282 static const ITypeInfo2Vtbl tinfvt;
1283 static const ITypeCompVtbl tcompvt;
1284 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1286 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1287 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1289 typedef struct tagTLBContext
1291 unsigned int oStart; /* start of TLB in file */
1292 unsigned int pos; /* current pos */
1293 unsigned int length; /* total length */
1294 void *mapping; /* memory mapping */
1295 MSFT_SegDir * pTblDir;
1296 ITypeLibImpl* pLibInfo;
1297 } TLBContext;
1300 static inline BSTR TLB_get_bstr(const TLBString *str)
1302 return str != NULL ? str->str : NULL;
1305 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1307 if(!str)
1308 return 1;
1309 return memcmp(left, str->str, len);
1312 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1314 return guid != NULL ? &guid->guid : NULL;
1317 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1319 return guid != NULL ? &guid->guid : &GUID_NULL;
1322 static int get_ptr_size(SYSKIND syskind)
1324 switch(syskind){
1325 case SYS_WIN64:
1326 return 8;
1327 case SYS_WIN32:
1328 case SYS_MAC:
1329 case SYS_WIN16:
1330 return 4;
1332 WARN("Unhandled syskind: 0x%x\n", syskind);
1333 return 4;
1337 debug
1339 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1340 if (pTD->vt & VT_RESERVED)
1341 szVarType += strlen(strcpy(szVarType, "reserved | "));
1342 if (pTD->vt & VT_BYREF)
1343 szVarType += strlen(strcpy(szVarType, "ref to "));
1344 if (pTD->vt & VT_ARRAY)
1345 szVarType += strlen(strcpy(szVarType, "array of "));
1346 if (pTD->vt & VT_VECTOR)
1347 szVarType += strlen(strcpy(szVarType, "vector of "));
1348 switch(pTD->vt & VT_TYPEMASK) {
1349 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1350 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1351 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1352 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1353 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1354 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1355 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1356 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1357 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1358 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1359 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1360 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1361 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1362 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1363 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1364 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1365 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1366 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1367 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1368 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1369 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1370 pTD->u.hreftype); break;
1371 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1372 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1373 case VT_PTR: sprintf(szVarType, "ptr to ");
1374 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1375 break;
1376 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1377 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1378 break;
1379 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1380 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1381 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1382 break;
1384 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1388 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1389 char buf[200];
1390 USHORT flags = edesc->u.paramdesc.wParamFlags;
1391 dump_TypeDesc(&edesc->tdesc,buf);
1392 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1393 MESSAGE("\t\tu.paramdesc.wParamFlags");
1394 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1395 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1396 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1397 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1398 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1399 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1400 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1401 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1402 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1404 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1405 int i;
1406 MESSAGE("memid is %08x\n",funcdesc->memid);
1407 for (i=0;i<funcdesc->cParams;i++) {
1408 MESSAGE("Param %d:\n",i);
1409 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1411 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1412 switch (funcdesc->funckind) {
1413 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1414 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1415 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1416 case FUNC_STATIC: MESSAGE("static");break;
1417 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1418 default: MESSAGE("unknown");break;
1420 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1421 switch (funcdesc->invkind) {
1422 case INVOKE_FUNC: MESSAGE("func");break;
1423 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1424 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1425 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1427 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1428 switch (funcdesc->callconv) {
1429 case CC_CDECL: MESSAGE("cdecl");break;
1430 case CC_PASCAL: MESSAGE("pascal");break;
1431 case CC_STDCALL: MESSAGE("stdcall");break;
1432 case CC_SYSCALL: MESSAGE("syscall");break;
1433 default:break;
1435 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1436 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1437 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1439 MESSAGE("\telemdescFunc (return value type):\n");
1440 dump_ELEMDESC(&funcdesc->elemdescFunc);
1443 static const char * const typekind_desc[] =
1445 "TKIND_ENUM",
1446 "TKIND_RECORD",
1447 "TKIND_MODULE",
1448 "TKIND_INTERFACE",
1449 "TKIND_DISPATCH",
1450 "TKIND_COCLASS",
1451 "TKIND_ALIAS",
1452 "TKIND_UNION",
1453 "TKIND_MAX"
1456 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1458 int i;
1459 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1460 for (i=0;i<pfd->funcdesc.cParams;i++)
1461 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1464 dump_FUNCDESC(&(pfd->funcdesc));
1466 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1467 if(pfd->Entry == NULL)
1468 MESSAGE("\tentry: (null)\n");
1469 else if(pfd->Entry == (void*)-1)
1470 MESSAGE("\tentry: invalid\n");
1471 else if(IS_INTRESOURCE(pfd->Entry))
1472 MESSAGE("\tentry: %p\n", pfd->Entry);
1473 else
1474 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1476 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1478 while (n)
1480 dump_TLBFuncDescOne(pfd);
1481 ++pfd;
1482 --n;
1485 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1487 while (n)
1489 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1490 ++pvd;
1491 --n;
1495 static void dump_TLBImpLib(const TLBImpLib *import)
1497 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1498 debugstr_w(import->name));
1499 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1500 import->wVersionMinor, import->lcid, import->offset);
1503 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1505 TLBRefType *ref;
1507 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1509 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1510 if(ref->index == -1)
1511 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1512 else
1513 TRACE_(typelib)("type no: %d\n", ref->index);
1515 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1517 TRACE_(typelib)("in lib\n");
1518 dump_TLBImpLib(ref->pImpTLInfo);
1523 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1525 if(!impl)
1526 return;
1527 while (n) {
1528 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1529 impl->hRef, impl->implflags);
1530 ++impl;
1531 --n;
1535 static void dump_Variant(const VARIANT * pvar)
1537 SYSTEMTIME st;
1539 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1541 if (pvar)
1543 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1544 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1546 TRACE(",%p", V_BYREF(pvar));
1548 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1550 TRACE(",%p", V_ARRAY(pvar));
1552 else switch (V_TYPE(pvar))
1554 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1555 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1556 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1557 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1558 case VT_INT:
1559 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1560 case VT_UINT:
1561 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1562 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1563 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1564 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1565 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1566 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1567 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1568 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1569 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1570 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1571 V_CY(pvar).s.Lo); break;
1572 case VT_DATE:
1573 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1574 TRACE(",<invalid>");
1575 else
1576 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1577 st.wHour, st.wMinute, st.wSecond);
1578 break;
1579 case VT_ERROR:
1580 case VT_VOID:
1581 case VT_USERDEFINED:
1582 case VT_EMPTY:
1583 case VT_NULL: break;
1584 default: TRACE(",?"); break;
1587 TRACE("}\n");
1590 static void dump_DispParms(const DISPPARAMS * pdp)
1592 unsigned int index;
1594 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1596 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1598 TRACE("named args:\n");
1599 for (index = 0; index < pdp->cNamedArgs; index++)
1600 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1603 if (pdp->cArgs && pdp->rgvarg)
1605 TRACE("args:\n");
1606 for (index = 0; index < pdp->cArgs; index++)
1607 dump_Variant( &pdp->rgvarg[index] );
1611 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1613 TRACE("%p ref=%u\n", pty, pty->ref);
1614 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1615 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1616 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1617 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1618 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1619 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1620 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1621 if (TRACE_ON(ole))
1622 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1623 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1624 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1627 static void dump_VARDESC(const VARDESC *v)
1629 MESSAGE("memid %d\n",v->memid);
1630 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1631 MESSAGE("oInst %d\n",v->u.oInst);
1632 dump_ELEMDESC(&(v->elemdescVar));
1633 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1634 MESSAGE("varkind %d\n",v->varkind);
1637 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1639 /* VT_LPWSTR is largest type that, may appear in type description */
1640 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1641 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1642 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1643 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1644 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1645 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1646 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1647 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1650 static void TLB_abort(void)
1652 DebugBreak();
1655 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1657 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1658 if (!ret) ERR("cannot allocate memory\n");
1659 return ret;
1662 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1664 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1665 if (!ret) ERR("cannot allocate memory\n");
1666 return ret;
1669 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1671 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1674 void heap_free(void *ptr)
1676 HeapFree(GetProcessHeap(), 0, ptr);
1679 /* returns the size required for a deep copy of a typedesc into a
1680 * flat buffer */
1681 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1683 SIZE_T size = 0;
1685 if (alloc_initial_space)
1686 size += sizeof(TYPEDESC);
1688 switch (tdesc->vt)
1690 case VT_PTR:
1691 case VT_SAFEARRAY:
1692 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1693 break;
1694 case VT_CARRAY:
1695 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1696 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1697 break;
1699 return size;
1702 /* deep copy a typedesc into a flat buffer */
1703 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1705 if (!dest)
1707 dest = buffer;
1708 buffer = (char *)buffer + sizeof(TYPEDESC);
1711 *dest = *src;
1713 switch (src->vt)
1715 case VT_PTR:
1716 case VT_SAFEARRAY:
1717 dest->u.lptdesc = buffer;
1718 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1719 break;
1720 case VT_CARRAY:
1721 dest->u.lpadesc = buffer;
1722 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1723 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1724 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1725 break;
1727 return buffer;
1730 /* free custom data allocated by MSFT_CustData */
1731 static inline void TLB_FreeCustData(struct list *custdata_list)
1733 TLBCustData *cd, *cdn;
1734 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1736 list_remove(&cd->entry);
1737 VariantClear(&cd->data);
1738 heap_free(cd);
1742 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1744 DWORD len;
1745 BSTR ret;
1747 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1748 ret = SysAllocStringLen(NULL, len - 1);
1749 if (!ret) return ret;
1750 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1751 return ret;
1754 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1755 UINT n, MEMBERID memid)
1757 while(n){
1758 if(funcdescs->funcdesc.memid == memid)
1759 return funcdescs;
1760 ++funcdescs;
1761 --n;
1763 return NULL;
1766 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1767 UINT n, const OLECHAR *name)
1769 while(n){
1770 if(!lstrcmpiW(TLB_get_bstr(funcdescs->Name), name))
1771 return funcdescs;
1772 ++funcdescs;
1773 --n;
1775 return NULL;
1778 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1779 UINT n, MEMBERID memid)
1781 while(n){
1782 if(vardescs->vardesc.memid == memid)
1783 return vardescs;
1784 ++vardescs;
1785 --n;
1787 return NULL;
1790 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1791 UINT n, const OLECHAR *name)
1793 while(n){
1794 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1795 return vardescs;
1796 ++vardescs;
1797 --n;
1799 return NULL;
1802 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1804 TLBCustData *cust_data;
1805 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1806 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1807 return cust_data;
1808 return NULL;
1811 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1812 UINT n, const OLECHAR *name)
1814 while(n){
1815 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1816 return *typeinfos;
1817 ++typeinfos;
1818 --n;
1820 return NULL;
1823 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1825 list_init(&var_desc->custdata_list);
1828 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1830 TLBVarDesc *ret;
1832 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1833 if(!ret)
1834 return NULL;
1836 while(n){
1837 TLBVarDesc_Constructor(&ret[n-1]);
1838 --n;
1841 return ret;
1844 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1846 TLBParDesc *ret;
1848 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1849 if(!ret)
1850 return NULL;
1852 while(n){
1853 list_init(&ret[n-1].custdata_list);
1854 --n;
1857 return ret;
1860 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1862 list_init(&func_desc->custdata_list);
1865 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1867 TLBFuncDesc *ret;
1869 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1870 if(!ret)
1871 return NULL;
1873 while(n){
1874 TLBFuncDesc_Constructor(&ret[n-1]);
1875 --n;
1878 return ret;
1881 static void TLBImplType_Constructor(TLBImplType *impl)
1883 list_init(&impl->custdata_list);
1886 static TLBImplType *TLBImplType_Alloc(UINT n)
1888 TLBImplType *ret;
1890 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1891 if(!ret)
1892 return NULL;
1894 while(n){
1895 TLBImplType_Constructor(&ret[n-1]);
1896 --n;
1899 return ret;
1902 static TLBGuid *TLB_append_guid(struct list *guid_list,
1903 const GUID *new_guid, HREFTYPE hreftype)
1905 TLBGuid *guid;
1907 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1908 if (IsEqualGUID(&guid->guid, new_guid))
1909 return guid;
1912 guid = heap_alloc(sizeof(TLBGuid));
1913 if (!guid)
1914 return NULL;
1916 memcpy(&guid->guid, new_guid, sizeof(GUID));
1917 guid->hreftype = hreftype;
1919 list_add_tail(guid_list, &guid->entry);
1921 return guid;
1924 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1926 TLBCustData *cust_data;
1928 switch(V_VT(var)){
1929 case VT_I4:
1930 case VT_R4:
1931 case VT_UI4:
1932 case VT_INT:
1933 case VT_UINT:
1934 case VT_HRESULT:
1935 case VT_BSTR:
1936 break;
1937 default:
1938 return DISP_E_BADVARTYPE;
1941 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1943 if (!cust_data) {
1944 cust_data = heap_alloc(sizeof(TLBCustData));
1945 if (!cust_data)
1946 return E_OUTOFMEMORY;
1948 cust_data->guid = tlbguid;
1949 VariantInit(&cust_data->data);
1951 list_add_tail(custdata_list, &cust_data->entry);
1952 }else
1953 VariantClear(&cust_data->data);
1955 return VariantCopy(&cust_data->data, var);
1958 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1960 TLBString *str;
1962 if(!new_str)
1963 return NULL;
1965 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1966 if (strcmpW(str->str, new_str) == 0)
1967 return str;
1970 str = heap_alloc(sizeof(TLBString));
1971 if (!str)
1972 return NULL;
1974 str->str = SysAllocString(new_str);
1975 if (!str->str) {
1976 heap_free(str);
1977 return NULL;
1980 list_add_tail(string_list, &str->entry);
1982 return str;
1985 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1986 ULONG *size, WORD *align)
1988 ITypeInfo *other;
1989 TYPEATTR *attr;
1990 HRESULT hr;
1992 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1993 if(FAILED(hr))
1994 return hr;
1996 hr = ITypeInfo_GetTypeAttr(other, &attr);
1997 if(FAILED(hr)){
1998 ITypeInfo_Release(other);
1999 return hr;
2002 if(size)
2003 *size = attr->cbSizeInstance;
2004 if(align)
2005 *align = attr->cbAlignment;
2007 ITypeInfo_ReleaseTypeAttr(other, attr);
2008 ITypeInfo_Release(other);
2010 return S_OK;
2013 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
2014 TYPEDESC *tdesc, ULONG *size, WORD *align)
2016 ULONG i, sub, ptr_size;
2017 HRESULT hr;
2019 ptr_size = get_ptr_size(sys);
2021 switch(tdesc->vt){
2022 case VT_VOID:
2023 *size = 0;
2024 break;
2025 case VT_I1:
2026 case VT_UI1:
2027 *size = 1;
2028 break;
2029 case VT_I2:
2030 case VT_BOOL:
2031 case VT_UI2:
2032 *size = 2;
2033 break;
2034 case VT_I4:
2035 case VT_R4:
2036 case VT_ERROR:
2037 case VT_UI4:
2038 case VT_INT:
2039 case VT_UINT:
2040 case VT_HRESULT:
2041 *size = 4;
2042 break;
2043 case VT_R8:
2044 case VT_I8:
2045 case VT_UI8:
2046 *size = 8;
2047 break;
2048 case VT_BSTR:
2049 case VT_DISPATCH:
2050 case VT_UNKNOWN:
2051 case VT_PTR:
2052 case VT_SAFEARRAY:
2053 case VT_LPSTR:
2054 case VT_LPWSTR:
2055 *size = ptr_size;
2056 break;
2057 case VT_DATE:
2058 *size = sizeof(DATE);
2059 break;
2060 case VT_VARIANT:
2061 *size = sizeof(VARIANT);
2062 #ifdef _WIN64
2063 if(sys == SYS_WIN32)
2064 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2065 #endif
2066 break;
2067 case VT_DECIMAL:
2068 *size = sizeof(DECIMAL);
2069 break;
2070 case VT_CY:
2071 *size = sizeof(CY);
2072 break;
2073 case VT_CARRAY:
2074 *size = 0;
2075 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2076 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2077 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2078 if(FAILED(hr))
2079 return hr;
2080 *size *= sub;
2081 return S_OK;
2082 case VT_USERDEFINED:
2083 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2084 default:
2085 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2086 return E_FAIL;
2089 if(align){
2090 if(*size < 4)
2091 *align = *size;
2092 else
2093 *align = 4;
2096 return S_OK;
2099 /**********************************************************************
2101 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2103 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
2105 return pcx->pos;
2108 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2110 if (where != DO_NOT_SEEK)
2112 where += pcx->oStart;
2113 if (where > pcx->length)
2115 /* FIXME */
2116 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2117 TLB_abort();
2119 pcx->pos = where;
2123 /* read function */
2124 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2126 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2127 pcx->pos, count, pcx->oStart, pcx->length, where);
2129 MSFT_Seek(pcx, where);
2130 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2131 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2132 pcx->pos += count;
2133 return count;
2136 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2137 LONG where )
2139 DWORD ret;
2141 ret = MSFT_Read(buffer, count, pcx, where);
2142 FromLEDWords(buffer, ret);
2144 return ret;
2147 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2148 LONG where )
2150 DWORD ret;
2152 ret = MSFT_Read(buffer, count, pcx, where);
2153 FromLEWords(buffer, ret);
2155 return ret;
2158 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2160 TLBGuid *guid;
2161 MSFT_GuidEntry entry;
2162 int offs = 0;
2164 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2165 while (1) {
2166 if (offs >= pcx->pTblDir->pGuidTab.length)
2167 return S_OK;
2169 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2171 guid = heap_alloc(sizeof(TLBGuid));
2173 guid->offset = offs;
2174 guid->guid = entry.guid;
2175 guid->hreftype = entry.hreftype;
2177 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2179 offs += sizeof(MSFT_GuidEntry);
2183 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2185 TLBGuid *ret;
2187 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2188 if(ret->offset == offset){
2189 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2190 return ret;
2194 return NULL;
2197 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2199 MSFT_NameIntro niName;
2201 if (offset < 0)
2203 ERR_(typelib)("bad offset %d\n", offset);
2204 return -1;
2207 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2208 pcx->pTblDir->pNametab.offset+offset);
2210 return niName.hreftype;
2213 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2215 char *string;
2216 MSFT_NameIntro intro;
2217 INT16 len_piece;
2218 int offs = 0, lengthInChars;
2220 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2221 while (1) {
2222 TLBString *tlbstr;
2224 if (offs >= pcx->pTblDir->pNametab.length)
2225 return S_OK;
2227 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2228 intro.namelen &= 0xFF;
2229 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2230 if(len_piece % 4)
2231 len_piece = (len_piece + 4) & ~0x3;
2232 if(len_piece < 8)
2233 len_piece = 8;
2235 string = heap_alloc(len_piece + 1);
2236 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2237 string[intro.namelen] = '\0';
2239 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2240 string, -1, NULL, 0);
2241 if (!lengthInChars) {
2242 heap_free(string);
2243 return E_UNEXPECTED;
2246 tlbstr = heap_alloc(sizeof(TLBString));
2248 tlbstr->offset = offs;
2249 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2250 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2252 heap_free(string);
2254 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2256 offs += len_piece;
2260 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2262 TLBString *tlbstr;
2264 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2265 if (tlbstr->offset == offset) {
2266 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2267 return tlbstr;
2271 return NULL;
2274 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2276 TLBString *tlbstr;
2278 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2279 if (tlbstr->offset == offset) {
2280 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2281 return tlbstr;
2285 return NULL;
2289 * read a value and fill a VARIANT structure
2291 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2293 int size;
2295 TRACE_(typelib)("\n");
2297 if(offset <0) { /* data are packed in here */
2298 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2299 V_I4(pVar) = offset & 0x3ffffff;
2300 return;
2302 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2303 pcx->pTblDir->pCustData.offset + offset );
2304 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2305 switch (V_VT(pVar)){
2306 case VT_EMPTY: /* FIXME: is this right? */
2307 case VT_NULL: /* FIXME: is this right? */
2308 case VT_I2 : /* this should not happen */
2309 case VT_I4 :
2310 case VT_R4 :
2311 case VT_ERROR :
2312 case VT_BOOL :
2313 case VT_I1 :
2314 case VT_UI1 :
2315 case VT_UI2 :
2316 case VT_UI4 :
2317 case VT_INT :
2318 case VT_UINT :
2319 case VT_VOID : /* FIXME: is this right? */
2320 case VT_HRESULT :
2321 size=4; break;
2322 case VT_R8 :
2323 case VT_CY :
2324 case VT_DATE :
2325 case VT_I8 :
2326 case VT_UI8 :
2327 case VT_DECIMAL : /* FIXME: is this right? */
2328 case VT_FILETIME :
2329 size=8;break;
2330 /* pointer types with known behaviour */
2331 case VT_BSTR :{
2332 char * ptr;
2333 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2334 if(size == -1){
2335 V_BSTR(pVar) = NULL;
2336 }else{
2337 ptr = heap_alloc_zero(size);
2338 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2339 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2340 /* FIXME: do we need a AtoW conversion here? */
2341 V_UNION(pVar, bstrVal[size])='\0';
2342 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2343 heap_free(ptr);
2346 size=-4; break;
2347 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2348 case VT_DISPATCH :
2349 case VT_VARIANT :
2350 case VT_UNKNOWN :
2351 case VT_PTR :
2352 case VT_SAFEARRAY :
2353 case VT_CARRAY :
2354 case VT_USERDEFINED :
2355 case VT_LPSTR :
2356 case VT_LPWSTR :
2357 case VT_BLOB :
2358 case VT_STREAM :
2359 case VT_STORAGE :
2360 case VT_STREAMED_OBJECT :
2361 case VT_STORED_OBJECT :
2362 case VT_BLOB_OBJECT :
2363 case VT_CF :
2364 case VT_CLSID :
2365 default:
2366 size=0;
2367 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2368 V_VT(pVar));
2371 if(size>0) /* (big|small) endian correct? */
2372 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2373 return;
2376 * create a linked list with custom data
2378 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2380 MSFT_CDGuid entry;
2381 TLBCustData* pNew;
2382 int count=0;
2384 TRACE_(typelib)("\n");
2386 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2388 while(offset >=0){
2389 count++;
2390 pNew=heap_alloc_zero(sizeof(TLBCustData));
2391 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2392 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2393 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2394 list_add_head(custdata_list, &pNew->entry);
2395 offset = entry.next;
2397 return count;
2400 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2402 if(type <0)
2403 pTd->vt=type & VT_TYPEMASK;
2404 else
2405 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2407 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2410 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2412 return (invkind == INVOKE_PROPERTYGET ||
2413 invkind == INVOKE_PROPERTYPUT ||
2414 invkind == INVOKE_PROPERTYPUTREF);
2417 static void
2418 MSFT_DoFuncs(TLBContext* pcx,
2419 ITypeInfoImpl* pTI,
2420 int cFuncs,
2421 int cVars,
2422 int offset,
2423 TLBFuncDesc** pptfd)
2426 * member information is stored in a data structure at offset
2427 * indicated by the memoffset field of the typeinfo structure
2428 * There are several distinctive parts.
2429 * The first part starts with a field that holds the total length
2430 * of this (first) part excluding this field. Then follow the records,
2431 * for each member there is one record.
2433 * The first entry is always the length of the record (including this
2434 * length word).
2435 * The rest of the record depends on the type of the member. If there is
2436 * a field indicating the member type (function, variable, interface, etc)
2437 * I have not found it yet. At this time we depend on the information
2438 * in the type info and the usual order how things are stored.
2440 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2441 * for each member;
2443 * Third is an equal sized array with file offsets to the name entry
2444 * of each member.
2446 * The fourth and last (?) part is an array with offsets to the records
2447 * in the first part of this file segment.
2450 int infolen, nameoffset, reclength, i;
2451 int recoffset = offset + sizeof(INT);
2453 char *recbuf = heap_alloc(0xffff);
2454 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2455 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2457 TRACE_(typelib)("\n");
2459 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2461 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2462 ptfd = *pptfd;
2463 for ( i = 0; i < cFuncs ; i++ )
2465 int optional;
2467 /* name, eventually add to a hash table */
2468 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2469 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2471 /* read the function information record */
2472 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2474 reclength &= 0xffff;
2476 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2478 /* size without argument data */
2479 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2480 if (pFuncRec->FKCCIC & 0x1000)
2481 optional -= pFuncRec->nrargs * sizeof(INT);
2483 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2484 ptfd->helpcontext = pFuncRec->HelpContext;
2486 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2487 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2489 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2491 if (pFuncRec->FKCCIC & 0x2000 )
2493 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2494 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2495 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2497 else
2498 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2500 else
2501 ptfd->Entry = (TLBString*)-1;
2503 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2504 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2506 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2507 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2509 /* fill the FuncDesc Structure */
2510 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2511 offset + infolen + ( i + 1) * sizeof(INT));
2513 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2514 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2515 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2516 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2517 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2518 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2519 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2521 /* nameoffset is sometimes -1 on the second half of a propget/propput
2522 * pair of functions */
2523 if ((nameoffset == -1) && (i > 0) &&
2524 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2525 TLB_is_propgetput(ptfd->funcdesc.invkind))
2526 ptfd->Name = ptfd_prev->Name;
2527 else
2528 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2530 MSFT_GetTdesc(pcx,
2531 pFuncRec->DataType,
2532 &ptfd->funcdesc.elemdescFunc.tdesc);
2534 /* do the parameters/arguments */
2535 if(pFuncRec->nrargs)
2537 int j = 0;
2538 MSFT_ParameterInfo paraminfo;
2540 ptfd->funcdesc.lprgelemdescParam =
2541 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2543 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2545 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2546 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2548 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2550 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2552 MSFT_GetTdesc(pcx,
2553 paraminfo.DataType,
2554 &elemdesc->tdesc);
2556 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2558 /* name */
2559 if (paraminfo.oName != -1)
2560 ptfd->pParamDesc[j].Name =
2561 MSFT_ReadName( pcx, paraminfo.oName );
2562 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2564 /* default value */
2565 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2566 (pFuncRec->FKCCIC & 0x1000) )
2568 INT* pInt = (INT *)((char *)pFuncRec +
2569 reclength -
2570 (pFuncRec->nrargs * 4) * sizeof(INT) );
2572 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2574 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2575 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2577 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2578 pInt[j], pcx);
2580 else
2581 elemdesc->u.paramdesc.pparamdescex = NULL;
2583 /* custom info */
2584 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2585 j*sizeof(pFuncRec->oArgCustData[0])) &&
2586 pFuncRec->FKCCIC & 0x80 )
2588 MSFT_CustData(pcx,
2589 pFuncRec->oArgCustData[j],
2590 &ptfd->pParamDesc[j].custdata_list);
2593 /* SEEK value = jump to offset,
2594 * from there jump to the end of record,
2595 * go back by (j-1) arguments
2597 MSFT_ReadLEDWords( &paraminfo ,
2598 sizeof(MSFT_ParameterInfo), pcx,
2599 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2600 * sizeof(MSFT_ParameterInfo)));
2604 /* scode is not used: archaic win16 stuff FIXME: right? */
2605 ptfd->funcdesc.cScodes = 0 ;
2606 ptfd->funcdesc.lprgscode = NULL ;
2608 ptfd_prev = ptfd;
2609 ++ptfd;
2610 recoffset += reclength;
2612 heap_free(recbuf);
2615 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2616 int cVars, int offset, TLBVarDesc ** pptvd)
2618 int infolen, nameoffset, reclength;
2619 char recbuf[256];
2620 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2621 TLBVarDesc *ptvd;
2622 int i;
2623 int recoffset;
2625 TRACE_(typelib)("\n");
2627 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2628 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2629 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2630 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2631 recoffset += offset+sizeof(INT);
2632 for(i=0;i<cVars;i++, ++ptvd){
2633 /* name, eventually add to a hash table */
2634 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2635 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2636 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2637 /* read the variable information record */
2638 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2639 reclength &= 0xff;
2640 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2642 /* optional data */
2643 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2644 ptvd->HelpContext = pVarRec->HelpContext;
2646 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2647 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2649 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2650 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2652 /* fill the VarDesc Structure */
2653 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2654 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2655 ptvd->vardesc.varkind = pVarRec->VarKind;
2656 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2657 MSFT_GetTdesc(pcx, pVarRec->DataType,
2658 &ptvd->vardesc.elemdescVar.tdesc);
2659 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2660 if(pVarRec->VarKind == VAR_CONST ){
2661 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2662 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2663 pVarRec->OffsValue, pcx);
2664 } else
2665 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2666 recoffset += reclength;
2670 /* process Implemented Interfaces of a com class */
2671 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2672 int offset)
2674 int i;
2675 MSFT_RefRecord refrec;
2676 TLBImplType *pImpl;
2678 TRACE_(typelib)("\n");
2680 pTI->impltypes = TLBImplType_Alloc(count);
2681 pImpl = pTI->impltypes;
2682 for(i=0;i<count;i++){
2683 if(offset<0) break; /* paranoia */
2684 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2685 pImpl->hRef = refrec.reftype;
2686 pImpl->implflags=refrec.flags;
2687 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2688 offset=refrec.onext;
2689 ++pImpl;
2693 #ifdef _WIN64
2694 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2695 * and some structures, and fix the alignment */
2696 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2698 if(info->typekind == TKIND_ALIAS){
2699 switch(info->tdescAlias->vt){
2700 case VT_BSTR:
2701 case VT_DISPATCH:
2702 case VT_UNKNOWN:
2703 case VT_PTR:
2704 case VT_SAFEARRAY:
2705 case VT_LPSTR:
2706 case VT_LPWSTR:
2707 info->cbSizeInstance = sizeof(void*);
2708 info->cbAlignment = sizeof(void*);
2709 break;
2710 case VT_CARRAY:
2711 case VT_USERDEFINED:
2712 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->cbSizeInstance, &info->cbAlignment);
2713 break;
2714 case VT_VARIANT:
2715 info->cbSizeInstance = sizeof(VARIANT);
2716 info->cbAlignment = 8;
2717 default:
2718 if(info->cbSizeInstance < sizeof(void*))
2719 info->cbAlignment = info->cbSizeInstance;
2720 else
2721 info->cbAlignment = sizeof(void*);
2722 break;
2724 }else if(info->typekind == TKIND_INTERFACE ||
2725 info->typekind == TKIND_DISPATCH ||
2726 info->typekind == TKIND_COCLASS){
2727 info->cbSizeInstance = sizeof(void*);
2728 info->cbAlignment = sizeof(void*);
2731 #endif
2734 * process a typeinfo record
2736 static ITypeInfoImpl * MSFT_DoTypeInfo(
2737 TLBContext *pcx,
2738 int count,
2739 ITypeLibImpl * pLibInfo)
2741 MSFT_TypeInfoBase tiBase;
2742 ITypeInfoImpl *ptiRet;
2744 TRACE_(typelib)("count=%u\n", count);
2746 ptiRet = ITypeInfoImpl_Constructor();
2747 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2748 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2750 /* this is where we are coming from */
2751 ptiRet->pTypeLib = pLibInfo;
2752 ptiRet->index=count;
2754 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2755 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2756 ptiRet->lpstrSchema=NULL; /* reserved */
2757 ptiRet->cbSizeInstance=tiBase.size;
2758 ptiRet->typekind=tiBase.typekind & 0xF;
2759 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2760 ptiRet->cVars=HIWORD(tiBase.cElement);
2761 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2762 ptiRet->wTypeFlags=tiBase.flags;
2763 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2764 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2765 ptiRet->cImplTypes=tiBase.cImplTypes;
2766 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2767 if(ptiRet->typekind == TKIND_ALIAS){
2768 TYPEDESC tmp;
2769 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2770 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2771 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2774 /* FIXME: */
2775 /* IDLDESC idldescType; *//* never saw this one != zero */
2777 /* name, eventually add to a hash table */
2778 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2779 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2780 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2781 /* help info */
2782 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2783 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2784 ptiRet->dwHelpContext=tiBase.helpcontext;
2786 if (ptiRet->typekind == TKIND_MODULE)
2787 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2789 /* note: InfoType's Help file and HelpStringDll come from the containing
2790 * library. Further HelpString and Docstring appear to be the same thing :(
2792 /* functions */
2793 if(ptiRet->cFuncs >0 )
2794 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2795 ptiRet->cVars,
2796 tiBase.memoffset, &ptiRet->funcdescs);
2797 /* variables */
2798 if(ptiRet->cVars >0 )
2799 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2800 ptiRet->cVars,
2801 tiBase.memoffset, &ptiRet->vardescs);
2802 if(ptiRet->cImplTypes >0 ) {
2803 switch(ptiRet->typekind)
2805 case TKIND_COCLASS:
2806 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2807 tiBase.datatype1);
2808 break;
2809 case TKIND_DISPATCH:
2810 /* This is not -1 when the interface is a non-base dual interface or
2811 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2812 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2813 not this interface.
2816 if (tiBase.datatype1 != -1)
2818 ptiRet->impltypes = TLBImplType_Alloc(1);
2819 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2821 break;
2822 default:
2823 ptiRet->impltypes = TLBImplType_Alloc(1);
2824 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2825 break;
2828 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2830 TRACE_(typelib)("%s guid: %s kind:%s\n",
2831 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2832 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2833 typekind_desc[ptiRet->typekind]);
2834 if (TRACE_ON(typelib))
2835 dump_TypeInfo(ptiRet);
2837 return ptiRet;
2840 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2842 char *string;
2843 INT16 len_str, len_piece;
2844 int offs = 0, lengthInChars;
2846 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2847 while (1) {
2848 TLBString *tlbstr;
2850 if (offs >= pcx->pTblDir->pStringtab.length)
2851 return S_OK;
2853 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2854 len_piece = len_str + sizeof(INT16);
2855 if(len_piece % 4)
2856 len_piece = (len_piece + 4) & ~0x3;
2857 if(len_piece < 8)
2858 len_piece = 8;
2860 string = heap_alloc(len_piece + 1);
2861 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2862 string[len_str] = '\0';
2864 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2865 string, -1, NULL, 0);
2866 if (!lengthInChars) {
2867 heap_free(string);
2868 return E_UNEXPECTED;
2871 tlbstr = heap_alloc(sizeof(TLBString));
2873 tlbstr->offset = offs;
2874 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2875 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2877 heap_free(string);
2879 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2881 offs += len_piece;
2885 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2887 TLBRefType *ref;
2888 int offs = 0;
2890 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2891 while (offs < pcx->pTblDir->pImpInfo.length) {
2892 MSFT_ImpInfo impinfo;
2893 TLBImpLib *pImpLib;
2895 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2897 ref = heap_alloc_zero(sizeof(TLBRefType));
2898 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2900 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2901 if(pImpLib->offset==impinfo.oImpFile)
2902 break;
2904 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2905 ref->reference = offs;
2906 ref->pImpTLInfo = pImpLib;
2907 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2908 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2909 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2910 ref->index = TLB_REF_USE_GUID;
2911 } else
2912 ref->index = impinfo.oGuid;
2913 }else{
2914 ERR("Cannot find a reference\n");
2915 ref->reference = -1;
2916 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2919 offs += sizeof(impinfo);
2922 return S_OK;
2925 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2926 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2927 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2928 * tradeoff here.
2930 static struct list tlb_cache = LIST_INIT(tlb_cache);
2931 static CRITICAL_SECTION cache_section;
2932 static CRITICAL_SECTION_DEBUG cache_section_debug =
2934 0, 0, &cache_section,
2935 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2936 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2938 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2941 typedef struct TLB_PEFile
2943 IUnknown IUnknown_iface;
2944 LONG refs;
2945 HMODULE dll;
2946 HRSRC typelib_resource;
2947 HGLOBAL typelib_global;
2948 LPVOID typelib_base;
2949 } TLB_PEFile;
2951 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2953 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2956 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2958 if (IsEqualIID(riid, &IID_IUnknown))
2960 *ppv = iface;
2961 IUnknown_AddRef(iface);
2962 return S_OK;
2964 *ppv = NULL;
2965 return E_NOINTERFACE;
2968 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2970 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2971 return InterlockedIncrement(&This->refs);
2974 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2976 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2977 ULONG refs = InterlockedDecrement(&This->refs);
2978 if (!refs)
2980 if (This->typelib_global)
2981 FreeResource(This->typelib_global);
2982 if (This->dll)
2983 FreeLibrary(This->dll);
2984 heap_free(This);
2986 return refs;
2989 static const IUnknownVtbl TLB_PEFile_Vtable =
2991 TLB_PEFile_QueryInterface,
2992 TLB_PEFile_AddRef,
2993 TLB_PEFile_Release
2996 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2998 TLB_PEFile *This;
2999 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3001 This = heap_alloc(sizeof(TLB_PEFile));
3002 if (!This)
3003 return E_OUTOFMEMORY;
3005 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
3006 This->refs = 1;
3007 This->dll = NULL;
3008 This->typelib_resource = NULL;
3009 This->typelib_global = NULL;
3010 This->typelib_base = NULL;
3012 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
3013 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
3015 if (This->dll)
3017 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
3018 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
3019 if (This->typelib_resource)
3021 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
3022 if (This->typelib_global)
3024 This->typelib_base = LockResource(This->typelib_global);
3026 if (This->typelib_base)
3028 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
3029 *ppBase = This->typelib_base;
3030 *ppFile = &This->IUnknown_iface;
3031 return S_OK;
3036 TRACE("No TYPELIB resource found\n");
3037 hr = E_FAIL;
3040 TLB_PEFile_Release(&This->IUnknown_iface);
3041 return hr;
3044 typedef struct TLB_NEFile
3046 IUnknown IUnknown_iface;
3047 LONG refs;
3048 LPVOID typelib_base;
3049 } TLB_NEFile;
3051 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
3053 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
3056 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3058 if (IsEqualIID(riid, &IID_IUnknown))
3060 *ppv = iface;
3061 IUnknown_AddRef(iface);
3062 return S_OK;
3064 *ppv = NULL;
3065 return E_NOINTERFACE;
3068 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3070 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3071 return InterlockedIncrement(&This->refs);
3074 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3076 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3077 ULONG refs = InterlockedDecrement(&This->refs);
3078 if (!refs)
3080 heap_free(This->typelib_base);
3081 heap_free(This);
3083 return refs;
3086 static const IUnknownVtbl TLB_NEFile_Vtable =
3088 TLB_NEFile_QueryInterface,
3089 TLB_NEFile_AddRef,
3090 TLB_NEFile_Release
3093 /***********************************************************************
3094 * read_xx_header [internal]
3096 static int read_xx_header( HFILE lzfd )
3098 IMAGE_DOS_HEADER mzh;
3099 char magic[3];
3101 LZSeek( lzfd, 0, SEEK_SET );
3102 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3103 return 0;
3104 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3105 return 0;
3107 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3108 if ( 2 != LZRead( lzfd, magic, 2 ) )
3109 return 0;
3111 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3113 if ( magic[0] == 'N' && magic[1] == 'E' )
3114 return IMAGE_OS2_SIGNATURE;
3115 if ( magic[0] == 'P' && magic[1] == 'E' )
3116 return IMAGE_NT_SIGNATURE;
3118 magic[2] = '\0';
3119 WARN("Can't handle %s files.\n", magic );
3120 return 0;
3124 /***********************************************************************
3125 * find_ne_resource [internal]
3127 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3128 DWORD *resLen, DWORD *resOff )
3130 IMAGE_OS2_HEADER nehd;
3131 NE_TYPEINFO *typeInfo;
3132 NE_NAMEINFO *nameInfo;
3133 DWORD nehdoffset;
3134 LPBYTE resTab;
3135 DWORD resTabSize;
3136 int count;
3138 /* Read in NE header */
3139 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3140 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3142 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3143 if ( !resTabSize )
3145 TRACE("No resources in NE dll\n" );
3146 return FALSE;
3149 /* Read in resource table */
3150 resTab = heap_alloc( resTabSize );
3151 if ( !resTab ) return FALSE;
3153 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3154 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3156 heap_free( resTab );
3157 return FALSE;
3160 /* Find resource */
3161 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3163 if (!IS_INTRESOURCE(typeid)) /* named type */
3165 BYTE len = strlen( typeid );
3166 while (typeInfo->type_id)
3168 if (!(typeInfo->type_id & 0x8000))
3170 BYTE *p = resTab + typeInfo->type_id;
3171 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3173 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3174 typeInfo->count * sizeof(NE_NAMEINFO));
3177 else /* numeric type id */
3179 WORD id = LOWORD(typeid) | 0x8000;
3180 while (typeInfo->type_id)
3182 if (typeInfo->type_id == id) goto found_type;
3183 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3184 typeInfo->count * sizeof(NE_NAMEINFO));
3187 TRACE("No typeid entry found for %p\n", typeid );
3188 heap_free( resTab );
3189 return FALSE;
3191 found_type:
3192 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3194 if (!IS_INTRESOURCE(resid)) /* named resource */
3196 BYTE len = strlen( resid );
3197 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3199 BYTE *p = resTab + nameInfo->id;
3200 if (nameInfo->id & 0x8000) continue;
3201 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3204 else /* numeric resource id */
3206 WORD id = LOWORD(resid) | 0x8000;
3207 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3208 if (nameInfo->id == id) goto found_name;
3210 TRACE("No resid entry found for %p\n", typeid );
3211 heap_free( resTab );
3212 return FALSE;
3214 found_name:
3215 /* Return resource data */
3216 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3217 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3219 heap_free( resTab );
3220 return TRUE;
3223 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3225 HFILE lzfd = -1;
3226 OFSTRUCT ofs;
3227 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3228 TLB_NEFile *This;
3230 This = heap_alloc(sizeof(TLB_NEFile));
3231 if (!This) return E_OUTOFMEMORY;
3233 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3234 This->refs = 1;
3235 This->typelib_base = NULL;
3237 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3238 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3240 DWORD reslen, offset;
3241 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3243 This->typelib_base = heap_alloc(reslen);
3244 if( !This->typelib_base )
3245 hr = E_OUTOFMEMORY;
3246 else
3248 LZSeek( lzfd, offset, SEEK_SET );
3249 reslen = LZRead( lzfd, This->typelib_base, reslen );
3250 LZClose( lzfd );
3251 *ppBase = This->typelib_base;
3252 *pdwTLBLength = reslen;
3253 *ppFile = &This->IUnknown_iface;
3254 return S_OK;
3259 if( lzfd >= 0) LZClose( lzfd );
3260 TLB_NEFile_Release(&This->IUnknown_iface);
3261 return hr;
3264 typedef struct TLB_Mapping
3266 IUnknown IUnknown_iface;
3267 LONG refs;
3268 HANDLE file;
3269 HANDLE mapping;
3270 LPVOID typelib_base;
3271 } TLB_Mapping;
3273 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3275 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3278 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3280 if (IsEqualIID(riid, &IID_IUnknown))
3282 *ppv = iface;
3283 IUnknown_AddRef(iface);
3284 return S_OK;
3286 *ppv = NULL;
3287 return E_NOINTERFACE;
3290 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3292 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3293 return InterlockedIncrement(&This->refs);
3296 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3298 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3299 ULONG refs = InterlockedDecrement(&This->refs);
3300 if (!refs)
3302 if (This->typelib_base)
3303 UnmapViewOfFile(This->typelib_base);
3304 if (This->mapping)
3305 CloseHandle(This->mapping);
3306 if (This->file != INVALID_HANDLE_VALUE)
3307 CloseHandle(This->file);
3308 heap_free(This);
3310 return refs;
3313 static const IUnknownVtbl TLB_Mapping_Vtable =
3315 TLB_Mapping_QueryInterface,
3316 TLB_Mapping_AddRef,
3317 TLB_Mapping_Release
3320 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3322 TLB_Mapping *This;
3324 This = heap_alloc(sizeof(TLB_Mapping));
3325 if (!This)
3326 return E_OUTOFMEMORY;
3328 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3329 This->refs = 1;
3330 This->file = INVALID_HANDLE_VALUE;
3331 This->mapping = NULL;
3332 This->typelib_base = NULL;
3334 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3335 if (INVALID_HANDLE_VALUE != This->file)
3337 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3338 if (This->mapping)
3340 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3341 if(This->typelib_base)
3343 /* retrieve file size */
3344 *pdwTLBLength = GetFileSize(This->file, NULL);
3345 *ppBase = This->typelib_base;
3346 *ppFile = &This->IUnknown_iface;
3347 return S_OK;
3352 IUnknown_Release(&This->IUnknown_iface);
3353 return TYPE_E_CANTLOADLIBRARY;
3356 /****************************************************************************
3357 * TLB_ReadTypeLib
3359 * find the type of the typelib file and map the typelib resource into
3360 * the memory
3363 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3364 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3366 ITypeLibImpl *entry;
3367 HRESULT ret;
3368 INT index = 1;
3369 LPWSTR index_str, file = (LPWSTR)pszFileName;
3370 LPVOID pBase = NULL;
3371 DWORD dwTLBLength = 0;
3372 IUnknown *pFile = NULL;
3373 HANDLE h;
3375 *ppTypeLib = NULL;
3377 index_str = strrchrW(pszFileName, '\\');
3378 if(index_str && *++index_str != '\0')
3380 LPWSTR end_ptr;
3381 LONG idx = strtolW(index_str, &end_ptr, 10);
3382 if(*end_ptr == '\0')
3384 int str_len = index_str - pszFileName - 1;
3385 index = idx;
3386 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3387 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3388 file[str_len] = 0;
3392 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3394 if(strchrW(file, '\\'))
3396 lstrcpyW(pszPath, file);
3398 else
3400 int len = GetSystemDirectoryW(pszPath, cchPath);
3401 pszPath[len] = '\\';
3402 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3406 if(file != pszFileName) heap_free(file);
3408 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3409 if(h != INVALID_HANDLE_VALUE){
3410 FILE_NAME_INFORMATION *info;
3411 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3412 BOOL br;
3414 info = (FILE_NAME_INFORMATION*)data;
3415 /* GetFileInformationByHandleEx returns the path of the file without
3416 * WOW64 redirection */
3417 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3418 if(br){
3419 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3420 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3422 CloseHandle(h);
3425 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3427 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3428 EnterCriticalSection(&cache_section);
3429 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3431 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3433 TRACE("cache hit\n");
3434 *ppTypeLib = &entry->ITypeLib2_iface;
3435 ITypeLib2_AddRef(*ppTypeLib);
3436 LeaveCriticalSection(&cache_section);
3437 return S_OK;
3440 LeaveCriticalSection(&cache_section);
3442 /* now actually load and parse the typelib */
3444 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3445 if (ret == TYPE_E_CANTLOADLIBRARY)
3446 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3447 if (ret == TYPE_E_CANTLOADLIBRARY)
3448 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3449 if (SUCCEEDED(ret))
3451 if (dwTLBLength >= 4)
3453 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3454 if (dwSignature == MSFT_SIGNATURE)
3455 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3456 else if (dwSignature == SLTG_SIGNATURE)
3457 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3458 else
3460 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3461 ret = TYPE_E_CANTLOADLIBRARY;
3464 else
3465 ret = TYPE_E_CANTLOADLIBRARY;
3466 IUnknown_Release(pFile);
3469 if(*ppTypeLib) {
3470 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3472 TRACE("adding to cache\n");
3473 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3474 lstrcpyW(impl->path, pszPath);
3475 /* We should really canonicalise the path here. */
3476 impl->index = index;
3478 /* FIXME: check if it has added already in the meantime */
3479 EnterCriticalSection(&cache_section);
3480 list_add_head(&tlb_cache, &impl->entry);
3481 LeaveCriticalSection(&cache_section);
3482 ret = S_OK;
3484 else
3486 if(ret != E_FAIL)
3487 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3489 ret = TYPE_E_CANTLOADLIBRARY;
3493 return ret;
3496 /*================== ITypeLib(2) Methods ===================================*/
3498 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3500 ITypeLibImpl* pTypeLibImpl;
3502 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3503 if (!pTypeLibImpl) return NULL;
3505 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3506 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3507 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3508 pTypeLibImpl->ref = 1;
3510 list_init(&pTypeLibImpl->implib_list);
3511 list_init(&pTypeLibImpl->custdata_list);
3512 list_init(&pTypeLibImpl->name_list);
3513 list_init(&pTypeLibImpl->string_list);
3514 list_init(&pTypeLibImpl->guid_list);
3515 list_init(&pTypeLibImpl->ref_list);
3516 pTypeLibImpl->dispatch_href = -1;
3518 return pTypeLibImpl;
3521 /****************************************************************************
3522 * ITypeLib2_Constructor_MSFT
3524 * loading an MSFT typelib from an in-memory image
3526 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3528 TLBContext cx;
3529 LONG lPSegDir;
3530 MSFT_Header tlbHeader;
3531 MSFT_SegDir tlbSegDir;
3532 ITypeLibImpl * pTypeLibImpl;
3533 int i;
3535 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3537 pTypeLibImpl = TypeLibImpl_Constructor();
3538 if (!pTypeLibImpl) return NULL;
3540 /* get pointer to beginning of typelib data */
3541 cx.pos = 0;
3542 cx.oStart=0;
3543 cx.mapping = pLib;
3544 cx.pLibInfo = pTypeLibImpl;
3545 cx.length = dwTLBLength;
3547 /* read header */
3548 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3549 TRACE_(typelib)("header:\n");
3550 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3551 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3552 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3553 return NULL;
3555 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3557 /* there is a small amount of information here until the next important
3558 * part:
3559 * the segment directory . Try to calculate the amount of data */
3560 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3562 /* now read the segment directory */
3563 TRACE("read segment directory (at %d)\n",lPSegDir);
3564 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3565 cx.pTblDir = &tlbSegDir;
3567 /* just check two entries */
3568 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3570 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3571 heap_free(pTypeLibImpl);
3572 return NULL;
3575 MSFT_ReadAllNames(&cx);
3576 MSFT_ReadAllStrings(&cx);
3577 MSFT_ReadAllGuids(&cx);
3579 /* now fill our internal data */
3580 /* TLIBATTR fields */
3581 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3583 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3584 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3585 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3586 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3587 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3589 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3590 pTypeLibImpl->lcid = tlbHeader.lcid;
3592 /* name, eventually add to a hash table */
3593 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3595 /* help info */
3596 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3597 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3599 if( tlbHeader.varflags & HELPDLLFLAG)
3601 int offset;
3602 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3603 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3606 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3608 /* custom data */
3609 if(tlbHeader.CustomDataOffset >= 0)
3611 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3614 /* fill in type descriptions */
3615 if(tlbSegDir.pTypdescTab.length > 0)
3617 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3618 INT16 td[4];
3619 pTypeLibImpl->ctTypeDesc = cTD;
3620 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3621 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3622 for(i=0; i<cTD; )
3624 /* FIXME: add several sanity checks here */
3625 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3626 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3628 /* FIXME: check safearray */
3629 if(td[3] < 0)
3630 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3631 else
3632 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3634 else if(td[0] == VT_CARRAY)
3636 /* array descr table here */
3637 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3639 else if(td[0] == VT_USERDEFINED)
3641 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3643 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3646 /* second time around to fill the array subscript info */
3647 for(i=0;i<cTD;i++)
3649 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3650 if(tlbSegDir.pArrayDescriptions.offset>0)
3652 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3653 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3655 if(td[1]<0)
3656 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3657 else
3658 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3660 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3662 for(j = 0; j<td[2]; j++)
3664 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3665 sizeof(INT), &cx, DO_NOT_SEEK);
3666 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3667 sizeof(INT), &cx, DO_NOT_SEEK);
3670 else
3672 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3673 ERR("didn't find array description data\n");
3678 /* imported type libs */
3679 if(tlbSegDir.pImpFiles.offset>0)
3681 TLBImpLib *pImpLib;
3682 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3683 UINT16 size;
3685 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3687 char *name;
3689 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3690 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3691 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3693 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3694 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3695 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3696 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3698 size >>= 2;
3699 name = heap_alloc_zero(size+1);
3700 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3701 pImpLib->name = TLB_MultiByteToBSTR(name);
3702 heap_free(name);
3704 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3705 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3707 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3711 MSFT_ReadAllRefs(&cx);
3713 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3715 /* type infos */
3716 if(tlbHeader.nrtypeinfos >= 0 )
3718 ITypeInfoImpl **ppTI;
3720 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3722 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3724 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3726 ++ppTI;
3727 (pTypeLibImpl->TypeInfoCount)++;
3731 #ifdef _WIN64
3732 if(pTypeLibImpl->syskind == SYS_WIN32){
3733 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3734 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3736 #endif
3738 TRACE("(%p)\n", pTypeLibImpl);
3739 return &pTypeLibImpl->ITypeLib2_iface;
3743 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3745 char b[3];
3746 int i;
3747 short s;
3749 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3750 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3751 return FALSE;
3754 guid->Data4[0] = s >> 8;
3755 guid->Data4[1] = s & 0xff;
3757 b[2] = '\0';
3758 for(i = 0; i < 6; i++) {
3759 memcpy(b, str + 24 + 2 * i, 2);
3760 guid->Data4[i + 2] = strtol(b, NULL, 16);
3762 return TRUE;
3765 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3767 WORD bytelen;
3768 DWORD len;
3769 BSTR tmp_str;
3771 *pStr = NULL;
3772 bytelen = *(const WORD*)ptr;
3773 if(bytelen == 0xffff) return 2;
3775 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3776 tmp_str = SysAllocStringLen(NULL, len);
3777 if (tmp_str) {
3778 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3779 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3780 SysFreeString(tmp_str);
3782 return bytelen + 2;
3785 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3787 WORD bytelen;
3789 *str = NULL;
3790 bytelen = *(const WORD*)ptr;
3791 if(bytelen == 0xffff) return 2;
3792 *str = heap_alloc(bytelen + 1);
3793 memcpy(*str, ptr + 2, bytelen);
3794 (*str)[bytelen] = '\0';
3795 return bytelen + 2;
3798 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3800 BSTR tmp_str;
3801 TLBString *tlbstr;
3803 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3804 if (tlbstr->offset == offset)
3805 return tlbstr;
3808 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3809 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3810 SysFreeString(tmp_str);
3812 return tlbstr;
3815 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3817 char *ptr = pLibBlk;
3818 WORD w;
3820 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3821 FIXME("libblk magic = %04x\n", w);
3822 return 0;
3825 ptr += 6;
3826 if((w = *(WORD*)ptr) != 0xffff) {
3827 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3828 ptr += w;
3830 ptr += 2;
3832 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3834 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3836 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3837 ptr += 4;
3839 pTypeLibImpl->syskind = *(WORD*)ptr;
3840 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3841 ptr += 2;
3843 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3844 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3845 else
3846 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3847 ptr += 2;
3849 ptr += 4; /* skip res12 */
3851 pTypeLibImpl->libflags = *(WORD*)ptr;
3852 ptr += 2;
3854 pTypeLibImpl->ver_major = *(WORD*)ptr;
3855 ptr += 2;
3857 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3858 ptr += 2;
3860 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3861 ptr += sizeof(GUID);
3863 return ptr - (char*)pLibBlk;
3866 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3867 typedef struct
3869 unsigned int num;
3870 HREFTYPE refs[1];
3871 } sltg_ref_lookup_t;
3873 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3874 HREFTYPE *typelib_ref)
3876 if(table && typeinfo_ref < table->num)
3878 *typelib_ref = table->refs[typeinfo_ref];
3879 return S_OK;
3882 ERR_(typelib)("Unable to find reference\n");
3883 *typelib_ref = -1;
3884 return E_FAIL;
3887 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3889 BOOL done = FALSE;
3891 while(!done) {
3892 if((*pType & 0xe00) == 0xe00) {
3893 pTD->vt = VT_PTR;
3894 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3895 pTD = pTD->u.lptdesc;
3897 switch(*pType & 0x3f) {
3898 case VT_PTR:
3899 pTD->vt = VT_PTR;
3900 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3901 pTD = pTD->u.lptdesc;
3902 break;
3904 case VT_USERDEFINED:
3905 pTD->vt = VT_USERDEFINED;
3906 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3907 done = TRUE;
3908 break;
3910 case VT_CARRAY:
3912 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3913 array */
3915 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3917 pTD->vt = VT_CARRAY;
3918 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3919 pTD->u.lpadesc->cDims = pSA->cDims;
3920 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3921 pSA->cDims * sizeof(SAFEARRAYBOUND));
3923 pTD = &pTD->u.lpadesc->tdescElem;
3924 break;
3927 case VT_SAFEARRAY:
3929 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3930 useful? */
3932 pType++;
3933 pTD->vt = VT_SAFEARRAY;
3934 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3935 pTD = pTD->u.lptdesc;
3936 break;
3938 default:
3939 pTD->vt = *pType & 0x3f;
3940 done = TRUE;
3941 break;
3943 pType++;
3945 return pType;
3948 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3949 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3951 /* Handle [in/out] first */
3952 if((*pType & 0xc000) == 0xc000)
3953 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3954 else if(*pType & 0x8000)
3955 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3956 else if(*pType & 0x4000)
3957 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3958 else
3959 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3961 if(*pType & 0x2000)
3962 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3964 if(*pType & 0x80)
3965 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3967 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3971 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3972 char *pNameTable)
3974 unsigned int ref;
3975 char *name;
3976 TLBRefType *ref_type;
3977 sltg_ref_lookup_t *table;
3978 HREFTYPE typelib_ref;
3980 if(pRef->magic != SLTG_REF_MAGIC) {
3981 FIXME("Ref magic = %x\n", pRef->magic);
3982 return NULL;
3984 name = ( (char*)pRef->names + pRef->number);
3986 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3987 table->num = pRef->number >> 3;
3989 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3991 /* We don't want the first href to be 0 */
3992 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3994 for(ref = 0; ref < pRef->number >> 3; ref++) {
3995 char *refname;
3996 unsigned int lib_offs, type_num;
3998 ref_type = heap_alloc_zero(sizeof(TLBRefType));
4000 name += SLTG_ReadStringA(name, &refname);
4001 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
4002 FIXME_(typelib)("Can't sscanf ref\n");
4003 if(lib_offs != 0xffff) {
4004 TLBImpLib *import;
4006 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
4007 if(import->offset == lib_offs)
4008 break;
4010 if(&import->entry == &pTL->implib_list) {
4011 char fname[MAX_PATH+1];
4012 int len;
4013 GUID tmpguid;
4015 import = heap_alloc_zero(sizeof(*import));
4016 import->offset = lib_offs;
4017 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
4018 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
4019 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
4020 &import->wVersionMajor,
4021 &import->wVersionMinor,
4022 &import->lcid, fname) != 4) {
4023 FIXME_(typelib)("can't sscanf ref %s\n",
4024 pNameTable + lib_offs + 40);
4026 len = strlen(fname);
4027 if(fname[len-1] != '#')
4028 FIXME("fname = %s\n", fname);
4029 fname[len-1] = '\0';
4030 import->name = TLB_MultiByteToBSTR(fname);
4031 list_add_tail(&pTL->implib_list, &import->entry);
4033 ref_type->pImpTLInfo = import;
4035 /* Store a reference to IDispatch */
4036 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
4037 pTL->dispatch_href = typelib_ref;
4039 } else { /* internal ref */
4040 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
4042 ref_type->reference = typelib_ref;
4043 ref_type->index = type_num;
4045 heap_free(refname);
4046 list_add_tail(&pTL->ref_list, &ref_type->entry);
4048 table->refs[ref] = typelib_ref;
4049 typelib_ref += 4;
4051 if((BYTE)*name != SLTG_REF_MAGIC)
4052 FIXME_(typelib)("End of ref block magic = %x\n", *name);
4053 dump_TLBRefType(pTL);
4054 return table;
4057 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
4058 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
4060 SLTG_ImplInfo *info;
4061 TLBImplType *pImplType;
4062 /* I don't really get this structure, usually it's 0x16 bytes
4063 long, but iuser.tlb contains some that are 0x18 bytes long.
4064 That's ok because we can use the next ptr to jump to the next
4065 one. But how do we know the length of the last one? The WORD
4066 at offs 0x8 might be the clue. For now I'm just assuming that
4067 the last one is the regular 0x16 bytes. */
4069 info = (SLTG_ImplInfo*)pBlk;
4070 while(1){
4071 pTI->cImplTypes++;
4072 if(info->next == 0xffff)
4073 break;
4074 info = (SLTG_ImplInfo*)(pBlk + info->next);
4077 info = (SLTG_ImplInfo*)pBlk;
4078 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
4079 pImplType = pTI->impltypes;
4080 while(1) {
4081 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4082 pImplType->implflags = info->impltypeflags;
4083 ++pImplType;
4085 if(info->next == 0xffff)
4086 break;
4087 if(OneOnly)
4088 FIXME_(typelib)("Interface inheriting more than one interface\n");
4089 info = (SLTG_ImplInfo*)(pBlk + info->next);
4091 info++; /* see comment at top of function */
4092 return (char*)info;
4095 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4096 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4098 TLBVarDesc *pVarDesc;
4099 const TLBString *prevName = NULL;
4100 SLTG_Variable *pItem;
4101 unsigned short i;
4102 WORD *pType;
4104 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4106 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4107 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4109 pVarDesc->vardesc.memid = pItem->memid;
4111 if (pItem->magic != SLTG_VAR_MAGIC &&
4112 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4113 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4114 return;
4117 if (pItem->name == 0xfffe)
4118 pVarDesc->Name = prevName;
4119 else
4120 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4122 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4123 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4124 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4126 if(pItem->flags & 0x02)
4127 pType = &pItem->type;
4128 else
4129 pType = (WORD*)(pBlk + pItem->type);
4131 if (pItem->flags & ~0xda)
4132 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4134 SLTG_DoElem(pType, pBlk,
4135 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4137 if (TRACE_ON(typelib)) {
4138 char buf[300];
4139 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4140 TRACE_(typelib)("elemdescVar: %s\n", buf);
4143 if (pItem->flags & 0x40) {
4144 TRACE_(typelib)("VAR_DISPATCH\n");
4145 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4147 else if (pItem->flags & 0x10) {
4148 TRACE_(typelib)("VAR_CONST\n");
4149 pVarDesc->vardesc.varkind = VAR_CONST;
4150 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4151 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4152 if (pItem->flags & 0x08)
4153 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4154 else {
4155 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4157 case VT_LPSTR:
4158 case VT_LPWSTR:
4159 case VT_BSTR:
4161 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4162 BSTR str;
4163 TRACE_(typelib)("len = %u\n", len);
4164 if (len == 0xffff) {
4165 str = NULL;
4166 } else {
4167 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4168 str = SysAllocStringLen(NULL, alloc_len);
4169 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4171 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4172 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4173 break;
4175 case VT_I2:
4176 case VT_UI2:
4177 case VT_I4:
4178 case VT_UI4:
4179 case VT_INT:
4180 case VT_UINT:
4181 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4182 *(INT*)(pBlk + pItem->byte_offs);
4183 break;
4184 default:
4185 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4189 else {
4190 TRACE_(typelib)("VAR_PERINSTANCE\n");
4191 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4192 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4195 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4196 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4198 if (pItem->flags & 0x80)
4199 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4201 prevName = pVarDesc->Name;
4203 pTI->cVars = cVars;
4206 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4207 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4209 SLTG_Function *pFunc;
4210 unsigned short i;
4211 TLBFuncDesc *pFuncDesc;
4213 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4215 pFuncDesc = pTI->funcdescs;
4216 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4217 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4219 int param;
4220 WORD *pType, *pArg;
4222 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4223 case SLTG_FUNCTION_MAGIC:
4224 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4225 break;
4226 case SLTG_DISPATCH_FUNCTION_MAGIC:
4227 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4228 break;
4229 case SLTG_STATIC_FUNCTION_MAGIC:
4230 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4231 break;
4232 default:
4233 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4234 continue;
4236 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4238 pFuncDesc->funcdesc.memid = pFunc->dispid;
4239 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4240 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4241 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4242 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4243 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4245 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4246 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4248 if(pFunc->retnextopt & 0x80)
4249 pType = &pFunc->rettype;
4250 else
4251 pType = (WORD*)(pBlk + pFunc->rettype);
4253 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4255 pFuncDesc->funcdesc.lprgelemdescParam =
4256 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4257 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4259 pArg = (WORD*)(pBlk + pFunc->arg_off);
4261 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4262 char *paramName = pNameTable + *pArg;
4263 BOOL HaveOffs;
4264 /* If arg type follows then paramName points to the 2nd
4265 letter of the name, else the next WORD is an offset to
4266 the arg type and paramName points to the first letter.
4267 So let's take one char off paramName and see if we're
4268 pointing at an alpha-numeric char. However if *pArg is
4269 0xffff or 0xfffe then the param has no name, the former
4270 meaning that the next WORD is the type, the latter
4271 meaning that the next WORD is an offset to the type. */
4273 HaveOffs = FALSE;
4274 if(*pArg == 0xffff)
4275 paramName = NULL;
4276 else if(*pArg == 0xfffe) {
4277 paramName = NULL;
4278 HaveOffs = TRUE;
4280 else if(paramName[-1] && !isalnum(paramName[-1]))
4281 HaveOffs = TRUE;
4283 pArg++;
4285 if(HaveOffs) { /* the next word is an offset to type */
4286 pType = (WORD*)(pBlk + *pArg);
4287 SLTG_DoElem(pType, pBlk,
4288 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4289 pArg++;
4290 } else {
4291 if(paramName)
4292 paramName--;
4293 pArg = SLTG_DoElem(pArg, pBlk,
4294 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4297 /* Are we an optional param ? */
4298 if(pFuncDesc->funcdesc.cParams - param <=
4299 pFuncDesc->funcdesc.cParamsOpt)
4300 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4302 if(paramName) {
4303 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4304 paramName - pNameTable, pTI->pTypeLib);
4305 } else {
4306 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4310 pTI->cFuncs = cFuncs;
4313 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4314 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4315 SLTG_TypeInfoTail *pTITail)
4317 char *pFirstItem;
4318 sltg_ref_lookup_t *ref_lookup = NULL;
4320 if(pTIHeader->href_table != 0xffffffff) {
4321 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4322 pNameTable);
4325 pFirstItem = pBlk;
4327 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4328 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4330 heap_free(ref_lookup);
4334 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4335 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4336 const SLTG_TypeInfoTail *pTITail)
4338 char *pFirstItem;
4339 sltg_ref_lookup_t *ref_lookup = NULL;
4341 if(pTIHeader->href_table != 0xffffffff) {
4342 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4343 pNameTable);
4346 pFirstItem = pBlk;
4348 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4349 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4352 if (pTITail->funcs_off != 0xffff)
4353 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4355 heap_free(ref_lookup);
4357 if (TRACE_ON(typelib))
4358 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4361 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4362 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4363 const SLTG_TypeInfoTail *pTITail)
4365 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4368 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4369 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4370 const SLTG_TypeInfoTail *pTITail)
4372 WORD *pType;
4373 sltg_ref_lookup_t *ref_lookup = NULL;
4375 if (pTITail->simple_alias) {
4376 /* if simple alias, no more processing required */
4377 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4378 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4379 return;
4382 if(pTIHeader->href_table != 0xffffffff) {
4383 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4384 pNameTable);
4387 /* otherwise it is an offset to a type */
4388 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4390 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4391 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4393 heap_free(ref_lookup);
4396 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4397 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4398 const SLTG_TypeInfoTail *pTITail)
4400 sltg_ref_lookup_t *ref_lookup = NULL;
4401 if (pTIHeader->href_table != 0xffffffff)
4402 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4403 pNameTable);
4405 if (pTITail->vars_off != 0xffff)
4406 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4408 if (pTITail->funcs_off != 0xffff)
4409 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4411 if (pTITail->impls_off != 0xffff)
4412 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4414 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4415 * of dispinterface functions including the IDispatch ones, so
4416 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4417 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4419 heap_free(ref_lookup);
4420 if (TRACE_ON(typelib))
4421 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4424 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4425 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4426 const SLTG_TypeInfoTail *pTITail)
4428 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4431 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4432 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4433 const SLTG_TypeInfoTail *pTITail)
4435 sltg_ref_lookup_t *ref_lookup = NULL;
4436 if (pTIHeader->href_table != 0xffffffff)
4437 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4438 pNameTable);
4440 if (pTITail->vars_off != 0xffff)
4441 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4443 if (pTITail->funcs_off != 0xffff)
4444 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4445 heap_free(ref_lookup);
4446 if (TRACE_ON(typelib))
4447 dump_TypeInfo(pTI);
4450 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4451 manageable copy of it into this */
4452 typedef struct {
4453 WORD small_no;
4454 char *index_name;
4455 char *other_name;
4456 WORD res1a;
4457 WORD name_offs;
4458 WORD more_bytes;
4459 char *extra;
4460 WORD res20;
4461 DWORD helpcontext;
4462 WORD res26;
4463 GUID uuid;
4464 } SLTG_InternalOtherTypeInfo;
4466 /****************************************************************************
4467 * ITypeLib2_Constructor_SLTG
4469 * loading a SLTG typelib from an in-memory image
4471 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4473 ITypeLibImpl *pTypeLibImpl;
4474 SLTG_Header *pHeader;
4475 SLTG_BlkEntry *pBlkEntry;
4476 SLTG_Magic *pMagic;
4477 SLTG_Index *pIndex;
4478 SLTG_Pad9 *pPad9;
4479 LPVOID pBlk, pFirstBlk;
4480 SLTG_LibBlk *pLibBlk;
4481 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4482 char *pAfterOTIBlks = NULL;
4483 char *pNameTable, *ptr;
4484 int i;
4485 DWORD len, order;
4486 ITypeInfoImpl **ppTypeInfoImpl;
4488 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4491 pTypeLibImpl = TypeLibImpl_Constructor();
4492 if (!pTypeLibImpl) return NULL;
4494 pHeader = pLib;
4496 TRACE_(typelib)("header:\n");
4497 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4498 pHeader->nrOfFileBlks );
4499 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4500 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4501 pHeader->SLTG_magic);
4502 return NULL;
4505 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4506 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4508 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4509 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4511 /* Next we have a magic block */
4512 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4514 /* Let's see if we're still in sync */
4515 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4516 sizeof(SLTG_COMPOBJ_MAGIC))) {
4517 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4518 return NULL;
4520 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4521 sizeof(SLTG_DIR_MAGIC))) {
4522 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4523 return NULL;
4526 pIndex = (SLTG_Index*)(pMagic+1);
4528 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4530 pFirstBlk = pPad9 + 1;
4532 /* We'll set up a ptr to the main library block, which is the last one. */
4534 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4535 pBlkEntry[order].next != 0;
4536 order = pBlkEntry[order].next - 1, i++) {
4537 pBlk = (char*)pBlk + pBlkEntry[order].len;
4539 pLibBlk = pBlk;
4541 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4543 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4544 interspersed */
4546 len += 0x40;
4548 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4550 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4553 ptr = (char*)pLibBlk + len;
4555 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4556 WORD w, extra;
4557 len = 0;
4559 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4561 w = *(WORD*)(ptr + 2);
4562 if(w != 0xffff) {
4563 len += w;
4564 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4565 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4566 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4568 w = *(WORD*)(ptr + 4 + len);
4569 if(w != 0xffff) {
4570 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4571 len += w;
4572 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4573 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4574 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4576 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4577 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4578 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4579 if(extra) {
4580 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4581 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4582 len += extra;
4584 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4585 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4586 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4587 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4588 len += sizeof(SLTG_OtherTypeInfo);
4589 ptr += len;
4592 pAfterOTIBlks = ptr;
4594 /* Skip this WORD and get the next DWORD */
4595 len = *(DWORD*)(pAfterOTIBlks + 2);
4597 /* Now add this to pLibBLk look at what we're pointing at and
4598 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4599 dust and we should be pointing at the beginning of the name
4600 table */
4602 pNameTable = (char*)pLibBlk + len;
4604 switch(*(WORD*)pNameTable) {
4605 case 0xffff:
4606 break;
4607 case 0x0200:
4608 pNameTable += 0x20;
4609 break;
4610 default:
4611 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4612 break;
4615 pNameTable += 0x216;
4617 pNameTable += 2;
4619 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4621 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4624 /* Hopefully we now have enough ptrs set up to actually read in
4625 some TypeInfos. It's not clear which order to do them in, so
4626 I'll just follow the links along the BlkEntry chain and read
4627 them in the order in which they are in the file */
4629 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4630 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4632 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4633 pBlkEntry[order].next != 0;
4634 order = pBlkEntry[order].next - 1, i++) {
4636 SLTG_TypeInfoHeader *pTIHeader;
4637 SLTG_TypeInfoTail *pTITail;
4638 SLTG_MemberHeader *pMemHeader;
4640 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4641 FIXME_(typelib)("Index strings don't match\n");
4642 heap_free(pOtherTypeInfoBlks);
4643 return NULL;
4646 pTIHeader = pBlk;
4647 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4648 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4649 heap_free(pOtherTypeInfoBlks);
4650 return NULL;
4652 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4653 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4654 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4656 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4657 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4658 (*ppTypeInfoImpl)->index = i;
4659 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4660 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4661 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4662 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4663 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4664 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4665 (*ppTypeInfoImpl)->wTypeFlags =
4666 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4668 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4669 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4671 if((pTIHeader->typeflags1 & 7) != 2)
4672 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4673 if(pTIHeader->typeflags3 != 2)
4674 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4676 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4677 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4678 typekind_desc[pTIHeader->typekind],
4679 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4680 (*ppTypeInfoImpl)->wTypeFlags);
4682 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4684 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4686 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4687 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4688 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4690 switch(pTIHeader->typekind) {
4691 case TKIND_ENUM:
4692 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4693 pTIHeader, pTITail);
4694 break;
4696 case TKIND_RECORD:
4697 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4698 pTIHeader, pTITail);
4699 break;
4701 case TKIND_INTERFACE:
4702 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4703 pTIHeader, pTITail);
4704 break;
4706 case TKIND_COCLASS:
4707 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4708 pTIHeader, pTITail);
4709 break;
4711 case TKIND_ALIAS:
4712 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4713 pTIHeader, pTITail);
4714 break;
4716 case TKIND_DISPATCH:
4717 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4718 pTIHeader, pTITail);
4719 break;
4721 case TKIND_MODULE:
4722 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4723 pTIHeader, pTITail);
4724 break;
4726 default:
4727 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4728 break;
4732 /* could get cFuncs, cVars and cImplTypes from here
4733 but we've already set those */
4734 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4735 X(06);
4736 X(16);
4737 X(18);
4738 X(1a);
4739 X(1e);
4740 X(24);
4741 X(26);
4742 X(2a);
4743 X(2c);
4744 X(2e);
4745 X(30);
4746 X(32);
4747 X(34);
4748 #undef X
4749 ++ppTypeInfoImpl;
4750 pBlk = (char*)pBlk + pBlkEntry[order].len;
4753 if(i != pTypeLibImpl->TypeInfoCount) {
4754 FIXME("Somehow processed %d TypeInfos\n", i);
4755 heap_free(pOtherTypeInfoBlks);
4756 return NULL;
4759 heap_free(pOtherTypeInfoBlks);
4760 return &pTypeLibImpl->ITypeLib2_iface;
4763 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4765 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4767 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4769 if(IsEqualIID(riid, &IID_IUnknown) ||
4770 IsEqualIID(riid,&IID_ITypeLib)||
4771 IsEqualIID(riid,&IID_ITypeLib2))
4773 *ppv = &This->ITypeLib2_iface;
4775 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4776 IsEqualIID(riid, &IID_ICreateTypeLib2))
4778 *ppv = &This->ICreateTypeLib2_iface;
4780 else
4782 *ppv = NULL;
4783 TRACE("-- Interface: E_NOINTERFACE\n");
4784 return E_NOINTERFACE;
4787 IUnknown_AddRef((IUnknown*)*ppv);
4788 return S_OK;
4791 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4793 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4794 ULONG ref = InterlockedIncrement(&This->ref);
4796 TRACE("(%p) ref=%u\n", This, ref);
4798 return ref;
4801 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4803 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4804 ULONG ref = InterlockedDecrement(&This->ref);
4806 TRACE("(%p) ref=%u\n",This, ref);
4808 if (!ref)
4810 TLBImpLib *pImpLib, *pImpLibNext;
4811 TLBRefType *ref_type;
4812 TLBString *tlbstr, *tlbstr_next;
4813 TLBGuid *tlbguid, *tlbguid_next;
4814 void *cursor2;
4815 int i;
4817 /* remove cache entry */
4818 if(This->path)
4820 TRACE("removing from cache list\n");
4821 EnterCriticalSection(&cache_section);
4822 if(This->entry.next)
4823 list_remove(&This->entry);
4824 LeaveCriticalSection(&cache_section);
4825 heap_free(This->path);
4827 TRACE(" destroying ITypeLib(%p)\n",This);
4829 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4830 list_remove(&tlbstr->entry);
4831 SysFreeString(tlbstr->str);
4832 heap_free(tlbstr);
4835 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4836 list_remove(&tlbstr->entry);
4837 SysFreeString(tlbstr->str);
4838 heap_free(tlbstr);
4841 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4842 list_remove(&tlbguid->entry);
4843 heap_free(tlbguid);
4846 TLB_FreeCustData(&This->custdata_list);
4848 for (i = 0; i < This->ctTypeDesc; i++)
4849 if (This->pTypeDesc[i].vt == VT_CARRAY)
4850 heap_free(This->pTypeDesc[i].u.lpadesc);
4852 heap_free(This->pTypeDesc);
4854 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4856 if (pImpLib->pImpTypeLib)
4857 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4858 SysFreeString(pImpLib->name);
4860 list_remove(&pImpLib->entry);
4861 heap_free(pImpLib);
4864 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4866 list_remove(&ref_type->entry);
4867 heap_free(ref_type);
4870 for (i = 0; i < This->TypeInfoCount; ++i){
4871 heap_free(This->typeinfos[i]->tdescAlias);
4872 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4874 heap_free(This->typeinfos);
4875 heap_free(This);
4876 return 0;
4879 return ref;
4882 /* ITypeLib::GetTypeInfoCount
4884 * Returns the number of type descriptions in the type library
4886 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4888 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4889 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4890 return This->TypeInfoCount;
4893 /* ITypeLib::GetTypeInfo
4895 * retrieves the specified type description in the library.
4897 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4898 ITypeLib2 *iface,
4899 UINT index,
4900 ITypeInfo **ppTInfo)
4902 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4904 TRACE("%p %u %p\n", This, index, ppTInfo);
4906 if(!ppTInfo)
4907 return E_INVALIDARG;
4909 if(index >= This->TypeInfoCount)
4910 return TYPE_E_ELEMENTNOTFOUND;
4912 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4913 ITypeInfo_AddRef(*ppTInfo);
4915 return S_OK;
4919 /* ITypeLibs::GetTypeInfoType
4921 * Retrieves the type of a type description.
4923 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4924 ITypeLib2 *iface,
4925 UINT index,
4926 TYPEKIND *pTKind)
4928 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4930 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4932 if(!pTKind)
4933 return E_INVALIDARG;
4935 if(index >= This->TypeInfoCount)
4936 return TYPE_E_ELEMENTNOTFOUND;
4938 *pTKind = This->typeinfos[index]->typekind;
4940 return S_OK;
4943 /* ITypeLib::GetTypeInfoOfGuid
4945 * Retrieves the type description that corresponds to the specified GUID.
4948 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4949 ITypeLib2 *iface,
4950 REFGUID guid,
4951 ITypeInfo **ppTInfo)
4953 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4954 int i;
4956 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4958 for(i = 0; i < This->TypeInfoCount; ++i){
4959 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4960 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4961 ITypeInfo_AddRef(*ppTInfo);
4962 return S_OK;
4966 return TYPE_E_ELEMENTNOTFOUND;
4969 /* ITypeLib::GetLibAttr
4971 * Retrieves the structure that contains the library's attributes.
4974 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4975 ITypeLib2 *iface,
4976 LPTLIBATTR *attr)
4978 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4980 TRACE("(%p, %p)\n", This, attr);
4982 if (!attr) return E_INVALIDARG;
4984 *attr = heap_alloc(sizeof(**attr));
4985 if (!*attr) return E_OUTOFMEMORY;
4987 (*attr)->guid = *TLB_get_guid_null(This->guid);
4988 (*attr)->lcid = This->set_lcid;
4989 (*attr)->syskind = This->syskind;
4990 (*attr)->wMajorVerNum = This->ver_major;
4991 (*attr)->wMinorVerNum = This->ver_minor;
4992 (*attr)->wLibFlags = This->libflags;
4994 return S_OK;
4997 /* ITypeLib::GetTypeComp
4999 * Enables a client compiler to bind to a library's types, variables,
5000 * constants, and global functions.
5003 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
5004 ITypeLib2 *iface,
5005 ITypeComp **ppTComp)
5007 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5009 TRACE("(%p)->(%p)\n",This,ppTComp);
5010 *ppTComp = &This->ITypeComp_iface;
5011 ITypeComp_AddRef(*ppTComp);
5013 return S_OK;
5016 /* ITypeLib::GetDocumentation
5018 * Retrieves the library's documentation string, the complete Help file name
5019 * and path, and the context identifier for the library Help topic in the Help
5020 * file.
5022 * On a successful return all non-null BSTR pointers will have been set,
5023 * possibly to NULL.
5025 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
5026 ITypeLib2 *iface,
5027 INT index,
5028 BSTR *pBstrName,
5029 BSTR *pBstrDocString,
5030 DWORD *pdwHelpContext,
5031 BSTR *pBstrHelpFile)
5033 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5034 HRESULT result = E_INVALIDARG;
5035 ITypeInfo *pTInfo;
5037 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
5038 This, index,
5039 pBstrName, pBstrDocString,
5040 pdwHelpContext, pBstrHelpFile);
5042 if(index<0)
5044 /* documentation for the typelib */
5045 if(pBstrName)
5047 if (This->Name)
5049 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
5050 goto memerr1;
5052 else
5053 *pBstrName = NULL;
5055 if(pBstrDocString)
5057 if (This->DocString)
5059 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
5060 goto memerr2;
5062 else
5063 *pBstrDocString = NULL;
5065 if(pdwHelpContext)
5067 *pdwHelpContext = This->dwHelpContext;
5069 if(pBstrHelpFile)
5071 if (This->HelpFile)
5073 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5074 goto memerr3;
5076 else
5077 *pBstrHelpFile = NULL;
5080 result = S_OK;
5082 else
5084 /* for a typeinfo */
5085 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5087 if(SUCCEEDED(result))
5089 result = ITypeInfo_GetDocumentation(pTInfo,
5090 MEMBERID_NIL,
5091 pBstrName,
5092 pBstrDocString,
5093 pdwHelpContext, pBstrHelpFile);
5095 ITypeInfo_Release(pTInfo);
5098 return result;
5099 memerr3:
5100 if (pBstrDocString) SysFreeString (*pBstrDocString);
5101 memerr2:
5102 if (pBstrName) SysFreeString (*pBstrName);
5103 memerr1:
5104 return STG_E_INSUFFICIENTMEMORY;
5107 /* ITypeLib::IsName
5109 * Indicates whether a passed-in string contains the name of a type or member
5110 * described in the library.
5113 static HRESULT WINAPI ITypeLib2_fnIsName(
5114 ITypeLib2 *iface,
5115 LPOLESTR szNameBuf,
5116 ULONG lHashVal,
5117 BOOL *pfName)
5119 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5120 int tic;
5121 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5123 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5124 pfName);
5126 *pfName=TRUE;
5127 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5128 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5129 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5130 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5131 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5132 int pc;
5133 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5134 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5135 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5136 goto ITypeLib2_fnIsName_exit;
5139 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
5140 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5141 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5145 *pfName=FALSE;
5147 ITypeLib2_fnIsName_exit:
5148 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5149 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5151 return S_OK;
5154 /* ITypeLib::FindName
5156 * Finds occurrences of a type description in a type library. This may be used
5157 * to quickly verify that a name exists in a type library.
5160 static HRESULT WINAPI ITypeLib2_fnFindName(
5161 ITypeLib2 *iface,
5162 LPOLESTR name,
5163 ULONG hash,
5164 ITypeInfo **ppTInfo,
5165 MEMBERID *memid,
5166 UINT16 *found)
5168 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5169 int tic;
5170 UINT count = 0;
5171 UINT len;
5173 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5175 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5176 return E_INVALIDARG;
5178 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5179 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
5180 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5181 TLBVarDesc *var;
5182 UINT fdc;
5184 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
5185 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5186 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5187 int pc;
5189 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
5190 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
5191 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
5192 goto ITypeLib2_fnFindName_exit;
5196 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
5197 if (var)
5198 goto ITypeLib2_fnFindName_exit;
5200 continue;
5201 ITypeLib2_fnFindName_exit:
5202 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5203 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5204 count++;
5206 TRACE("found %d typeinfos\n", count);
5208 *found = count;
5210 return S_OK;
5213 /* ITypeLib::ReleaseTLibAttr
5215 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5218 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5219 ITypeLib2 *iface,
5220 TLIBATTR *pTLibAttr)
5222 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5223 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5224 heap_free(pTLibAttr);
5227 /* ITypeLib2::GetCustData
5229 * gets the custom data
5231 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5232 ITypeLib2 * iface,
5233 REFGUID guid,
5234 VARIANT *pVarVal)
5236 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5237 TLBCustData *pCData;
5239 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5241 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5242 if(!pCData)
5243 return TYPE_E_ELEMENTNOTFOUND;
5245 VariantInit(pVarVal);
5246 VariantCopy(pVarVal, &pCData->data);
5248 return S_OK;
5251 /* ITypeLib2::GetLibStatistics
5253 * Returns statistics about a type library that are required for efficient
5254 * sizing of hash tables.
5257 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5258 ITypeLib2 * iface,
5259 ULONG *pcUniqueNames,
5260 ULONG *pcchUniqueNames)
5262 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5264 FIXME("(%p): stub!\n", This);
5266 if(pcUniqueNames) *pcUniqueNames=1;
5267 if(pcchUniqueNames) *pcchUniqueNames=1;
5268 return S_OK;
5271 /* ITypeLib2::GetDocumentation2
5273 * Retrieves the library's documentation string, the complete Help file name
5274 * and path, the localization context to use, and the context ID for the
5275 * library Help topic in the Help file.
5278 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5279 ITypeLib2 * iface,
5280 INT index,
5281 LCID lcid,
5282 BSTR *pbstrHelpString,
5283 DWORD *pdwHelpStringContext,
5284 BSTR *pbstrHelpStringDll)
5286 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5287 HRESULT result;
5288 ITypeInfo *pTInfo;
5290 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5292 /* the help string should be obtained from the helpstringdll,
5293 * using the _DLLGetDocumentation function, based on the supplied
5294 * lcid. Nice to do sometime...
5296 if(index<0)
5298 /* documentation for the typelib */
5299 if(pbstrHelpString)
5300 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5301 if(pdwHelpStringContext)
5302 *pdwHelpStringContext=This->dwHelpContext;
5303 if(pbstrHelpStringDll)
5304 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5306 result = S_OK;
5308 else
5310 /* for a typeinfo */
5311 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5313 if(SUCCEEDED(result))
5315 ITypeInfo2 * pTInfo2;
5316 result = ITypeInfo_QueryInterface(pTInfo,
5317 &IID_ITypeInfo2,
5318 (LPVOID*) &pTInfo2);
5320 if(SUCCEEDED(result))
5322 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5323 MEMBERID_NIL,
5324 lcid,
5325 pbstrHelpString,
5326 pdwHelpStringContext,
5327 pbstrHelpStringDll);
5329 ITypeInfo2_Release(pTInfo2);
5332 ITypeInfo_Release(pTInfo);
5335 return result;
5338 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5340 TLBCustData *pCData;
5341 unsigned int ct;
5342 CUSTDATAITEM *cdi;
5344 ct = list_count(custdata_list);
5346 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5347 if(!pCustData->prgCustData)
5348 return E_OUTOFMEMORY;
5350 pCustData->cCustData = ct;
5352 cdi = pCustData->prgCustData;
5353 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5354 cdi->guid = *TLB_get_guid_null(pCData->guid);
5355 VariantCopy(&cdi->varValue, &pCData->data);
5356 ++cdi;
5359 return S_OK;
5363 /* ITypeLib2::GetAllCustData
5365 * Gets all custom data items for the library.
5368 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5369 ITypeLib2 * iface,
5370 CUSTDATA *pCustData)
5372 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5373 TRACE("(%p)->(%p)\n", This, pCustData);
5374 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5377 static const ITypeLib2Vtbl tlbvt = {
5378 ITypeLib2_fnQueryInterface,
5379 ITypeLib2_fnAddRef,
5380 ITypeLib2_fnRelease,
5381 ITypeLib2_fnGetTypeInfoCount,
5382 ITypeLib2_fnGetTypeInfo,
5383 ITypeLib2_fnGetTypeInfoType,
5384 ITypeLib2_fnGetTypeInfoOfGuid,
5385 ITypeLib2_fnGetLibAttr,
5386 ITypeLib2_fnGetTypeComp,
5387 ITypeLib2_fnGetDocumentation,
5388 ITypeLib2_fnIsName,
5389 ITypeLib2_fnFindName,
5390 ITypeLib2_fnReleaseTLibAttr,
5392 ITypeLib2_fnGetCustData,
5393 ITypeLib2_fnGetLibStatistics,
5394 ITypeLib2_fnGetDocumentation2,
5395 ITypeLib2_fnGetAllCustData
5399 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5401 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5403 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5406 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5408 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5410 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5413 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5415 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5417 return ITypeLib2_Release(&This->ITypeLib2_iface);
5420 static HRESULT WINAPI ITypeLibComp_fnBind(
5421 ITypeComp * iface,
5422 OLECHAR * szName,
5423 ULONG lHash,
5424 WORD wFlags,
5425 ITypeInfo ** ppTInfo,
5426 DESCKIND * pDescKind,
5427 BINDPTR * pBindPtr)
5429 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5430 BOOL typemismatch = FALSE;
5431 int i;
5433 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5435 *pDescKind = DESCKIND_NONE;
5436 pBindPtr->lptcomp = NULL;
5437 *ppTInfo = NULL;
5439 for(i = 0; i < This->TypeInfoCount; ++i){
5440 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5441 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5443 /* FIXME: check wFlags here? */
5444 /* FIXME: we should use a hash table to look this info up using lHash
5445 * instead of an O(n) search */
5446 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5447 (pTypeInfo->typekind == TKIND_MODULE))
5449 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5451 *pDescKind = DESCKIND_TYPECOMP;
5452 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5453 ITypeComp_AddRef(pBindPtr->lptcomp);
5454 TRACE("module or enum: %s\n", debugstr_w(szName));
5455 return S_OK;
5459 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5460 (pTypeInfo->typekind == TKIND_ENUM))
5462 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5463 HRESULT hr;
5465 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5466 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5468 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5469 return S_OK;
5471 else if (hr == TYPE_E_TYPEMISMATCH)
5472 typemismatch = TRUE;
5475 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5476 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5478 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5479 HRESULT hr;
5480 ITypeInfo *subtypeinfo;
5481 BINDPTR subbindptr;
5482 DESCKIND subdesckind;
5484 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5485 &subtypeinfo, &subdesckind, &subbindptr);
5486 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5488 TYPEDESC tdesc_appobject;
5489 const VARDESC vardesc_appobject =
5491 -2, /* memid */
5492 NULL, /* lpstrSchema */
5494 0 /* oInst */
5497 /* ELEMDESC */
5499 /* TYPEDESC */
5501 &tdesc_appobject
5503 VT_PTR
5506 0, /* wVarFlags */
5507 VAR_STATIC /* varkind */
5510 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5511 tdesc_appobject.vt = VT_USERDEFINED;
5513 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5515 /* cleanup things filled in by Bind call so we can put our
5516 * application object data in there instead */
5517 switch (subdesckind)
5519 case DESCKIND_FUNCDESC:
5520 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5521 break;
5522 case DESCKIND_VARDESC:
5523 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5524 break;
5525 default:
5526 break;
5528 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5530 if (pTypeInfo->hreftype == -1)
5531 FIXME("no hreftype for interface %p\n", pTypeInfo);
5533 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5534 if (FAILED(hr))
5535 return hr;
5537 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5538 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5539 ITypeInfo_AddRef(*ppTInfo);
5540 return S_OK;
5542 else if (hr == TYPE_E_TYPEMISMATCH)
5543 typemismatch = TRUE;
5547 if (typemismatch)
5549 TRACE("type mismatch %s\n", debugstr_w(szName));
5550 return TYPE_E_TYPEMISMATCH;
5552 else
5554 TRACE("name not found %s\n", debugstr_w(szName));
5555 return S_OK;
5559 static HRESULT WINAPI ITypeLibComp_fnBindType(
5560 ITypeComp * iface,
5561 OLECHAR * szName,
5562 ULONG lHash,
5563 ITypeInfo ** ppTInfo,
5564 ITypeComp ** ppTComp)
5566 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5567 ITypeInfoImpl *info;
5569 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5571 if(!szName || !ppTInfo || !ppTComp)
5572 return E_INVALIDARG;
5574 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5575 if(!info){
5576 *ppTInfo = NULL;
5577 *ppTComp = NULL;
5578 return S_OK;
5581 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5582 ITypeInfo_AddRef(*ppTInfo);
5583 *ppTComp = &info->ITypeComp_iface;
5584 ITypeComp_AddRef(*ppTComp);
5586 return S_OK;
5589 static const ITypeCompVtbl tlbtcvt =
5592 ITypeLibComp_fnQueryInterface,
5593 ITypeLibComp_fnAddRef,
5594 ITypeLibComp_fnRelease,
5596 ITypeLibComp_fnBind,
5597 ITypeLibComp_fnBindType
5600 /*================== ITypeInfo(2) Methods ===================================*/
5601 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5603 ITypeInfoImpl *pTypeInfoImpl;
5605 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5606 if (pTypeInfoImpl)
5608 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5609 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5610 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5611 pTypeInfoImpl->ref = 0;
5612 pTypeInfoImpl->hreftype = -1;
5613 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5614 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5615 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5616 list_init(pTypeInfoImpl->pcustdata_list);
5618 TRACE("(%p)\n", pTypeInfoImpl);
5619 return pTypeInfoImpl;
5622 /* ITypeInfo::QueryInterface
5624 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5625 ITypeInfo2 *iface,
5626 REFIID riid,
5627 VOID **ppvObject)
5629 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5631 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5633 *ppvObject=NULL;
5634 if(IsEqualIID(riid, &IID_IUnknown) ||
5635 IsEqualIID(riid,&IID_ITypeInfo)||
5636 IsEqualIID(riid,&IID_ITypeInfo2))
5637 *ppvObject = This;
5638 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5639 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5640 *ppvObject = &This->ICreateTypeInfo2_iface;
5642 if(*ppvObject){
5643 ITypeInfo2_AddRef(iface);
5644 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5645 return S_OK;
5647 TRACE("-- Interface: E_NOINTERFACE\n");
5648 return E_NOINTERFACE;
5651 /* ITypeInfo::AddRef
5653 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5655 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5656 ULONG ref = InterlockedIncrement(&This->ref);
5658 TRACE("(%p)->ref is %u\n",This, ref);
5660 if (ref == 1 /* incremented from 0 */)
5661 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5663 return ref;
5666 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5668 UINT i;
5670 TRACE("destroying ITypeInfo(%p)\n",This);
5672 for (i = 0; i < This->cFuncs; ++i)
5674 int j;
5675 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5676 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5678 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5679 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5680 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5681 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5683 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5684 heap_free(pFInfo->pParamDesc);
5685 TLB_FreeCustData(&pFInfo->custdata_list);
5687 heap_free(This->funcdescs);
5689 for(i = 0; i < This->cVars; ++i)
5691 TLBVarDesc *pVInfo = &This->vardescs[i];
5692 if (pVInfo->vardesc_create) {
5693 TLB_FreeVarDesc(pVInfo->vardesc_create);
5694 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5695 VariantClear(pVInfo->vardesc.u.lpvarValue);
5696 heap_free(pVInfo->vardesc.u.lpvarValue);
5698 TLB_FreeCustData(&pVInfo->custdata_list);
5700 heap_free(This->vardescs);
5702 if(This->impltypes){
5703 for (i = 0; i < This->cImplTypes; ++i){
5704 TLBImplType *pImpl = &This->impltypes[i];
5705 TLB_FreeCustData(&pImpl->custdata_list);
5707 heap_free(This->impltypes);
5710 TLB_FreeCustData(&This->custdata_list);
5712 heap_free(This);
5715 /* ITypeInfo::Release
5717 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5719 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5720 ULONG ref = InterlockedDecrement(&This->ref);
5722 TRACE("(%p)->(%u)\n",This, ref);
5724 if (!ref)
5726 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5727 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5728 if (not_attached_to_typelib)
5729 heap_free(This);
5730 /* otherwise This will be freed when typelib is freed */
5733 return ref;
5736 /* ITypeInfo::GetTypeAttr
5738 * Retrieves a TYPEATTR structure that contains the attributes of the type
5739 * description.
5742 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5743 LPTYPEATTR *ppTypeAttr)
5745 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5746 SIZE_T size;
5748 TRACE("(%p)\n",This);
5750 size = sizeof(**ppTypeAttr);
5751 if (This->typekind == TKIND_ALIAS && This->tdescAlias)
5752 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5754 *ppTypeAttr = heap_alloc(size);
5755 if (!*ppTypeAttr)
5756 return E_OUTOFMEMORY;
5758 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5759 (*ppTypeAttr)->lcid = This->lcid;
5760 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5761 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5762 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5763 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5764 (*ppTypeAttr)->typekind = This->typekind;
5765 (*ppTypeAttr)->cFuncs = This->cFuncs;
5766 (*ppTypeAttr)->cVars = This->cVars;
5767 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5768 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5769 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5770 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5771 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5772 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5773 (*ppTypeAttr)->idldescType = This->idldescType;
5775 if (This->tdescAlias)
5776 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5777 This->tdescAlias, *ppTypeAttr + 1);
5778 else{
5779 (*ppTypeAttr)->tdescAlias.vt = VT_EMPTY;
5780 (*ppTypeAttr)->tdescAlias.u.lptdesc = NULL;
5783 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5784 /* This should include all the inherited funcs */
5785 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5786 /* This is always the size of IDispatch's vtbl */
5787 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5788 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5790 return S_OK;
5793 /* ITypeInfo::GetTypeComp
5795 * Retrieves the ITypeComp interface for the type description, which enables a
5796 * client compiler to bind to the type description's members.
5799 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5800 ITypeComp * *ppTComp)
5802 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5804 TRACE("(%p)->(%p)\n", This, ppTComp);
5806 *ppTComp = &This->ITypeComp_iface;
5807 ITypeComp_AddRef(*ppTComp);
5808 return S_OK;
5811 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5813 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5814 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5815 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5816 return size;
5819 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5821 *dest = *src;
5822 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5823 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5825 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5826 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5827 *buffer += sizeof(PARAMDESCEX);
5828 *pparamdescex_dest = *pparamdescex_src;
5829 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5830 VariantInit(&pparamdescex_dest->varDefaultValue);
5831 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5832 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5834 else
5835 dest->u.paramdesc.pparamdescex = NULL;
5836 return S_OK;
5839 static HRESULT TLB_SanitizeBSTR(BSTR str)
5841 UINT len = SysStringLen(str), i;
5842 for (i = 0; i < len; ++i)
5843 if (str[i] > 0x7f)
5844 str[i] = '?';
5845 return S_OK;
5848 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5850 if (V_VT(var) == VT_INT)
5851 return VariantChangeType(var, var, 0, VT_I4);
5852 else if (V_VT(var) == VT_UINT)
5853 return VariantChangeType(var, var, 0, VT_UI4);
5854 else if (V_VT(var) == VT_BSTR)
5855 return TLB_SanitizeBSTR(V_BSTR(var));
5857 return S_OK;
5860 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5862 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5863 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5866 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5868 FUNCDESC *dest;
5869 char *buffer;
5870 SIZE_T size = sizeof(*src);
5871 SHORT i;
5872 HRESULT hr;
5874 size += sizeof(*src->lprgscode) * src->cScodes;
5875 size += TLB_SizeElemDesc(&src->elemdescFunc);
5876 for (i = 0; i < src->cParams; i++)
5878 size += sizeof(ELEMDESC);
5879 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5882 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5883 if (!dest) return E_OUTOFMEMORY;
5885 *dest = *src;
5886 if (dispinterface) /* overwrite funckind */
5887 dest->funckind = FUNC_DISPATCH;
5888 buffer = (char *)(dest + 1);
5890 dest->oVft = dest->oVft & 0xFFFC;
5892 if (dest->cScodes) {
5893 dest->lprgscode = (SCODE *)buffer;
5894 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5895 buffer += sizeof(*src->lprgscode) * src->cScodes;
5896 } else
5897 dest->lprgscode = NULL;
5899 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5900 if (FAILED(hr))
5902 SysFreeString((BSTR)dest);
5903 return hr;
5906 if (dest->cParams) {
5907 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5908 buffer += sizeof(ELEMDESC) * src->cParams;
5909 for (i = 0; i < src->cParams; i++)
5911 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5912 if (FAILED(hr))
5913 break;
5915 if (FAILED(hr))
5917 /* undo the above actions */
5918 for (i = i - 1; i >= 0; i--)
5919 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5920 TLB_FreeElemDesc(&dest->elemdescFunc);
5921 SysFreeString((BSTR)dest);
5922 return hr;
5924 } else
5925 dest->lprgelemdescParam = NULL;
5927 /* special treatment for dispinterfaces: this makes functions appear
5928 * to return their [retval] value when it is really returning an
5929 * HRESULT */
5930 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5932 if (dest->cParams &&
5933 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5935 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5936 if (elemdesc->tdesc.vt != VT_PTR)
5938 ERR("elemdesc should have started with VT_PTR instead of:\n");
5939 if (ERR_ON(ole))
5940 dump_ELEMDESC(elemdesc);
5941 return E_UNEXPECTED;
5944 /* copy last parameter to the return value. we are using a flat
5945 * buffer so there is no danger of leaking memory in
5946 * elemdescFunc */
5947 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5949 /* remove the last parameter */
5950 dest->cParams--;
5952 else
5953 /* otherwise this function is made to appear to have no return
5954 * value */
5955 dest->elemdescFunc.tdesc.vt = VT_VOID;
5959 *dest_ptr = dest;
5960 return S_OK;
5963 static void TLB_FreeVarDesc(VARDESC *var_desc)
5965 TLB_FreeElemDesc(&var_desc->elemdescVar);
5966 if (var_desc->varkind == VAR_CONST)
5967 VariantClear(var_desc->u.lpvarValue);
5968 SysFreeString((BSTR)var_desc);
5971 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5973 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5975 if (index >= This->cFuncs)
5976 return TYPE_E_ELEMENTNOTFOUND;
5978 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5979 return S_OK;
5982 /* internal function to make the inherited interfaces' methods appear
5983 * part of the interface */
5984 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5985 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5987 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5988 HRESULT hr;
5989 UINT implemented_funcs = 0;
5991 if (funcs)
5992 *funcs = 0;
5993 else
5994 *hrefoffset = DISPATCH_HREF_OFFSET;
5996 if(This->impltypes)
5998 ITypeInfo *pSubTypeInfo;
5999 UINT sub_funcs;
6001 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6002 if (FAILED(hr))
6003 return hr;
6005 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
6006 index,
6007 ppFuncDesc,
6008 &sub_funcs, hrefoffset);
6009 implemented_funcs += sub_funcs;
6010 ITypeInfo_Release(pSubTypeInfo);
6011 if (SUCCEEDED(hr))
6012 return hr;
6013 *hrefoffset += DISPATCH_HREF_OFFSET;
6016 if (funcs)
6017 *funcs = implemented_funcs + This->cFuncs;
6018 else
6019 *hrefoffset = 0;
6021 if (index < implemented_funcs)
6022 return E_INVALIDARG;
6023 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
6024 ppFuncDesc);
6027 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
6029 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
6030 while (TRUE)
6032 switch (pTypeDesc->vt)
6034 case VT_USERDEFINED:
6035 pTypeDesc->u.hreftype += hrefoffset;
6036 return;
6037 case VT_PTR:
6038 case VT_SAFEARRAY:
6039 pTypeDesc = pTypeDesc->u.lptdesc;
6040 break;
6041 case VT_CARRAY:
6042 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
6043 break;
6044 default:
6045 return;
6050 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
6052 SHORT i;
6053 for (i = 0; i < pFuncDesc->cParams; i++)
6054 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
6055 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
6058 /* ITypeInfo::GetFuncDesc
6060 * Retrieves the FUNCDESC structure that contains information about a
6061 * specified function.
6064 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
6065 LPFUNCDESC *ppFuncDesc)
6067 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6068 const FUNCDESC *internal_funcdesc;
6069 HRESULT hr;
6070 UINT hrefoffset = 0;
6072 TRACE("(%p) index %d\n", This, index);
6074 if (!ppFuncDesc)
6075 return E_INVALIDARG;
6077 if (This->needs_layout)
6078 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6080 if (This->typekind == TKIND_DISPATCH)
6081 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6082 &internal_funcdesc, NULL,
6083 &hrefoffset);
6084 else
6085 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6086 &internal_funcdesc);
6087 if (FAILED(hr))
6089 WARN("description for function %d not found\n", index);
6090 return hr;
6093 hr = TLB_AllocAndInitFuncDesc(
6094 internal_funcdesc,
6095 ppFuncDesc,
6096 This->typekind == TKIND_DISPATCH);
6098 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
6099 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6101 TRACE("-- 0x%08x\n", hr);
6102 return hr;
6105 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6107 VARDESC *dest;
6108 char *buffer;
6109 SIZE_T size = sizeof(*src);
6110 HRESULT hr;
6112 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6113 if (src->varkind == VAR_CONST)
6114 size += sizeof(VARIANT);
6115 size += TLB_SizeElemDesc(&src->elemdescVar);
6117 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6118 if (!dest) return E_OUTOFMEMORY;
6120 *dest = *src;
6121 buffer = (char *)(dest + 1);
6122 if (src->lpstrSchema)
6124 int len;
6125 dest->lpstrSchema = (LPOLESTR)buffer;
6126 len = strlenW(src->lpstrSchema);
6127 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6128 buffer += (len + 1) * sizeof(WCHAR);
6131 if (src->varkind == VAR_CONST)
6133 HRESULT hr;
6135 dest->u.lpvarValue = (VARIANT *)buffer;
6136 *dest->u.lpvarValue = *src->u.lpvarValue;
6137 buffer += sizeof(VARIANT);
6138 VariantInit(dest->u.lpvarValue);
6139 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6140 if (FAILED(hr))
6142 SysFreeString((BSTR)dest);
6143 return hr;
6146 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6147 if (FAILED(hr))
6149 if (src->varkind == VAR_CONST)
6150 VariantClear(dest->u.lpvarValue);
6151 SysFreeString((BSTR)dest);
6152 return hr;
6154 *dest_ptr = dest;
6155 return S_OK;
6158 /* ITypeInfo::GetVarDesc
6160 * Retrieves a VARDESC structure that describes the specified variable.
6163 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6164 LPVARDESC *ppVarDesc)
6166 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6167 const TLBVarDesc *pVDesc = &This->vardescs[index];
6169 TRACE("(%p) index %d\n", This, index);
6171 if(index >= This->cVars)
6172 return TYPE_E_ELEMENTNOTFOUND;
6174 if (This->needs_layout)
6175 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6177 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6180 /* ITypeInfo_GetNames
6182 * Retrieves the variable with the specified member ID (or the name of the
6183 * property or method and its parameters) that correspond to the specified
6184 * function ID.
6186 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6187 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6189 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6190 const TLBFuncDesc *pFDesc;
6191 const TLBVarDesc *pVDesc;
6192 int i;
6193 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6195 if(!rgBstrNames)
6196 return E_INVALIDARG;
6198 *pcNames = 0;
6200 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
6201 if(pFDesc)
6203 if(!cMaxNames || !pFDesc->Name)
6204 return S_OK;
6206 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6207 ++(*pcNames);
6209 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6210 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6211 return S_OK;
6212 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6213 ++(*pcNames);
6215 return S_OK;
6218 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
6219 if(pVDesc)
6221 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6222 *pcNames=1;
6224 else
6226 if(This->impltypes &&
6227 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
6228 /* recursive search */
6229 ITypeInfo *pTInfo;
6230 HRESULT result;
6231 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6232 if(SUCCEEDED(result))
6234 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6235 ITypeInfo_Release(pTInfo);
6236 return result;
6238 WARN("Could not search inherited interface!\n");
6240 else
6242 WARN("no names found\n");
6244 *pcNames=0;
6245 return TYPE_E_ELEMENTNOTFOUND;
6247 return S_OK;
6251 /* ITypeInfo::GetRefTypeOfImplType
6253 * If a type description describes a COM class, it retrieves the type
6254 * description of the implemented interface types. For an interface,
6255 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6256 * if any exist.
6259 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6260 ITypeInfo2 *iface,
6261 UINT index,
6262 HREFTYPE *pRefType)
6264 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6265 HRESULT hr = S_OK;
6267 TRACE("(%p) index %d\n", This, index);
6268 if (TRACE_ON(ole)) dump_TypeInfo(This);
6270 if(index==(UINT)-1)
6272 /* only valid on dual interfaces;
6273 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6276 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6278 *pRefType = -2;
6280 else
6282 hr = TYPE_E_ELEMENTNOTFOUND;
6285 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6287 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6288 *pRefType = This->pTypeLib->dispatch_href;
6290 else
6292 if(index >= This->cImplTypes)
6293 hr = TYPE_E_ELEMENTNOTFOUND;
6294 else{
6295 *pRefType = This->impltypes[index].hRef;
6296 if(This->typekind == TKIND_INTERFACE)
6297 *pRefType |= 0x2;
6301 if(TRACE_ON(ole))
6303 if(SUCCEEDED(hr))
6304 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6305 else
6306 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6309 return hr;
6312 /* ITypeInfo::GetImplTypeFlags
6314 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6315 * or base interface in a type description.
6317 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6318 UINT index, INT *pImplTypeFlags)
6320 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6322 TRACE("(%p) index %d\n", This, index);
6324 if(!pImplTypeFlags)
6325 return E_INVALIDARG;
6327 if(This->typekind == TKIND_DISPATCH && index == 0){
6328 *pImplTypeFlags = 0;
6329 return S_OK;
6332 if(index >= This->cImplTypes)
6333 return TYPE_E_ELEMENTNOTFOUND;
6335 *pImplTypeFlags = This->impltypes[index].implflags;
6337 return S_OK;
6340 /* GetIDsOfNames
6341 * Maps between member names and member IDs, and parameter names and
6342 * parameter IDs.
6344 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6345 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6347 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6348 const TLBVarDesc *pVDesc;
6349 HRESULT ret=S_OK;
6350 UINT i, fdc;
6352 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6353 cNames);
6355 /* init out parameters in case of failure */
6356 for (i = 0; i < cNames; i++)
6357 pMemId[i] = MEMBERID_NIL;
6359 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6360 int j;
6361 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6362 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6363 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6364 for(i=1; i < cNames; i++){
6365 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6366 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6367 break;
6368 if( j<pFDesc->funcdesc.cParams)
6369 pMemId[i]=j;
6370 else
6371 ret=DISP_E_UNKNOWNNAME;
6373 TRACE("-- 0x%08x\n", ret);
6374 return ret;
6377 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6378 if(pVDesc){
6379 if(cNames)
6380 *pMemId = pVDesc->vardesc.memid;
6381 return ret;
6383 /* not found, see if it can be found in an inherited interface */
6384 if(This->impltypes) {
6385 /* recursive search */
6386 ITypeInfo *pTInfo;
6387 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6388 if(SUCCEEDED(ret)){
6389 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6390 ITypeInfo_Release(pTInfo);
6391 return ret;
6393 WARN("Could not search inherited interface!\n");
6394 } else
6395 WARN("no names found\n");
6396 return DISP_E_UNKNOWNNAME;
6400 #ifdef __i386__
6402 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6403 __ASM_GLOBAL_FUNC( call_method,
6404 "pushl %ebp\n\t"
6405 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6406 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6407 "movl %esp,%ebp\n\t"
6408 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6409 "pushl %esi\n\t"
6410 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6411 "pushl %edi\n\t"
6412 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6413 "movl 12(%ebp),%edx\n\t"
6414 "movl %esp,%edi\n\t"
6415 "shll $2,%edx\n\t"
6416 "jz 1f\n\t"
6417 "subl %edx,%edi\n\t"
6418 "andl $~15,%edi\n\t"
6419 "movl %edi,%esp\n\t"
6420 "movl 12(%ebp),%ecx\n\t"
6421 "movl 16(%ebp),%esi\n\t"
6422 "cld\n\t"
6423 "rep; movsl\n"
6424 "1:\tcall *8(%ebp)\n\t"
6425 "subl %esp,%edi\n\t"
6426 "movl 20(%ebp),%ecx\n\t"
6427 "movl %edi,(%ecx)\n\t"
6428 "leal -8(%ebp),%esp\n\t"
6429 "popl %edi\n\t"
6430 __ASM_CFI(".cfi_same_value %edi\n\t")
6431 "popl %esi\n\t"
6432 __ASM_CFI(".cfi_same_value %esi\n\t")
6433 "popl %ebp\n\t"
6434 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6435 __ASM_CFI(".cfi_same_value %ebp\n\t")
6436 "ret" )
6438 /* same function but returning floating point */
6439 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6441 /* ITypeInfo::Invoke
6443 * Invokes a method, or accesses a property of an object, that implements the
6444 * interface described by the type description.
6446 DWORD
6447 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6448 DWORD res;
6449 int stack_offset;
6451 if (TRACE_ON(ole)) {
6452 int i;
6453 TRACE("Calling %p(",func);
6454 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6455 if (nrargs > 30) TRACE("...");
6456 TRACE(")\n");
6459 switch (callconv) {
6460 case CC_STDCALL:
6461 case CC_CDECL:
6462 res = call_method( func, nrargs, args, &stack_offset );
6463 break;
6464 default:
6465 FIXME("unsupported calling convention %d\n",callconv);
6466 res = -1;
6467 break;
6469 TRACE("returns %08x\n",res);
6470 return res;
6473 #elif defined(__x86_64__)
6475 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6476 __ASM_GLOBAL_FUNC( call_method,
6477 "pushq %rbp\n\t"
6478 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6479 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6480 "movq %rsp,%rbp\n\t"
6481 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6482 "pushq %rsi\n\t"
6483 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6484 "pushq %rdi\n\t"
6485 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6486 "movq %rcx,%rax\n\t"
6487 "movq $4,%rcx\n\t"
6488 "cmp %rcx,%rdx\n\t"
6489 "cmovgq %rdx,%rcx\n\t"
6490 "leaq 0(,%rcx,8),%rdx\n\t"
6491 "subq %rdx,%rsp\n\t"
6492 "andq $~15,%rsp\n\t"
6493 "movq %rsp,%rdi\n\t"
6494 "movq %r8,%rsi\n\t"
6495 "rep; movsq\n\t"
6496 "movq 0(%rsp),%rcx\n\t"
6497 "movq 8(%rsp),%rdx\n\t"
6498 "movq 16(%rsp),%r8\n\t"
6499 "movq 24(%rsp),%r9\n\t"
6500 "movq %rcx,%xmm0\n\t"
6501 "movq %rdx,%xmm1\n\t"
6502 "movq %r8,%xmm2\n\t"
6503 "movq %r9,%xmm3\n\t"
6504 "callq *%rax\n\t"
6505 "leaq -16(%rbp),%rsp\n\t"
6506 "popq %rdi\n\t"
6507 __ASM_CFI(".cfi_same_value %rdi\n\t")
6508 "popq %rsi\n\t"
6509 __ASM_CFI(".cfi_same_value %rsi\n\t")
6510 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6511 "popq %rbp\n\t"
6512 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6513 __ASM_CFI(".cfi_same_value %rbp\n\t")
6514 "ret")
6516 /* same function but returning floating point */
6517 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6519 #endif /* __x86_64__ */
6521 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6523 HRESULT hr = S_OK;
6524 ITypeInfo *tinfo2 = NULL;
6525 TYPEATTR *tattr = NULL;
6527 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6528 if (hr)
6530 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6531 "hr = 0x%08x\n",
6532 tdesc->u.hreftype, hr);
6533 return hr;
6535 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6536 if (hr)
6538 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6539 ITypeInfo_Release(tinfo2);
6540 return hr;
6543 switch (tattr->typekind)
6545 case TKIND_ENUM:
6546 *vt |= VT_I4;
6547 break;
6549 case TKIND_ALIAS:
6550 tdesc = &tattr->tdescAlias;
6551 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6552 break;
6554 case TKIND_INTERFACE:
6555 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6556 *vt |= VT_DISPATCH;
6557 else
6558 *vt |= VT_UNKNOWN;
6559 break;
6561 case TKIND_DISPATCH:
6562 *vt |= VT_DISPATCH;
6563 break;
6565 case TKIND_COCLASS:
6566 *vt |= VT_DISPATCH;
6567 break;
6569 case TKIND_RECORD:
6570 FIXME("TKIND_RECORD unhandled.\n");
6571 hr = E_NOTIMPL;
6572 break;
6574 case TKIND_UNION:
6575 FIXME("TKIND_UNION unhandled.\n");
6576 hr = E_NOTIMPL;
6577 break;
6579 default:
6580 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6581 hr = E_NOTIMPL;
6582 break;
6584 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6585 ITypeInfo_Release(tinfo2);
6586 return hr;
6589 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6591 HRESULT hr = S_OK;
6593 /* enforce only one level of pointer indirection */
6594 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6596 tdesc = tdesc->u.lptdesc;
6598 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6599 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6600 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6601 if ((tdesc->vt == VT_USERDEFINED) ||
6602 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6604 VARTYPE vt_userdefined = 0;
6605 const TYPEDESC *tdesc_userdefined = tdesc;
6606 if (tdesc->vt == VT_PTR)
6608 vt_userdefined = VT_BYREF;
6609 tdesc_userdefined = tdesc->u.lptdesc;
6611 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6612 if ((hr == S_OK) &&
6613 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6614 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6616 *vt |= vt_userdefined;
6617 return S_OK;
6620 *vt = VT_BYREF;
6623 switch (tdesc->vt)
6625 case VT_HRESULT:
6626 *vt |= VT_ERROR;
6627 break;
6628 case VT_USERDEFINED:
6629 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6630 break;
6631 case VT_VOID:
6632 case VT_CARRAY:
6633 case VT_PTR:
6634 case VT_LPSTR:
6635 case VT_LPWSTR:
6636 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6637 hr = DISP_E_BADVARTYPE;
6638 break;
6639 case VT_SAFEARRAY:
6640 *vt |= VT_ARRAY;
6641 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6642 break;
6643 case VT_INT:
6644 *vt |= VT_I4;
6645 break;
6646 case VT_UINT:
6647 *vt |= VT_UI4;
6648 break;
6649 default:
6650 *vt |= tdesc->vt;
6651 break;
6653 return hr;
6656 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6658 ITypeInfo *tinfo2;
6659 TYPEATTR *tattr;
6660 HRESULT hres;
6662 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6663 if(FAILED(hres))
6664 return hres;
6666 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6667 if(FAILED(hres)) {
6668 ITypeInfo_Release(tinfo2);
6669 return hres;
6672 switch(tattr->typekind) {
6673 case TKIND_ALIAS:
6674 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6675 break;
6677 case TKIND_INTERFACE:
6678 case TKIND_DISPATCH:
6679 *guid = tattr->guid;
6680 break;
6682 default:
6683 ERR("Unexpected typekind %d\n", tattr->typekind);
6684 hres = E_UNEXPECTED;
6687 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6688 ITypeInfo_Release(tinfo2);
6689 return hres;
6692 /***********************************************************************
6693 * DispCallFunc (OLEAUT32.@)
6695 * Invokes a function of the specified calling convention, passing the
6696 * specified arguments and returns the result.
6698 * PARAMS
6699 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6700 * oVft [I] The offset in the vtable. See notes.
6701 * cc [I] Calling convention of the function to call.
6702 * vtReturn [I] The return type of the function.
6703 * cActuals [I] Number of parameters.
6704 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6705 * prgpvarg [I] The arguments to pass.
6706 * pvargResult [O] The return value of the function. Can be NULL.
6708 * RETURNS
6709 * Success: S_OK.
6710 * Failure: HRESULT code.
6712 * NOTES
6713 * The HRESULT return value of this function is not affected by the return
6714 * value of the user supplied function, which is returned in pvargResult.
6716 * If pvInstance is NULL then a non-object function is to be called and oVft
6717 * is the address of the function to call.
6719 * The cc parameter can be one of the following values:
6720 *|CC_FASTCALL
6721 *|CC_CDECL
6722 *|CC_PASCAL
6723 *|CC_STDCALL
6724 *|CC_FPFASTCALL
6725 *|CC_SYSCALL
6726 *|CC_MPWCDECL
6727 *|CC_MPWPASCAL
6730 HRESULT WINAPI
6731 DispCallFunc(
6732 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6733 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6735 #ifdef __i386__
6736 int argspos, stack_offset;
6737 void *func;
6738 UINT i;
6739 DWORD *args;
6741 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6742 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6743 pvargResult, V_VT(pvargResult));
6745 if (cc != CC_STDCALL && cc != CC_CDECL)
6747 FIXME("unsupported calling convention %d\n",cc);
6748 return E_INVALIDARG;
6751 /* maximum size for an argument is sizeof(VARIANT) */
6752 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6754 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6755 argspos = 1;
6756 if (pvInstance)
6758 const FARPROC *vtable = *(FARPROC **)pvInstance;
6759 func = vtable[oVft/sizeof(void *)];
6760 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6762 else func = (void *)oVft;
6764 for (i = 0; i < cActuals; i++)
6766 VARIANT *arg = prgpvarg[i];
6768 switch (prgvt[i])
6770 case VT_EMPTY:
6771 break;
6772 case VT_I8:
6773 case VT_UI8:
6774 case VT_R8:
6775 case VT_DATE:
6776 case VT_CY:
6777 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6778 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6779 break;
6780 case VT_DECIMAL:
6781 case VT_VARIANT:
6782 memcpy( &args[argspos], arg, sizeof(*arg) );
6783 argspos += sizeof(*arg) / sizeof(DWORD);
6784 break;
6785 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6786 args[argspos++] = V_BOOL(arg);
6787 break;
6788 default:
6789 args[argspos++] = V_UI4(arg);
6790 break;
6792 TRACE("arg %u: type %d\n",i,prgvt[i]);
6793 dump_Variant(arg);
6796 switch (vtReturn)
6798 case VT_EMPTY:
6799 call_method( func, argspos - 1, args + 1, &stack_offset );
6800 break;
6801 case VT_R4:
6802 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6803 break;
6804 case VT_R8:
6805 case VT_DATE:
6806 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6807 break;
6808 case VT_DECIMAL:
6809 case VT_VARIANT:
6810 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6811 call_method( func, argspos, args, &stack_offset );
6812 break;
6813 case VT_I8:
6814 case VT_UI8:
6815 case VT_CY:
6816 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6817 break;
6818 case VT_HRESULT:
6819 WARN("invalid return type %u\n", vtReturn);
6820 heap_free( args );
6821 return E_INVALIDARG;
6822 default:
6823 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6824 break;
6826 heap_free( args );
6827 if (stack_offset && cc == CC_STDCALL)
6829 WARN( "stack pointer off by %d\n", stack_offset );
6830 return DISP_E_BADCALLEE;
6832 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6833 TRACE("retval: "); dump_Variant(pvargResult);
6834 return S_OK;
6836 #elif defined(__x86_64__)
6837 int argspos;
6838 UINT i;
6839 DWORD_PTR *args;
6840 void *func;
6842 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6843 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6844 pvargResult, V_VT(pvargResult));
6846 if (cc != CC_STDCALL && cc != CC_CDECL)
6848 FIXME("unsupported calling convention %d\n",cc);
6849 return E_INVALIDARG;
6852 /* maximum size for an argument is sizeof(DWORD_PTR) */
6853 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6855 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6856 argspos = 1;
6857 if (pvInstance)
6859 const FARPROC *vtable = *(FARPROC **)pvInstance;
6860 func = vtable[oVft/sizeof(void *)];
6861 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6863 else func = (void *)oVft;
6865 for (i = 0; i < cActuals; i++)
6867 VARIANT *arg = prgpvarg[i];
6869 switch (prgvt[i])
6871 case VT_DECIMAL:
6872 case VT_VARIANT:
6873 args[argspos++] = (ULONG_PTR)arg;
6874 break;
6875 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6876 args[argspos++] = V_BOOL(arg);
6877 break;
6878 default:
6879 args[argspos++] = V_UI8(arg);
6880 break;
6882 TRACE("arg %u: type %d\n",i,prgvt[i]);
6883 dump_Variant(arg);
6886 switch (vtReturn)
6888 case VT_R4:
6889 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6890 break;
6891 case VT_R8:
6892 case VT_DATE:
6893 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6894 break;
6895 case VT_DECIMAL:
6896 case VT_VARIANT:
6897 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6898 call_method( func, argspos, args );
6899 break;
6900 case VT_HRESULT:
6901 WARN("invalid return type %u\n", vtReturn);
6902 heap_free( args );
6903 return E_INVALIDARG;
6904 default:
6905 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6906 break;
6908 heap_free( args );
6909 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6910 TRACE("retval: "); dump_Variant(pvargResult);
6911 return S_OK;
6913 #else
6914 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6915 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6916 return E_NOTIMPL;
6917 #endif
6920 static inline BOOL func_restricted( const FUNCDESC *desc )
6922 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6925 #define INVBUF_ELEMENT_SIZE \
6926 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6927 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6928 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6929 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6930 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6931 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6932 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6933 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6935 static HRESULT WINAPI ITypeInfo_fnInvoke(
6936 ITypeInfo2 *iface,
6937 VOID *pIUnk,
6938 MEMBERID memid,
6939 UINT16 wFlags,
6940 DISPPARAMS *pDispParams,
6941 VARIANT *pVarResult,
6942 EXCEPINFO *pExcepInfo,
6943 UINT *pArgErr)
6945 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6946 int i;
6947 unsigned int var_index;
6948 TYPEKIND type_kind;
6949 HRESULT hres;
6950 const TLBFuncDesc *pFuncInfo;
6951 UINT fdc;
6953 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6954 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6957 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6958 return DISP_E_MEMBERNOTFOUND;
6960 if (!pDispParams)
6962 ERR("NULL pDispParams not allowed\n");
6963 return E_INVALIDARG;
6966 dump_DispParms(pDispParams);
6968 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6970 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6971 pDispParams->cNamedArgs, pDispParams->cArgs);
6972 return E_INVALIDARG;
6975 /* we do this instead of using GetFuncDesc since it will return a fake
6976 * FUNCDESC for dispinterfaces and we want the real function description */
6977 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6978 pFuncInfo = &This->funcdescs[fdc];
6979 if ((memid == pFuncInfo->funcdesc.memid) &&
6980 (wFlags & pFuncInfo->funcdesc.invkind) &&
6981 !func_restricted( &pFuncInfo->funcdesc ))
6982 break;
6985 if (fdc < This->cFuncs) {
6986 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6988 if (TRACE_ON(ole))
6990 TRACE("invoking:\n");
6991 dump_TLBFuncDescOne(pFuncInfo);
6994 switch (func_desc->funckind) {
6995 case FUNC_PUREVIRTUAL:
6996 case FUNC_VIRTUAL: {
6997 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6998 VARIANT varresult;
6999 VARIANT retval; /* pointer for storing byref retvals in */
7000 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7001 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7002 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7003 UINT cNamedArgs = pDispParams->cNamedArgs;
7004 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7005 UINT vargs_converted=0;
7007 hres = S_OK;
7009 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7011 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7013 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7014 hres = DISP_E_PARAMNOTFOUND;
7015 goto func_fail;
7019 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7021 ERR("functions with the vararg attribute do not support named arguments\n");
7022 hres = DISP_E_NONAMEDARGS;
7023 goto func_fail;
7026 for (i = 0; i < func_desc->cParams; i++)
7028 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7029 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7030 if (FAILED(hres))
7031 goto func_fail;
7034 TRACE("changing args\n");
7035 for (i = 0; i < func_desc->cParams; i++)
7037 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7038 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7039 VARIANTARG *src_arg;
7041 if (wParamFlags & PARAMFLAG_FLCID)
7043 VARIANTARG *arg;
7044 arg = prgpvarg[i] = &rgvarg[i];
7045 V_VT(arg) = VT_I4;
7046 V_I4(arg) = This->pTypeLib->lcid;
7047 continue;
7050 src_arg = NULL;
7052 if (cNamedArgs)
7054 USHORT j;
7055 for (j = 0; j < cNamedArgs; j++)
7056 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7058 src_arg = &pDispParams->rgvarg[j];
7059 break;
7063 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7065 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7066 vargs_converted++;
7069 if (wParamFlags & PARAMFLAG_FRETVAL)
7071 /* under most conditions the caller is not allowed to
7072 * pass in a dispparam arg in the index of what would be
7073 * the retval parameter. however, there is an exception
7074 * where the extra parameter is used in an extra
7075 * IDispatch::Invoke below */
7076 if ((i < pDispParams->cArgs) &&
7077 ((func_desc->cParams != 1) || !pVarResult ||
7078 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7080 hres = DISP_E_BADPARAMCOUNT;
7081 break;
7084 /* note: this check is placed so that if the caller passes
7085 * in a VARIANTARG for the retval we just ignore it, like
7086 * native does */
7087 if (i == func_desc->cParams - 1)
7089 VARIANTARG *arg;
7090 arg = prgpvarg[i] = &rgvarg[i];
7091 memset(arg, 0, sizeof(*arg));
7092 V_VT(arg) = rgvt[i];
7093 memset(&retval, 0, sizeof(retval));
7094 V_BYREF(arg) = &retval;
7096 else
7098 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7099 hres = E_UNEXPECTED;
7100 break;
7103 else if (src_arg)
7105 dump_Variant(src_arg);
7107 if(rgvt[i]!=V_VT(src_arg))
7109 if (rgvt[i] == VT_VARIANT)
7110 hres = VariantCopy(&rgvarg[i], src_arg);
7111 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7113 if (rgvt[i] == V_VT(src_arg))
7114 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7115 else
7117 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7118 if (wParamFlags & PARAMFLAG_FIN)
7119 hres = VariantCopy(&missing_arg[i], src_arg);
7120 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7122 V_VT(&rgvarg[i]) = rgvt[i];
7124 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
7126 SAFEARRAY *a;
7127 SAFEARRAYBOUND bound;
7128 VARIANT *v;
7129 LONG j;
7130 bound.lLbound = 0;
7131 bound.cElements = pDispParams->cArgs-i;
7132 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7134 ERR("SafeArrayCreate failed\n");
7135 break;
7137 hres = SafeArrayAccessData(a, (LPVOID)&v);
7138 if (hres != S_OK)
7140 ERR("SafeArrayAccessData failed with %x\n", hres);
7141 SafeArrayDestroy(a);
7142 break;
7144 for (j = 0; j < bound.cElements; j++)
7145 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7146 hres = SafeArrayUnaccessData(a);
7147 if (hres != S_OK)
7149 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7150 SafeArrayDestroy(a);
7151 break;
7153 V_ARRAY(&rgvarg[i]) = a;
7154 V_VT(&rgvarg[i]) = rgvt[i];
7156 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7158 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7159 if (wParamFlags & PARAMFLAG_FIN)
7160 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7161 else
7162 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7163 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7164 V_VT(&rgvarg[i]) = rgvt[i];
7166 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7168 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7169 V_VT(&rgvarg[i]) = rgvt[i];
7171 else
7173 /* FIXME: this doesn't work for VT_BYREF arguments if
7174 * they are not the same type as in the paramdesc */
7175 V_VT(&rgvarg[i]) = V_VT(src_arg);
7176 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7177 V_VT(&rgvarg[i]) = rgvt[i];
7180 if (FAILED(hres))
7182 ERR("failed to convert param %d to %s%s from %s%s\n", i,
7183 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
7184 debugstr_VT(src_arg), debugstr_VF(src_arg));
7185 break;
7187 prgpvarg[i] = &rgvarg[i];
7189 else
7191 prgpvarg[i] = src_arg;
7194 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7195 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7196 && V_UNKNOWN(prgpvarg[i])) {
7197 IUnknown *userdefined_iface;
7198 GUID guid;
7200 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7201 if(FAILED(hres))
7202 break;
7204 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7205 if(FAILED(hres)) {
7206 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7207 break;
7210 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7211 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7214 else if (wParamFlags & PARAMFLAG_FOPT)
7216 VARIANTARG *arg;
7217 arg = prgpvarg[i] = &rgvarg[i];
7218 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7220 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7221 if (FAILED(hres))
7222 break;
7224 else
7226 VARIANTARG *missing_arg;
7227 /* if the function wants a pointer to a variant then
7228 * set that up, otherwise just pass the VT_ERROR in
7229 * the argument by value */
7230 if (rgvt[i] & VT_BYREF)
7232 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7233 V_VT(arg) = VT_VARIANT | VT_BYREF;
7234 V_VARIANTREF(arg) = missing_arg;
7236 else
7237 missing_arg = arg;
7238 V_VT(missing_arg) = VT_ERROR;
7239 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7242 else
7244 hres = DISP_E_BADPARAMCOUNT;
7245 break;
7248 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7250 /* VT_VOID is a special case for return types, so it is not
7251 * handled in the general function */
7252 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7253 V_VT(&varresult) = VT_EMPTY;
7254 else
7256 V_VT(&varresult) = 0;
7257 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7258 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7261 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7262 V_VT(&varresult), func_desc->cParams, rgvt,
7263 prgpvarg, &varresult);
7265 vargs_converted = 0;
7267 for (i = 0; i < func_desc->cParams; i++)
7269 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7270 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7272 if (wParamFlags & PARAMFLAG_FLCID)
7273 continue;
7274 else if (wParamFlags & PARAMFLAG_FRETVAL)
7276 if (TRACE_ON(ole))
7278 TRACE("[retval] value: ");
7279 dump_Variant(prgpvarg[i]);
7282 if (pVarResult)
7284 VariantInit(pVarResult);
7285 /* deref return value */
7286 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7289 VARIANT_ClearInd(prgpvarg[i]);
7291 else if (vargs_converted < pDispParams->cArgs)
7293 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7294 if (wParamFlags & PARAMFLAG_FOUT)
7296 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7298 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7300 if (FAILED(hres))
7302 ERR("failed to convert param %d to vt %d\n", i,
7303 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7304 break;
7308 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7309 func_desc->cParamsOpt < 0 &&
7310 i == func_desc->cParams-1)
7312 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7313 LONG j, ubound;
7314 VARIANT *v;
7315 hres = SafeArrayGetUBound(a, 1, &ubound);
7316 if (hres != S_OK)
7318 ERR("SafeArrayGetUBound failed with %x\n", hres);
7319 break;
7321 hres = SafeArrayAccessData(a, (LPVOID)&v);
7322 if (hres != S_OK)
7324 ERR("SafeArrayAccessData failed with %x\n", hres);
7325 break;
7327 for (j = 0; j <= ubound; j++)
7328 VariantClear(&v[j]);
7329 hres = SafeArrayUnaccessData(a);
7330 if (hres != S_OK)
7332 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7333 break;
7336 VariantClear(&rgvarg[i]);
7337 vargs_converted++;
7339 else if (wParamFlags & PARAMFLAG_FOPT)
7341 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7342 VariantClear(&rgvarg[i]);
7345 VariantClear(&missing_arg[i]);
7348 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7350 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7351 hres = DISP_E_EXCEPTION;
7352 if (pExcepInfo)
7354 IErrorInfo *pErrorInfo;
7355 pExcepInfo->scode = V_ERROR(&varresult);
7356 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7358 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7359 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7360 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7361 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7363 IErrorInfo_Release(pErrorInfo);
7367 if (V_VT(&varresult) != VT_ERROR)
7369 TRACE("varresult value: ");
7370 dump_Variant(&varresult);
7372 if (pVarResult)
7374 VariantClear(pVarResult);
7375 *pVarResult = varresult;
7377 else
7378 VariantClear(&varresult);
7381 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7382 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7383 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7384 (pDispParams->cArgs != 0))
7386 if (V_VT(pVarResult) == VT_DISPATCH)
7388 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7389 /* Note: not VariantClear; we still need the dispatch
7390 * pointer to be valid */
7391 VariantInit(pVarResult);
7392 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7393 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7394 pDispParams, pVarResult, pExcepInfo, pArgErr);
7395 IDispatch_Release(pDispatch);
7397 else
7399 VariantClear(pVarResult);
7400 hres = DISP_E_NOTACOLLECTION;
7404 func_fail:
7405 heap_free(buffer);
7406 break;
7408 case FUNC_DISPATCH: {
7409 IDispatch *disp;
7411 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7412 if (SUCCEEDED(hres)) {
7413 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7414 hres = IDispatch_Invoke(
7415 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7416 pVarResult,pExcepInfo,pArgErr
7418 if (FAILED(hres))
7419 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7420 IDispatch_Release(disp);
7421 } else
7422 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7423 break;
7425 default:
7426 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7427 hres = E_FAIL;
7428 break;
7431 TRACE("-- 0x%08x\n", hres);
7432 return hres;
7434 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7435 VARDESC *var_desc;
7437 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7438 if(FAILED(hres)) return hres;
7440 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7441 dump_VARDESC(var_desc);
7442 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7443 return E_NOTIMPL;
7446 /* not found, look for it in inherited interfaces */
7447 ITypeInfo2_GetTypeKind(iface, &type_kind);
7448 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7449 if(This->impltypes) {
7450 /* recursive search */
7451 ITypeInfo *pTInfo;
7452 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7453 if(SUCCEEDED(hres)){
7454 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7455 ITypeInfo_Release(pTInfo);
7456 return hres;
7458 WARN("Could not search inherited interface!\n");
7461 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7462 return DISP_E_MEMBERNOTFOUND;
7465 /* ITypeInfo::GetDocumentation
7467 * Retrieves the documentation string, the complete Help file name and path,
7468 * and the context ID for the Help topic for a specified type description.
7470 * (Can be tested by the Visual Basic Editor in Word for instance.)
7472 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7473 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7474 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7476 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7477 const TLBFuncDesc *pFDesc;
7478 const TLBVarDesc *pVDesc;
7479 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7480 " HelpContext(%p) HelpFile(%p)\n",
7481 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7482 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7483 if(pBstrName)
7484 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7485 if(pBstrDocString)
7486 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7487 if(pdwHelpContext)
7488 *pdwHelpContext=This->dwHelpContext;
7489 if(pBstrHelpFile)
7490 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7491 return S_OK;
7492 }else {/* for a member */
7493 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7494 if(pFDesc){
7495 if(pBstrName)
7496 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7497 if(pBstrDocString)
7498 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7499 if(pdwHelpContext)
7500 *pdwHelpContext=pFDesc->helpcontext;
7501 if(pBstrHelpFile)
7502 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7503 return S_OK;
7505 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7506 if(pVDesc){
7507 if(pBstrName)
7508 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7509 if(pBstrDocString)
7510 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7511 if(pdwHelpContext)
7512 *pdwHelpContext=pVDesc->HelpContext;
7513 if(pBstrHelpFile)
7514 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7515 return S_OK;
7519 if(This->impltypes &&
7520 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7521 /* recursive search */
7522 ITypeInfo *pTInfo;
7523 HRESULT result;
7524 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7525 if(SUCCEEDED(result)) {
7526 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7527 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7528 ITypeInfo_Release(pTInfo);
7529 return result;
7531 WARN("Could not search inherited interface!\n");
7534 WARN("member %d not found\n", memid);
7535 return TYPE_E_ELEMENTNOTFOUND;
7538 /* ITypeInfo::GetDllEntry
7540 * Retrieves a description or specification of an entry point for a function
7541 * in a DLL.
7543 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7544 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7545 WORD *pwOrdinal)
7547 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7548 const TLBFuncDesc *pFDesc;
7550 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7552 if (pBstrDllName) *pBstrDllName = NULL;
7553 if (pBstrName) *pBstrName = NULL;
7554 if (pwOrdinal) *pwOrdinal = 0;
7556 if (This->typekind != TKIND_MODULE)
7557 return TYPE_E_BADMODULEKIND;
7559 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7560 if(pFDesc){
7561 dump_TypeInfo(This);
7562 if (TRACE_ON(ole))
7563 dump_TLBFuncDescOne(pFDesc);
7565 if (pBstrDllName)
7566 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7568 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7569 if (pBstrName)
7570 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7571 if (pwOrdinal)
7572 *pwOrdinal = -1;
7573 return S_OK;
7575 if (pBstrName)
7576 *pBstrName = NULL;
7577 if (pwOrdinal)
7578 *pwOrdinal = LOWORD(pFDesc->Entry);
7579 return S_OK;
7581 return TYPE_E_ELEMENTNOTFOUND;
7584 /* internal function to make the inherited interfaces' methods appear
7585 * part of the interface */
7586 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7587 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7589 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7590 HRESULT hr;
7592 TRACE("%p, 0x%x\n", iface, *hRefType);
7594 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7596 ITypeInfo *pSubTypeInfo;
7598 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7599 if (FAILED(hr))
7600 return hr;
7602 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7603 hRefType, ppTInfo);
7604 ITypeInfo_Release(pSubTypeInfo);
7605 if (SUCCEEDED(hr))
7606 return hr;
7608 *hRefType -= DISPATCH_HREF_OFFSET;
7610 if (!(*hRefType & DISPATCH_HREF_MASK))
7611 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7612 else
7613 return E_FAIL;
7616 /* ITypeInfo::GetRefTypeInfo
7618 * If a type description references other type descriptions, it retrieves
7619 * the referenced type descriptions.
7621 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7622 ITypeInfo2 *iface,
7623 HREFTYPE hRefType,
7624 ITypeInfo **ppTInfo)
7626 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7627 HRESULT result = E_FAIL;
7629 if(!ppTInfo)
7630 return E_INVALIDARG;
7632 if ((INT)hRefType < 0) {
7633 ITypeInfoImpl *pTypeInfoImpl;
7635 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7636 !(This->typekind == TKIND_INTERFACE ||
7637 This->typekind == TKIND_DISPATCH))
7638 return TYPE_E_ELEMENTNOTFOUND;
7640 /* when we meet a DUAL typeinfo, we must create the alternate
7641 * version of it.
7643 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7645 *pTypeInfoImpl = *This;
7646 pTypeInfoImpl->ref = 0;
7647 list_init(&pTypeInfoImpl->custdata_list);
7649 if (This->typekind == TKIND_INTERFACE)
7650 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7651 else
7652 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7654 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7655 /* the AddRef implicitly adds a reference to the parent typelib, which
7656 * stops the copied data from being destroyed until the new typeinfo's
7657 * refcount goes to zero, but we need to signal to the new instance to
7658 * not free its data structures when it is destroyed */
7659 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7661 ITypeInfo_AddRef(*ppTInfo);
7663 result = S_OK;
7664 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7665 (This->typekind == TKIND_DISPATCH))
7667 HREFTYPE href_dispatch = hRefType;
7668 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7669 } else {
7670 TLBRefType *ref_type;
7671 ITypeLib *pTLib = NULL;
7672 UINT i;
7674 if(!(hRefType & 0x1)){
7675 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7677 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7679 result = S_OK;
7680 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7681 ITypeInfo_AddRef(*ppTInfo);
7682 goto end;
7687 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7689 if(ref_type->reference == (hRefType & (~0x3)))
7690 break;
7692 if(&ref_type->entry == &This->pTypeLib->ref_list)
7694 FIXME("Can't find pRefType for ref %x\n", hRefType);
7695 goto end;
7698 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7699 UINT Index;
7700 TRACE("internal reference\n");
7701 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7702 } else {
7703 if(ref_type->pImpTLInfo->pImpTypeLib) {
7704 TRACE("typeinfo in imported typelib that is already loaded\n");
7705 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7706 ITypeLib_AddRef(pTLib);
7707 result = S_OK;
7708 } else {
7709 BSTR libnam;
7711 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7713 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7714 ref_type->pImpTLInfo->wVersionMajor,
7715 ref_type->pImpTLInfo->wVersionMinor,
7716 This->pTypeLib->syskind,
7717 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7718 if(FAILED(result))
7719 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7721 result = LoadTypeLib(libnam, &pTLib);
7722 SysFreeString(libnam);
7724 if(SUCCEEDED(result)) {
7725 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7726 ITypeLib_AddRef(pTLib);
7730 if(SUCCEEDED(result)) {
7731 if(ref_type->index == TLB_REF_USE_GUID)
7732 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7733 else
7734 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7736 if (pTLib != NULL)
7737 ITypeLib_Release(pTLib);
7740 end:
7741 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7742 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7743 return result;
7746 /* ITypeInfo::AddressOfMember
7748 * Retrieves the addresses of static functions or variables, such as those
7749 * defined in a DLL.
7751 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7752 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7754 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7755 HRESULT hr;
7756 BSTR dll, entry;
7757 WORD ordinal;
7758 HMODULE module;
7760 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7762 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7763 if (FAILED(hr))
7764 return hr;
7766 module = LoadLibraryW(dll);
7767 if (!module)
7769 ERR("couldn't load %s\n", debugstr_w(dll));
7770 SysFreeString(dll);
7771 SysFreeString(entry);
7772 return STG_E_FILENOTFOUND;
7774 /* FIXME: store library somewhere where we can free it */
7776 if (entry)
7778 LPSTR entryA;
7779 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7780 entryA = heap_alloc(len);
7781 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7783 *ppv = GetProcAddress(module, entryA);
7784 if (!*ppv)
7785 ERR("function not found %s\n", debugstr_a(entryA));
7787 heap_free(entryA);
7789 else
7791 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7792 if (!*ppv)
7793 ERR("function not found %d\n", ordinal);
7796 SysFreeString(dll);
7797 SysFreeString(entry);
7799 if (!*ppv)
7800 return TYPE_E_DLLFUNCTIONNOTFOUND;
7802 return S_OK;
7805 /* ITypeInfo::CreateInstance
7807 * Creates a new instance of a type that describes a component object class
7808 * (coclass).
7810 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7811 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7813 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7814 HRESULT hr;
7815 TYPEATTR *pTA;
7817 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7819 *ppvObj = NULL;
7821 if(pOuterUnk)
7823 WARN("Not able to aggregate\n");
7824 return CLASS_E_NOAGGREGATION;
7827 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7828 if(FAILED(hr)) return hr;
7830 if(pTA->typekind != TKIND_COCLASS)
7832 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7833 hr = E_INVALIDARG;
7834 goto end;
7837 hr = S_FALSE;
7838 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7840 IUnknown *pUnk;
7841 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7842 TRACE("GetActiveObject rets %08x\n", hr);
7843 if(hr == S_OK)
7845 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7846 IUnknown_Release(pUnk);
7850 if(hr != S_OK)
7851 hr = CoCreateInstance(&pTA->guid, NULL,
7852 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7853 riid, ppvObj);
7855 end:
7856 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7857 return hr;
7860 /* ITypeInfo::GetMops
7862 * Retrieves marshalling information.
7864 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7865 BSTR *pBstrMops)
7867 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7868 FIXME("(%p %d) stub!\n", This, memid);
7869 *pBstrMops = NULL;
7870 return S_OK;
7873 /* ITypeInfo::GetContainingTypeLib
7875 * Retrieves the containing type library and the index of the type description
7876 * within that type library.
7878 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7879 ITypeLib * *ppTLib, UINT *pIndex)
7881 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7883 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7884 if (pIndex) {
7885 *pIndex=This->index;
7886 TRACE("returning pIndex=%d\n", *pIndex);
7889 if (ppTLib) {
7890 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7891 ITypeLib_AddRef(*ppTLib);
7892 TRACE("returning ppTLib=%p\n", *ppTLib);
7895 return S_OK;
7898 /* ITypeInfo::ReleaseTypeAttr
7900 * Releases a TYPEATTR previously returned by Get
7903 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7904 TYPEATTR* pTypeAttr)
7906 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7907 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7908 heap_free(pTypeAttr);
7911 /* ITypeInfo::ReleaseFuncDesc
7913 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7915 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7916 ITypeInfo2 *iface,
7917 FUNCDESC *pFuncDesc)
7919 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7920 SHORT i;
7922 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7924 for (i = 0; i < pFuncDesc->cParams; i++)
7925 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7926 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7928 SysFreeString((BSTR)pFuncDesc);
7931 /* ITypeInfo::ReleaseVarDesc
7933 * Releases a VARDESC previously returned by GetVarDesc.
7935 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7936 VARDESC *pVarDesc)
7938 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7939 TRACE("(%p)->(%p)\n", This, pVarDesc);
7941 TLB_FreeVarDesc(pVarDesc);
7944 /* ITypeInfo2::GetTypeKind
7946 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7949 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7950 TYPEKIND *pTypeKind)
7952 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7953 *pTypeKind=This->typekind;
7954 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7955 return S_OK;
7958 /* ITypeInfo2::GetTypeFlags
7960 * Returns the type flags without any allocations. This returns a DWORD type
7961 * flag, which expands the type flags without growing the TYPEATTR (type
7962 * attribute).
7965 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7967 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7968 *pTypeFlags=This->wTypeFlags;
7969 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7970 return S_OK;
7973 /* ITypeInfo2::GetFuncIndexOfMemId
7974 * Binds to a specific member based on a known DISPID, where the member name
7975 * is not known (for example, when binding to a default member).
7978 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7979 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7981 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7982 UINT fdc;
7983 HRESULT result;
7985 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7986 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7987 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7988 break;
7990 if(fdc < This->cFuncs) {
7991 *pFuncIndex = fdc;
7992 result = S_OK;
7993 } else
7994 result = TYPE_E_ELEMENTNOTFOUND;
7996 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7997 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7998 return result;
8001 /* TypeInfo2::GetVarIndexOfMemId
8003 * Binds to a specific member based on a known DISPID, where the member name
8004 * is not known (for example, when binding to a default member).
8007 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8008 MEMBERID memid, UINT *pVarIndex)
8010 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8011 TLBVarDesc *pVarInfo;
8013 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8015 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8016 if(!pVarInfo)
8017 return TYPE_E_ELEMENTNOTFOUND;
8019 *pVarIndex = (pVarInfo - This->vardescs);
8021 return S_OK;
8024 /* ITypeInfo2::GetCustData
8026 * Gets the custom data
8028 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8029 ITypeInfo2 * iface,
8030 REFGUID guid,
8031 VARIANT *pVarVal)
8033 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8034 TLBCustData *pCData;
8036 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8038 if(!guid || !pVarVal)
8039 return E_INVALIDARG;
8041 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8043 VariantInit( pVarVal);
8044 if (pCData)
8045 VariantCopy( pVarVal, &pCData->data);
8046 else
8047 VariantClear( pVarVal );
8048 return S_OK;
8051 /* ITypeInfo2::GetFuncCustData
8053 * Gets the custom data
8055 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8056 ITypeInfo2 * iface,
8057 UINT index,
8058 REFGUID guid,
8059 VARIANT *pVarVal)
8061 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8062 TLBCustData *pCData;
8063 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8065 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8067 if(index >= This->cFuncs)
8068 return TYPE_E_ELEMENTNOTFOUND;
8070 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8071 if(!pCData)
8072 return TYPE_E_ELEMENTNOTFOUND;
8074 VariantInit(pVarVal);
8075 VariantCopy(pVarVal, &pCData->data);
8077 return S_OK;
8080 /* ITypeInfo2::GetParamCustData
8082 * Gets the custom data
8084 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8085 ITypeInfo2 * iface,
8086 UINT indexFunc,
8087 UINT indexParam,
8088 REFGUID guid,
8089 VARIANT *pVarVal)
8091 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8092 TLBCustData *pCData;
8093 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8095 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8096 debugstr_guid(guid), pVarVal);
8098 if(indexFunc >= This->cFuncs)
8099 return TYPE_E_ELEMENTNOTFOUND;
8101 if(indexParam >= pFDesc->funcdesc.cParams)
8102 return TYPE_E_ELEMENTNOTFOUND;
8104 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8105 if(!pCData)
8106 return TYPE_E_ELEMENTNOTFOUND;
8108 VariantInit(pVarVal);
8109 VariantCopy(pVarVal, &pCData->data);
8111 return S_OK;
8114 /* ITypeInfo2::GetVarCustData
8116 * Gets the custom data
8118 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8119 ITypeInfo2 * iface,
8120 UINT index,
8121 REFGUID guid,
8122 VARIANT *pVarVal)
8124 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8125 TLBCustData *pCData;
8126 TLBVarDesc *pVDesc = &This->vardescs[index];
8128 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8130 if(index >= This->cVars)
8131 return TYPE_E_ELEMENTNOTFOUND;
8133 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8134 if(!pCData)
8135 return TYPE_E_ELEMENTNOTFOUND;
8137 VariantInit(pVarVal);
8138 VariantCopy(pVarVal, &pCData->data);
8140 return S_OK;
8143 /* ITypeInfo2::GetImplCustData
8145 * Gets the custom data
8147 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8148 ITypeInfo2 * iface,
8149 UINT index,
8150 REFGUID guid,
8151 VARIANT *pVarVal)
8153 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8154 TLBCustData *pCData;
8155 TLBImplType *pRDesc = &This->impltypes[index];
8157 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8159 if(index >= This->cImplTypes)
8160 return TYPE_E_ELEMENTNOTFOUND;
8162 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8163 if(!pCData)
8164 return TYPE_E_ELEMENTNOTFOUND;
8166 VariantInit(pVarVal);
8167 VariantCopy(pVarVal, &pCData->data);
8169 return S_OK;
8172 /* ITypeInfo2::GetDocumentation2
8174 * Retrieves the documentation string, the complete Help file name and path,
8175 * the localization context to use, and the context ID for the library Help
8176 * topic in the Help file.
8179 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8180 ITypeInfo2 * iface,
8181 MEMBERID memid,
8182 LCID lcid,
8183 BSTR *pbstrHelpString,
8184 DWORD *pdwHelpStringContext,
8185 BSTR *pbstrHelpStringDll)
8187 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8188 const TLBFuncDesc *pFDesc;
8189 const TLBVarDesc *pVDesc;
8190 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8191 "HelpStringContext(%p) HelpStringDll(%p)\n",
8192 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8193 pbstrHelpStringDll );
8194 /* the help string should be obtained from the helpstringdll,
8195 * using the _DLLGetDocumentation function, based on the supplied
8196 * lcid. Nice to do sometime...
8198 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8199 if(pbstrHelpString)
8200 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8201 if(pdwHelpStringContext)
8202 *pdwHelpStringContext=This->dwHelpStringContext;
8203 if(pbstrHelpStringDll)
8204 *pbstrHelpStringDll=
8205 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8206 return S_OK;
8207 }else {/* for a member */
8208 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
8209 if(pFDesc){
8210 if(pbstrHelpString)
8211 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8212 if(pdwHelpStringContext)
8213 *pdwHelpStringContext=pFDesc->HelpStringContext;
8214 if(pbstrHelpStringDll)
8215 *pbstrHelpStringDll=
8216 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8217 return S_OK;
8219 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8220 if(pVDesc){
8221 if(pbstrHelpString)
8222 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8223 if(pdwHelpStringContext)
8224 *pdwHelpStringContext=pVDesc->HelpStringContext;
8225 if(pbstrHelpStringDll)
8226 *pbstrHelpStringDll=
8227 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8228 return S_OK;
8231 return TYPE_E_ELEMENTNOTFOUND;
8234 /* ITypeInfo2::GetAllCustData
8236 * Gets all custom data items for the Type info.
8239 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8240 ITypeInfo2 * iface,
8241 CUSTDATA *pCustData)
8243 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8245 TRACE("%p %p\n", This, pCustData);
8247 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8250 /* ITypeInfo2::GetAllFuncCustData
8252 * Gets all custom data items for the specified Function
8255 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8256 ITypeInfo2 * iface,
8257 UINT index,
8258 CUSTDATA *pCustData)
8260 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8261 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8263 TRACE("%p %u %p\n", This, index, pCustData);
8265 if(index >= This->cFuncs)
8266 return TYPE_E_ELEMENTNOTFOUND;
8268 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8271 /* ITypeInfo2::GetAllParamCustData
8273 * Gets all custom data items for the Functions
8276 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8277 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8279 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8280 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8282 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8284 if(indexFunc >= This->cFuncs)
8285 return TYPE_E_ELEMENTNOTFOUND;
8287 if(indexParam >= pFDesc->funcdesc.cParams)
8288 return TYPE_E_ELEMENTNOTFOUND;
8290 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8293 /* ITypeInfo2::GetAllVarCustData
8295 * Gets all custom data items for the specified Variable
8298 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8299 UINT index, CUSTDATA *pCustData)
8301 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8302 TLBVarDesc * pVDesc = &This->vardescs[index];
8304 TRACE("%p %u %p\n", This, index, pCustData);
8306 if(index >= This->cVars)
8307 return TYPE_E_ELEMENTNOTFOUND;
8309 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8312 /* ITypeInfo2::GetAllImplCustData
8314 * Gets all custom data items for the specified implementation type
8317 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8318 ITypeInfo2 * iface,
8319 UINT index,
8320 CUSTDATA *pCustData)
8322 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8323 TLBImplType *pRDesc = &This->impltypes[index];
8325 TRACE("%p %u %p\n", This, index, pCustData);
8327 if(index >= This->cImplTypes)
8328 return TYPE_E_ELEMENTNOTFOUND;
8330 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8333 static const ITypeInfo2Vtbl tinfvt =
8336 ITypeInfo_fnQueryInterface,
8337 ITypeInfo_fnAddRef,
8338 ITypeInfo_fnRelease,
8340 ITypeInfo_fnGetTypeAttr,
8341 ITypeInfo_fnGetTypeComp,
8342 ITypeInfo_fnGetFuncDesc,
8343 ITypeInfo_fnGetVarDesc,
8344 ITypeInfo_fnGetNames,
8345 ITypeInfo_fnGetRefTypeOfImplType,
8346 ITypeInfo_fnGetImplTypeFlags,
8347 ITypeInfo_fnGetIDsOfNames,
8348 ITypeInfo_fnInvoke,
8349 ITypeInfo_fnGetDocumentation,
8350 ITypeInfo_fnGetDllEntry,
8351 ITypeInfo_fnGetRefTypeInfo,
8352 ITypeInfo_fnAddressOfMember,
8353 ITypeInfo_fnCreateInstance,
8354 ITypeInfo_fnGetMops,
8355 ITypeInfo_fnGetContainingTypeLib,
8356 ITypeInfo_fnReleaseTypeAttr,
8357 ITypeInfo_fnReleaseFuncDesc,
8358 ITypeInfo_fnReleaseVarDesc,
8360 ITypeInfo2_fnGetTypeKind,
8361 ITypeInfo2_fnGetTypeFlags,
8362 ITypeInfo2_fnGetFuncIndexOfMemId,
8363 ITypeInfo2_fnGetVarIndexOfMemId,
8364 ITypeInfo2_fnGetCustData,
8365 ITypeInfo2_fnGetFuncCustData,
8366 ITypeInfo2_fnGetParamCustData,
8367 ITypeInfo2_fnGetVarCustData,
8368 ITypeInfo2_fnGetImplTypeCustData,
8369 ITypeInfo2_fnGetDocumentation2,
8370 ITypeInfo2_fnGetAllCustData,
8371 ITypeInfo2_fnGetAllFuncCustData,
8372 ITypeInfo2_fnGetAllParamCustData,
8373 ITypeInfo2_fnGetAllVarCustData,
8374 ITypeInfo2_fnGetAllImplTypeCustData,
8377 /******************************************************************************
8378 * CreateDispTypeInfo [OLEAUT32.31]
8380 * Build type information for an object so it can be called through an
8381 * IDispatch interface.
8383 * RETURNS
8384 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8385 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8387 * NOTES
8388 * This call allows an objects methods to be accessed through IDispatch, by
8389 * building an ITypeInfo object that IDispatch can use to call through.
8391 HRESULT WINAPI CreateDispTypeInfo(
8392 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8393 LCID lcid, /* [I] Locale Id */
8394 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8396 ITypeInfoImpl *pTIClass, *pTIIface;
8397 ITypeLibImpl *pTypeLibImpl;
8398 unsigned int param, func;
8399 TLBFuncDesc *pFuncDesc;
8400 TLBRefType *ref;
8402 TRACE("\n");
8403 pTypeLibImpl = TypeLibImpl_Constructor();
8404 if (!pTypeLibImpl) return E_FAIL;
8406 pTypeLibImpl->TypeInfoCount = 2;
8407 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8409 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8410 pTIIface->pTypeLib = pTypeLibImpl;
8411 pTIIface->index = 0;
8412 pTIIface->Name = NULL;
8413 pTIIface->dwHelpContext = -1;
8414 pTIIface->guid = NULL;
8415 pTIIface->lcid = lcid;
8416 pTIIface->typekind = TKIND_INTERFACE;
8417 pTIIface->wMajorVerNum = 0;
8418 pTIIface->wMinorVerNum = 0;
8419 pTIIface->cbAlignment = 2;
8420 pTIIface->cbSizeInstance = -1;
8421 pTIIface->cbSizeVft = -1;
8422 pTIIface->cFuncs = 0;
8423 pTIIface->cImplTypes = 0;
8424 pTIIface->cVars = 0;
8425 pTIIface->wTypeFlags = 0;
8426 pTIIface->hreftype = 0;
8428 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8429 pFuncDesc = pTIIface->funcdescs;
8430 for(func = 0; func < pidata->cMembers; func++) {
8431 METHODDATA *md = pidata->pmethdata + func;
8432 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8433 pFuncDesc->funcdesc.memid = md->dispid;
8434 pFuncDesc->funcdesc.lprgscode = NULL;
8435 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8436 pFuncDesc->funcdesc.invkind = md->wFlags;
8437 pFuncDesc->funcdesc.callconv = md->cc;
8438 pFuncDesc->funcdesc.cParams = md->cArgs;
8439 pFuncDesc->funcdesc.cParamsOpt = 0;
8440 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8441 pFuncDesc->funcdesc.cScodes = 0;
8442 pFuncDesc->funcdesc.wFuncFlags = 0;
8443 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8444 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8445 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8446 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8447 md->cArgs * sizeof(ELEMDESC));
8448 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8449 for(param = 0; param < md->cArgs; param++) {
8450 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8451 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8453 pFuncDesc->helpcontext = 0;
8454 pFuncDesc->HelpStringContext = 0;
8455 pFuncDesc->HelpString = NULL;
8456 pFuncDesc->Entry = NULL;
8457 list_init(&pFuncDesc->custdata_list);
8458 pTIIface->cFuncs++;
8459 ++pFuncDesc;
8462 dump_TypeInfo(pTIIface);
8464 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8465 pTIClass->pTypeLib = pTypeLibImpl;
8466 pTIClass->index = 1;
8467 pTIClass->Name = NULL;
8468 pTIClass->dwHelpContext = -1;
8469 pTIClass->guid = NULL;
8470 pTIClass->lcid = lcid;
8471 pTIClass->typekind = TKIND_COCLASS;
8472 pTIClass->wMajorVerNum = 0;
8473 pTIClass->wMinorVerNum = 0;
8474 pTIClass->cbAlignment = 2;
8475 pTIClass->cbSizeInstance = -1;
8476 pTIClass->cbSizeVft = -1;
8477 pTIClass->cFuncs = 0;
8478 pTIClass->cImplTypes = 1;
8479 pTIClass->cVars = 0;
8480 pTIClass->wTypeFlags = 0;
8481 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8483 pTIClass->impltypes = TLBImplType_Alloc(1);
8485 ref = heap_alloc_zero(sizeof(*ref));
8486 ref->pImpTLInfo = TLB_REF_INTERNAL;
8487 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8489 dump_TypeInfo(pTIClass);
8491 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8493 ITypeInfo_AddRef(*pptinfo);
8494 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8496 return S_OK;
8500 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8502 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8504 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8507 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8509 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8511 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8514 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8516 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8518 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8521 static HRESULT WINAPI ITypeComp_fnBind(
8522 ITypeComp * iface,
8523 OLECHAR * szName,
8524 ULONG lHash,
8525 WORD wFlags,
8526 ITypeInfo ** ppTInfo,
8527 DESCKIND * pDescKind,
8528 BINDPTR * pBindPtr)
8530 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8531 const TLBFuncDesc *pFDesc;
8532 const TLBVarDesc *pVDesc;
8533 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8534 UINT fdc;
8536 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8538 *pDescKind = DESCKIND_NONE;
8539 pBindPtr->lpfuncdesc = NULL;
8540 *ppTInfo = NULL;
8542 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8543 pFDesc = &This->funcdescs[fdc];
8544 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8545 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8546 break;
8547 else
8548 /* name found, but wrong flags */
8549 hr = TYPE_E_TYPEMISMATCH;
8553 if (fdc < This->cFuncs)
8555 HRESULT hr = TLB_AllocAndInitFuncDesc(
8556 &pFDesc->funcdesc,
8557 &pBindPtr->lpfuncdesc,
8558 This->typekind == TKIND_DISPATCH);
8559 if (FAILED(hr))
8560 return hr;
8561 *pDescKind = DESCKIND_FUNCDESC;
8562 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8563 ITypeInfo_AddRef(*ppTInfo);
8564 return S_OK;
8565 } else {
8566 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8567 if(pVDesc){
8568 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8569 if (FAILED(hr))
8570 return hr;
8571 *pDescKind = DESCKIND_VARDESC;
8572 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8573 ITypeInfo_AddRef(*ppTInfo);
8574 return S_OK;
8578 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8579 /* recursive search */
8580 ITypeInfo *pTInfo;
8581 ITypeComp *pTComp;
8582 HRESULT hr;
8583 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8584 if (SUCCEEDED(hr))
8586 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8587 ITypeInfo_Release(pTInfo);
8589 if (SUCCEEDED(hr))
8591 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8592 ITypeComp_Release(pTComp);
8593 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8594 This->typekind == TKIND_DISPATCH)
8596 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8597 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8598 SysFreeString((BSTR)tmp);
8600 return hr;
8602 WARN("Could not search inherited interface!\n");
8604 if (hr == DISP_E_MEMBERNOTFOUND)
8605 hr = S_OK;
8606 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8607 return hr;
8610 static HRESULT WINAPI ITypeComp_fnBindType(
8611 ITypeComp * iface,
8612 OLECHAR * szName,
8613 ULONG lHash,
8614 ITypeInfo ** ppTInfo,
8615 ITypeComp ** ppTComp)
8617 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8619 /* strange behaviour (does nothing) but like the
8620 * original */
8622 if (!ppTInfo || !ppTComp)
8623 return E_POINTER;
8625 *ppTInfo = NULL;
8626 *ppTComp = NULL;
8628 return S_OK;
8631 static const ITypeCompVtbl tcompvt =
8634 ITypeComp_fnQueryInterface,
8635 ITypeComp_fnAddRef,
8636 ITypeComp_fnRelease,
8638 ITypeComp_fnBind,
8639 ITypeComp_fnBindType
8642 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8643 ICreateTypeLib2** ppctlib)
8645 ITypeLibImpl *This;
8646 HRESULT hres;
8648 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8650 if (!szFile) return E_INVALIDARG;
8652 This = TypeLibImpl_Constructor();
8653 if (!This)
8654 return E_OUTOFMEMORY;
8656 This->lcid = GetSystemDefaultLCID();
8657 This->syskind = syskind;
8658 This->ptr_size = get_ptr_size(syskind);
8660 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8661 if (!This->path) {
8662 ITypeLib2_Release(&This->ITypeLib2_iface);
8663 return E_OUTOFMEMORY;
8665 lstrcpyW(This->path, szFile);
8667 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8668 ITypeLib2_Release(&This->ITypeLib2_iface);
8669 return hres;
8672 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8673 REFIID riid, void **object)
8675 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8677 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8680 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8682 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8684 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8687 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8689 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8691 return ITypeLib2_Release(&This->ITypeLib2_iface);
8694 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8695 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8697 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8698 ITypeInfoImpl *info;
8699 HRESULT hres;
8701 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8703 if (!ctinfo || !name)
8704 return E_INVALIDARG;
8706 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8707 if (info)
8708 return TYPE_E_NAMECONFLICT;
8710 if (This->typeinfos)
8711 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8712 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8713 else
8714 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8716 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8718 info->pTypeLib = This;
8719 info->Name = TLB_append_str(&This->name_list, name);
8720 info->index = This->TypeInfoCount;
8721 info->typekind = kind;
8722 info->cbAlignment = 4;
8724 switch(info->typekind) {
8725 case TKIND_ENUM:
8726 case TKIND_INTERFACE:
8727 case TKIND_DISPATCH:
8728 case TKIND_COCLASS:
8729 info->cbSizeInstance = This->ptr_size;
8730 break;
8731 case TKIND_RECORD:
8732 case TKIND_UNION:
8733 info->cbSizeInstance = 0;
8734 break;
8735 case TKIND_MODULE:
8736 info->cbSizeInstance = 2;
8737 break;
8738 case TKIND_ALIAS:
8739 info->cbSizeInstance = -0x75;
8740 break;
8741 default:
8742 FIXME("unrecognized typekind %d\n", info->typekind);
8743 info->cbSizeInstance = 0xdeadbeef;
8744 break;
8747 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8748 &IID_ICreateTypeInfo, (void **)ctinfo);
8749 if (FAILED(hres)) {
8750 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8751 return hres;
8754 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8756 ++This->TypeInfoCount;
8758 return S_OK;
8761 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8762 LPOLESTR name)
8764 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8766 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8768 if (!name)
8769 return E_INVALIDARG;
8771 This->Name = TLB_append_str(&This->name_list, name);
8773 return S_OK;
8776 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8777 WORD majorVerNum, WORD minorVerNum)
8779 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8781 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8783 This->ver_major = majorVerNum;
8784 This->ver_minor = minorVerNum;
8786 return S_OK;
8789 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8790 REFGUID guid)
8792 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8794 TRACE("%p %s\n", This, debugstr_guid(guid));
8796 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8798 return S_OK;
8801 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8802 LPOLESTR doc)
8804 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8806 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8808 if (!doc)
8809 return E_INVALIDARG;
8811 This->DocString = TLB_append_str(&This->string_list, doc);
8813 return S_OK;
8816 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8817 LPOLESTR helpFileName)
8819 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8821 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8823 if (!helpFileName)
8824 return E_INVALIDARG;
8826 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8828 return S_OK;
8831 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8832 DWORD helpContext)
8834 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8836 TRACE("%p %d\n", This, helpContext);
8838 This->dwHelpContext = helpContext;
8840 return S_OK;
8843 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8844 LCID lcid)
8846 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8848 TRACE("%p %x\n", This, lcid);
8850 This->set_lcid = lcid;
8852 return S_OK;
8855 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8856 UINT libFlags)
8858 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8860 TRACE("%p %x\n", This, libFlags);
8862 This->libflags = libFlags;
8864 return S_OK;
8867 typedef struct tagWMSFT_SegContents {
8868 DWORD len;
8869 void *data;
8870 } WMSFT_SegContents;
8872 typedef struct tagWMSFT_TLBFile {
8873 MSFT_Header header;
8874 WMSFT_SegContents typeinfo_seg;
8875 WMSFT_SegContents impfile_seg;
8876 WMSFT_SegContents impinfo_seg;
8877 WMSFT_SegContents ref_seg;
8878 WMSFT_SegContents guidhash_seg;
8879 WMSFT_SegContents guid_seg;
8880 WMSFT_SegContents namehash_seg;
8881 WMSFT_SegContents name_seg;
8882 WMSFT_SegContents string_seg;
8883 WMSFT_SegContents typdesc_seg;
8884 WMSFT_SegContents arraydesc_seg;
8885 WMSFT_SegContents custdata_seg;
8886 WMSFT_SegContents cdguids_seg;
8887 MSFT_SegDir segdir;
8888 WMSFT_SegContents aux_seg;
8889 } WMSFT_TLBFile;
8891 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8892 WMSFT_TLBFile *file)
8894 TLBString *str;
8895 UINT last_offs;
8896 char *data;
8898 file->string_seg.len = 0;
8899 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8900 int size;
8902 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8903 if (size == 0)
8904 return E_UNEXPECTED;
8906 size += sizeof(INT16);
8907 if (size % 4)
8908 size = (size + 4) & ~0x3;
8909 if (size < 8)
8910 size = 8;
8912 file->string_seg.len += size;
8914 /* temporarily use str->offset to store the length of the aligned,
8915 * converted string */
8916 str->offset = size;
8919 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8921 last_offs = 0;
8922 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8923 int size;
8925 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8926 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8927 if (size == 0) {
8928 heap_free(file->string_seg.data);
8929 return E_UNEXPECTED;
8932 *((INT16*)data) = size;
8934 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8936 size = str->offset;
8937 data += size;
8938 str->offset = last_offs;
8939 last_offs += size;
8942 return S_OK;
8945 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8946 WMSFT_TLBFile *file)
8948 TLBString *str;
8949 UINT last_offs;
8950 char *data;
8951 MSFT_NameIntro *last_intro = NULL;
8953 file->header.nametablecount = 0;
8954 file->header.nametablechars = 0;
8956 file->name_seg.len = 0;
8957 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8958 int size;
8960 size = strlenW(str->str);
8961 file->header.nametablechars += size;
8962 file->header.nametablecount++;
8964 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8965 if (size == 0)
8966 return E_UNEXPECTED;
8968 size += sizeof(MSFT_NameIntro);
8969 if (size % 4)
8970 size = (size + 4) & ~0x3;
8971 if (size < 8)
8972 size = 8;
8974 file->name_seg.len += size;
8976 /* temporarily use str->offset to store the length of the aligned,
8977 * converted string */
8978 str->offset = size;
8981 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8982 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8984 last_offs = 0;
8985 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8986 int size, hash;
8987 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8989 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8990 data + sizeof(MSFT_NameIntro),
8991 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8992 if (size == 0) {
8993 heap_free(file->name_seg.data);
8994 return E_UNEXPECTED;
8996 data[sizeof(MSFT_NameIntro) + size] = '\0';
8998 intro->hreftype = -1; /* TODO? */
8999 intro->namelen = size & 0xFF;
9000 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9001 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9002 intro->namelen |= hash << 16;
9003 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9004 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9006 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9007 str->offset - size - sizeof(MSFT_NameIntro));
9009 /* update str->offset to actual value to use in other
9010 * compilation functions that require positions within
9011 * the string table */
9012 last_intro = intro;
9013 size = str->offset;
9014 data += size;
9015 str->offset = last_offs;
9016 last_offs += size;
9019 if(last_intro)
9020 last_intro->hreftype = 0; /* last one is 0? */
9022 return S_OK;
9025 static inline int hash_guid(GUID *guid)
9027 int i, hash = 0;
9029 for (i = 0; i < 8; i ++)
9030 hash ^= ((const short *)guid)[i];
9032 return hash & 0x1f;
9035 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9037 TLBGuid *guid;
9038 MSFT_GuidEntry *entry;
9039 DWORD offs;
9040 int hash_key, *guidhashtab;
9042 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9043 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9045 entry = file->guid_seg.data;
9046 offs = 0;
9047 guidhashtab = file->guidhash_seg.data;
9048 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9049 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9050 entry->hreftype = guid->hreftype;
9052 hash_key = hash_guid(&guid->guid);
9053 entry->next_hash = guidhashtab[hash_key];
9054 guidhashtab[hash_key] = offs;
9056 guid->offset = offs;
9057 offs += sizeof(MSFT_GuidEntry);
9058 ++entry;
9061 return S_OK;
9064 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9066 VARIANT v = *value;
9067 VARTYPE arg_type = V_VT(value);
9068 int mask = 0;
9069 HRESULT hres;
9070 DWORD ret = file->custdata_seg.len;
9072 if(arg_type == VT_INT)
9073 arg_type = VT_I4;
9074 if(arg_type == VT_UINT)
9075 arg_type = VT_UI4;
9077 v = *value;
9078 if(V_VT(value) != arg_type) {
9079 hres = VariantChangeType(&v, value, 0, arg_type);
9080 if(FAILED(hres)){
9081 ERR("VariantChangeType failed: %08x\n", hres);
9082 return -1;
9086 /* Check if default value can be stored in-place */
9087 switch(arg_type){
9088 case VT_I4:
9089 case VT_UI4:
9090 mask = 0x3ffffff;
9091 if(V_UI4(&v) > 0x3ffffff)
9092 break;
9093 /* fall through */
9094 case VT_I1:
9095 case VT_UI1:
9096 case VT_BOOL:
9097 if(!mask)
9098 mask = 0xff;
9099 /* fall through */
9100 case VT_I2:
9101 case VT_UI2:
9102 if(!mask)
9103 mask = 0xffff;
9104 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9107 /* have to allocate space in custdata_seg */
9108 switch(arg_type) {
9109 case VT_I4:
9110 case VT_R4:
9111 case VT_UI4:
9112 case VT_INT:
9113 case VT_UINT:
9114 case VT_HRESULT:
9115 case VT_PTR: {
9116 /* Construct the data to be allocated */
9117 int *data;
9119 if(file->custdata_seg.data){
9120 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9121 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9122 file->custdata_seg.len += sizeof(int) * 2;
9123 }else{
9124 file->custdata_seg.len = sizeof(int) * 2;
9125 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9128 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9129 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9131 /* TODO: Check if the encoded data is already present in custdata_seg */
9133 return ret;
9136 case VT_BSTR: {
9137 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9138 char *data;
9140 if(file->custdata_seg.data){
9141 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9142 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9143 file->custdata_seg.len += len;
9144 }else{
9145 file->custdata_seg.len = len;
9146 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9149 *((unsigned short *)data) = V_VT(value);
9150 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9151 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9152 if(V_BSTR(&v)[i] <= 0x7f)
9153 data[i+6] = V_BSTR(&v)[i];
9154 else
9155 data[i+6] = '?';
9157 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9158 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9159 data[i] = 0x57;
9161 /* TODO: Check if the encoded data is already present in custdata_seg */
9163 return ret;
9165 default:
9166 FIXME("Argument type not yet handled\n");
9167 return -1;
9171 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9173 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9175 DWORD offs = file->arraydesc_seg.len;
9176 DWORD *encoded;
9177 USHORT i;
9179 /* TODO: we should check for duplicates, but that's harder because each
9180 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9181 * at the library-level) */
9183 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9184 if(!file->arraydesc_seg.data)
9185 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9186 else
9187 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9188 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
9190 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9191 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9192 for(i = 0; i < desc->cDims; ++i){
9193 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9194 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9197 return offs;
9200 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9202 DWORD junk;
9203 INT16 junk2;
9204 DWORD offs = 0;
9205 DWORD encoded[2];
9206 VARTYPE vt, subtype;
9207 char *data;
9209 if(!desc)
9210 return -1;
9212 if(!out_mix)
9213 out_mix = &junk;
9214 if(!out_size)
9215 out_size = &junk2;
9217 vt = desc->vt & VT_TYPEMASK;
9219 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9220 DWORD mix;
9221 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9222 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9223 *out_mix = 0x7FFF;
9224 *out_size += 2 * sizeof(DWORD);
9225 }else if(vt == VT_CARRAY){
9226 encoded[0] = desc->vt | (0x7FFE << 16);
9227 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9228 *out_mix = 0x7FFE;
9229 }else if(vt == VT_USERDEFINED){
9230 encoded[0] = desc->vt | (0x7FFF << 16);
9231 encoded[1] = desc->u.hreftype;
9232 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9233 }else{
9234 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9236 switch(vt){
9237 case VT_INT:
9238 subtype = VT_I4;
9239 break;
9240 case VT_UINT:
9241 subtype = VT_UI4;
9242 break;
9243 case VT_VOID:
9244 subtype = VT_EMPTY;
9245 break;
9246 default:
9247 subtype = vt;
9248 break;
9251 *out_mix = subtype;
9252 return 0x80000000 | (subtype << 16) | desc->vt;
9255 data = file->typdesc_seg.data;
9256 while(offs < file->typdesc_seg.len){
9257 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9258 return offs;
9259 offs += sizeof(encoded);
9262 file->typdesc_seg.len += sizeof(encoded);
9263 if(!file->typdesc_seg.data)
9264 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9265 else
9266 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9268 memcpy(&data[offs], encoded, sizeof(encoded));
9270 return offs;
9273 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9275 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9276 DWORD ret = cdguids_seg->len, offs;
9277 MSFT_CDGuid *cdguid = cdguids_seg->data;
9278 TLBCustData *cd;
9280 if(list_empty(custdata_list))
9281 return -1;
9283 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9284 if(!cdguids_seg->data){
9285 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9286 }else
9287 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9289 offs = ret + sizeof(MSFT_CDGuid);
9290 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9291 cdguid->GuidOffset = cd->guid->offset;
9292 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9293 cdguid->next = offs;
9294 offs += sizeof(MSFT_CDGuid);
9295 ++cdguid;
9298 --cdguid;
9299 cdguid->next = -1;
9301 return ret;
9304 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9305 WMSFT_TLBFile *file)
9307 WMSFT_SegContents *aux_seg = &file->aux_seg;
9308 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9309 MSFT_VarRecord *varrecord;
9310 MSFT_FuncRecord *funcrecord;
9311 MEMBERID *memid;
9312 DWORD *name, *offsets, offs;
9314 for(i = 0; i < info->cFuncs; ++i){
9315 TLBFuncDesc *desc = &info->funcdescs[i];
9317 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9319 /* optional fields */
9320 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9321 if(!list_empty(&desc->custdata_list))
9322 recorded_size += 7 * sizeof(INT);
9323 else if(desc->HelpStringContext != 0)
9324 recorded_size += 6 * sizeof(INT);
9325 /* res9? resA? */
9326 else if(desc->Entry)
9327 recorded_size += 3 * sizeof(INT);
9328 else if(desc->HelpString)
9329 recorded_size += 2 * sizeof(INT);
9330 else if(desc->helpcontext)
9331 recorded_size += sizeof(INT);
9333 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9335 for(j = 0; j < desc->funcdesc.cParams; ++j){
9336 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9337 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9338 break;
9342 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9345 for(i = 0; i < info->cVars; ++i){
9346 TLBVarDesc *desc = &info->vardescs[i];
9348 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9350 /* optional fields */
9351 if(desc->HelpStringContext != 0)
9352 recorded_size += 5 * sizeof(INT);
9353 else if(!list_empty(&desc->custdata_list))
9354 recorded_size += 4 * sizeof(INT);
9355 /* res9? */
9356 else if(desc->HelpString)
9357 recorded_size += 2 * sizeof(INT);
9358 else if(desc->HelpContext != 0)
9359 recorded_size += sizeof(INT);
9361 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9364 if(!recorded_size && !extra_size)
9365 return ret;
9367 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9369 aux_seg->len += recorded_size + extra_size;
9371 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9373 if(aux_seg->data)
9374 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9375 else
9376 aux_seg->data = heap_alloc(aux_seg->len);
9378 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9380 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9381 offs = 0;
9383 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9384 for(i = 0; i < info->cFuncs; ++i){
9385 TLBFuncDesc *desc = &info->funcdescs[i];
9386 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9388 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9389 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9390 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9391 funcrecord->VtableOffset = desc->funcdesc.oVft;
9393 /* FKCCIC:
9394 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9395 * ^^^funckind
9396 * ^^^ ^invkind
9397 * ^has_cust_data
9398 * ^^^^callconv
9399 * ^has_param_defaults
9400 * ^oEntry_is_intresource
9402 funcrecord->FKCCIC =
9403 desc->funcdesc.funckind |
9404 (desc->funcdesc.invkind << 3) |
9405 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9406 (desc->funcdesc.callconv << 8);
9408 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9409 funcrecord->FKCCIC |= 0x2000;
9411 for(j = 0; j < desc->funcdesc.cParams; ++j){
9412 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9413 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9414 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9417 if(paramdefault_size > 0)
9418 funcrecord->FKCCIC |= 0x1000;
9420 funcrecord->nrargs = desc->funcdesc.cParams;
9421 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9423 /* optional fields */
9424 /* res9? resA? */
9425 if(!list_empty(&desc->custdata_list)){
9426 size += 7 * sizeof(INT);
9427 funcrecord->HelpContext = desc->helpcontext;
9428 if(desc->HelpString)
9429 funcrecord->oHelpString = desc->HelpString->offset;
9430 else
9431 funcrecord->oHelpString = -1;
9432 if(!desc->Entry)
9433 funcrecord->oEntry = -1;
9434 else if(IS_INTRESOURCE(desc->Entry))
9435 funcrecord->oEntry = LOWORD(desc->Entry);
9436 else
9437 funcrecord->oEntry = desc->Entry->offset;
9438 funcrecord->res9 = -1;
9439 funcrecord->resA = -1;
9440 funcrecord->HelpStringContext = desc->HelpStringContext;
9441 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9442 }else if(desc->HelpStringContext != 0){
9443 size += 6 * sizeof(INT);
9444 funcrecord->HelpContext = desc->helpcontext;
9445 if(desc->HelpString)
9446 funcrecord->oHelpString = desc->HelpString->offset;
9447 else
9448 funcrecord->oHelpString = -1;
9449 if(!desc->Entry)
9450 funcrecord->oEntry = -1;
9451 else if(IS_INTRESOURCE(desc->Entry))
9452 funcrecord->oEntry = LOWORD(desc->Entry);
9453 else
9454 funcrecord->oEntry = desc->Entry->offset;
9455 funcrecord->res9 = -1;
9456 funcrecord->resA = -1;
9457 funcrecord->HelpStringContext = desc->HelpStringContext;
9458 }else if(desc->Entry){
9459 size += 3 * sizeof(INT);
9460 funcrecord->HelpContext = desc->helpcontext;
9461 if(desc->HelpString)
9462 funcrecord->oHelpString = desc->HelpString->offset;
9463 else
9464 funcrecord->oHelpString = -1;
9465 if(!desc->Entry)
9466 funcrecord->oEntry = -1;
9467 else if(IS_INTRESOURCE(desc->Entry))
9468 funcrecord->oEntry = LOWORD(desc->Entry);
9469 else
9470 funcrecord->oEntry = desc->Entry->offset;
9471 }else if(desc->HelpString){
9472 size += 2 * sizeof(INT);
9473 funcrecord->HelpContext = desc->helpcontext;
9474 funcrecord->oHelpString = desc->HelpString->offset;
9475 }else if(desc->helpcontext){
9476 size += sizeof(INT);
9477 funcrecord->HelpContext = desc->helpcontext;
9480 paramdefault = (DWORD*)((char *)funcrecord + size);
9481 size += paramdefault_size;
9483 for(j = 0; j < desc->funcdesc.cParams; ++j){
9484 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9486 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9487 if(desc->pParamDesc[j].Name)
9488 info->oName = desc->pParamDesc[j].Name->offset;
9489 else
9490 info->oName = -1;
9491 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9493 if(paramdefault_size){
9494 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9495 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9496 else if(paramdefault_size)
9497 *paramdefault = -1;
9498 ++paramdefault;
9501 size += sizeof(MSFT_ParameterInfo);
9504 funcrecord->Info = size | (i << 16); /* is it just the index? */
9506 *offsets = offs;
9507 offs += size;
9508 ++offsets;
9510 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9513 varrecord = (MSFT_VarRecord*)funcrecord;
9514 for(i = 0; i < info->cVars; ++i){
9515 TLBVarDesc *desc = &info->vardescs[i];
9516 DWORD size = 5 * sizeof(INT);
9518 varrecord->vardescsize = sizeof(desc->vardesc);
9519 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9520 varrecord->Flags = desc->vardesc.wVarFlags;
9521 varrecord->VarKind = desc->vardesc.varkind;
9523 if(desc->vardesc.varkind == VAR_CONST){
9524 varrecord->vardescsize += sizeof(VARIANT);
9525 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9526 }else
9527 varrecord->OffsValue = desc->vardesc.u.oInst;
9529 /* res9? */
9530 if(desc->HelpStringContext != 0){
9531 size += 5 * sizeof(INT);
9532 varrecord->HelpContext = desc->HelpContext;
9533 if(desc->HelpString)
9534 varrecord->HelpString = desc->HelpString->offset;
9535 else
9536 varrecord->HelpString = -1;
9537 varrecord->res9 = -1;
9538 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9539 varrecord->HelpStringContext = desc->HelpStringContext;
9540 }else if(!list_empty(&desc->custdata_list)){
9541 size += 4 * sizeof(INT);
9542 varrecord->HelpContext = desc->HelpContext;
9543 if(desc->HelpString)
9544 varrecord->HelpString = desc->HelpString->offset;
9545 else
9546 varrecord->HelpString = -1;
9547 varrecord->res9 = -1;
9548 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9549 }else if(desc->HelpString){
9550 size += 2 * sizeof(INT);
9551 varrecord->HelpContext = desc->HelpContext;
9552 if(desc->HelpString)
9553 varrecord->HelpString = desc->HelpString->offset;
9554 else
9555 varrecord->HelpString = -1;
9556 }else if(desc->HelpContext != 0){
9557 size += sizeof(INT);
9558 varrecord->HelpContext = desc->HelpContext;
9561 varrecord->Info = size | (i << 16);
9563 *offsets = offs;
9564 offs += size;
9565 ++offsets;
9567 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9570 memid = (MEMBERID*)varrecord;
9571 for(i = 0; i < info->cFuncs; ++i){
9572 TLBFuncDesc *desc = &info->funcdescs[i];
9573 *memid = desc->funcdesc.memid;
9574 ++memid;
9576 for(i = 0; i < info->cVars; ++i){
9577 TLBVarDesc *desc = &info->vardescs[i];
9578 *memid = desc->vardesc.memid;
9579 ++memid;
9582 name = (UINT*)memid;
9583 for(i = 0; i < info->cFuncs; ++i){
9584 TLBFuncDesc *desc = &info->funcdescs[i];
9585 if(desc->Name)
9586 *name = desc->Name->offset;
9587 else
9588 *name = -1;
9589 ++name;
9591 for(i = 0; i < info->cVars; ++i){
9592 TLBVarDesc *desc = &info->vardescs[i];
9593 if(desc->Name)
9594 *name = desc->Name->offset;
9595 else
9596 *name = -1;
9597 ++name;
9600 return ret;
9603 typedef struct tagWMSFT_RefChunk {
9604 DWORD href;
9605 DWORD res04;
9606 DWORD res08;
9607 DWORD next;
9608 } WMSFT_RefChunk;
9610 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9612 DWORD offs = file->ref_seg.len, i;
9613 WMSFT_RefChunk *chunk;
9615 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9616 if(!file->ref_seg.data)
9617 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9618 else
9619 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9621 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9623 for(i = 0; i < info->cImplTypes; ++i){
9624 chunk->href = info->impltypes[i].hRef;
9625 chunk->res04 = info->impltypes[i].implflags;
9626 chunk->res08 = -1;
9627 if(i < info->cImplTypes - 1)
9628 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9629 else
9630 chunk->next = -1;
9631 ++chunk;
9634 return offs;
9637 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9639 DWORD size;
9641 size = sizeof(MSFT_TypeInfoBase);
9643 if(data){
9644 MSFT_TypeInfoBase *base = (void*)data;
9645 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9646 base->typekind = TKIND_DISPATCH;
9647 else
9648 base->typekind = info->typekind;
9649 base->typekind |= index << 16; /* TODO: There are some other flags here */
9650 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9651 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9652 base->res2 = 0;
9653 base->res3 = 0;
9654 base->res4 = 3;
9655 base->res5 = 0;
9656 base->cElement = (info->cVars << 16) | info->cFuncs;
9657 base->res7 = 0;
9658 base->res8 = 0;
9659 base->res9 = 0;
9660 base->resA = 0;
9661 if(info->guid)
9662 base->posguid = info->guid->offset;
9663 else
9664 base->posguid = -1;
9665 base->flags = info->wTypeFlags;
9666 if(info->Name) {
9667 base->NameOffset = info->Name->offset;
9669 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9670 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9671 }else {
9672 base->NameOffset = -1;
9674 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9675 if(info->DocString)
9676 base->docstringoffs = info->DocString->offset;
9677 else
9678 base->docstringoffs = -1;
9679 base->helpstringcontext = info->dwHelpStringContext;
9680 base->helpcontext = info->dwHelpContext;
9681 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9682 base->cImplTypes = info->cImplTypes;
9683 base->cbSizeVft = info->cbSizeVft;
9684 base->size = info->cbSizeInstance;
9685 if(info->typekind == TKIND_COCLASS){
9686 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9687 }else if(info->typekind == TKIND_ALIAS){
9688 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9689 }else if(info->typekind == TKIND_MODULE){
9690 if(info->DllName)
9691 base->datatype1 = info->DllName->offset;
9692 else
9693 base->datatype1 = -1;
9694 }else{
9695 if(info->cImplTypes > 0)
9696 base->datatype1 = info->impltypes[0].hRef;
9697 else
9698 base->datatype1 = -1;
9700 base->datatype2 = index; /* FIXME: i think there's more here */
9701 base->res18 = 0;
9702 base->res19 = -1;
9705 return size;
9708 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9710 UINT i;
9712 file->typeinfo_seg.len = 0;
9713 for(i = 0; i < This->TypeInfoCount; ++i){
9714 ITypeInfoImpl *info = This->typeinfos[i];
9715 *junk = file->typeinfo_seg.len;
9716 ++junk;
9717 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9720 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9721 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9723 file->aux_seg.len = 0;
9724 file->aux_seg.data = NULL;
9726 file->typeinfo_seg.len = 0;
9727 for(i = 0; i < This->TypeInfoCount; ++i){
9728 ITypeInfoImpl *info = This->typeinfos[i];
9729 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9730 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9734 typedef struct tagWMSFT_ImpFile {
9735 INT guid_offs;
9736 LCID lcid;
9737 DWORD version;
9738 } WMSFT_ImpFile;
9740 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9742 TLBImpLib *implib;
9743 WMSFT_ImpFile *impfile;
9744 char *data;
9745 DWORD last_offs = 0;
9747 file->impfile_seg.len = 0;
9748 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9749 int size = 0;
9751 if(implib->name){
9752 WCHAR *path = strrchrW(implib->name, '\\');
9753 if(path)
9754 ++path;
9755 else
9756 path = implib->name;
9757 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9758 if (size == 0)
9759 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9762 size += sizeof(INT16);
9763 if (size % 4)
9764 size = (size + 4) & ~0x3;
9765 if (size < 8)
9766 size = 8;
9768 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9771 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9773 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9774 int strlen = 0, size;
9776 impfile = (WMSFT_ImpFile*)data;
9777 impfile->guid_offs = implib->guid->offset;
9778 impfile->lcid = implib->lcid;
9779 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9781 data += sizeof(WMSFT_ImpFile);
9783 if(implib->name){
9784 WCHAR *path= strrchrW(implib->name, '\\');
9785 if(path)
9786 ++path;
9787 else
9788 path = implib->name;
9789 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9790 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9791 if (strlen == 0)
9792 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9795 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9797 size = strlen + sizeof(INT16);
9798 if (size % 4)
9799 size = (size + 4) & ~0x3;
9800 if (size < 8)
9801 size = 8;
9802 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9804 data += size;
9805 implib->offset = last_offs;
9806 last_offs += size + sizeof(WMSFT_ImpFile);
9810 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9812 MSFT_ImpInfo *info;
9813 TLBRefType *ref_type;
9814 UINT i = 0;
9816 WMSFT_compile_impfile(This, file);
9818 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9819 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9821 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9822 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9823 if(ref_type->index == TLB_REF_USE_GUID){
9824 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9825 info->oGuid = ref_type->guid->offset;
9826 }else
9827 info->oGuid = ref_type->index;
9828 info->oImpFile = ref_type->pImpTLInfo->offset;
9829 ++i;
9830 ++info;
9834 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9836 file->guidhash_seg.len = 0x80;
9837 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9838 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9841 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9843 file->namehash_seg.len = 0x200;
9844 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9845 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9848 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9850 if(contents && contents->len){
9851 segdir->offset = *running_offset;
9852 segdir->length = contents->len;
9853 *running_offset += segdir->length;
9854 }else{
9855 segdir->offset = -1;
9856 segdir->length = 0;
9859 /* TODO: do these ever change? */
9860 segdir->res08 = -1;
9861 segdir->res0c = 0xf;
9864 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9866 DWORD written;
9867 if(segment)
9868 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9871 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9872 DWORD file_len)
9874 DWORD i;
9875 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9877 for(i = 0; i < This->TypeInfoCount; ++i){
9878 base->memoffset += file_len;
9879 ++base;
9882 return S_OK;
9885 static void WMSFT_free_file(WMSFT_TLBFile *file)
9887 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9888 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9889 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9890 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9891 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9892 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9893 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9894 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9895 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9896 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9897 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9898 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9899 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9900 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9903 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9905 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9906 WMSFT_TLBFile file;
9907 DWORD written, junk_size, junk_offs, running_offset;
9908 BOOL br;
9909 HANDLE outfile;
9910 HRESULT hres;
9911 DWORD *junk;
9912 UINT i;
9914 TRACE("%p\n", This);
9916 for(i = 0; i < This->TypeInfoCount; ++i)
9917 if(This->typeinfos[i]->needs_layout)
9918 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9920 memset(&file, 0, sizeof(file));
9922 file.header.magic1 = 0x5446534D;
9923 file.header.magic2 = 0x00010002;
9924 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9925 file.header.lcid2 = This->set_lcid;
9926 file.header.varflags = 0x40 | This->syskind;
9927 if (This->HelpFile)
9928 file.header.varflags |= 0x10;
9929 if (This->HelpStringDll)
9930 file.header.varflags |= HELPDLLFLAG;
9931 file.header.version = (This->ver_minor << 16) | This->ver_major;
9932 file.header.flags = This->libflags;
9933 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9934 file.header.helpcontext = This->dwHelpContext;
9935 file.header.res44 = 0x20;
9936 file.header.res48 = 0x80;
9937 file.header.dispatchpos = This->dispatch_href;
9939 WMSFT_compile_namehash(This, &file);
9940 /* do name and string compilation to get offsets for other compilations */
9941 hres = WMSFT_compile_names(This, &file);
9942 if (FAILED(hres)){
9943 WMSFT_free_file(&file);
9944 return hres;
9947 hres = WMSFT_compile_strings(This, &file);
9948 if (FAILED(hres)){
9949 WMSFT_free_file(&file);
9950 return hres;
9953 WMSFT_compile_guidhash(This, &file);
9954 hres = WMSFT_compile_guids(This, &file);
9955 if (FAILED(hres)){
9956 WMSFT_free_file(&file);
9957 return hres;
9960 if(This->HelpFile)
9961 file.header.helpfile = This->HelpFile->offset;
9962 else
9963 file.header.helpfile = -1;
9965 if(This->DocString)
9966 file.header.helpstring = This->DocString->offset;
9967 else
9968 file.header.helpstring = -1;
9970 /* do some more segment compilation */
9971 file.header.nimpinfos = list_count(&This->ref_list);
9972 file.header.nrtypeinfos = This->TypeInfoCount;
9974 if(This->Name)
9975 file.header.NameOffset = This->Name->offset;
9976 else
9977 file.header.NameOffset = -1;
9979 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9981 if(This->guid)
9982 file.header.posguid = This->guid->offset;
9983 else
9984 file.header.posguid = -1;
9986 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9987 if(file.header.varflags & HELPDLLFLAG)
9988 junk_size += sizeof(DWORD);
9989 if(junk_size){
9990 junk = heap_alloc_zero(junk_size);
9991 if(file.header.varflags & HELPDLLFLAG){
9992 *junk = This->HelpStringDll->offset;
9993 junk_offs = 1;
9994 }else
9995 junk_offs = 0;
9996 }else{
9997 junk = NULL;
9998 junk_offs = 0;
10001 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10002 WMSFT_compile_impinfo(This, &file);
10004 running_offset = 0;
10006 TRACE("header at: 0x%x\n", running_offset);
10007 running_offset += sizeof(file.header);
10009 TRACE("junk at: 0x%x\n", running_offset);
10010 running_offset += junk_size;
10012 TRACE("segdir at: 0x%x\n", running_offset);
10013 running_offset += sizeof(file.segdir);
10015 TRACE("typeinfo at: 0x%x\n", running_offset);
10016 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10018 TRACE("guidhashtab at: 0x%x\n", running_offset);
10019 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10021 TRACE("guidtab at: 0x%x\n", running_offset);
10022 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10024 TRACE("reftab at: 0x%x\n", running_offset);
10025 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10027 TRACE("impinfo at: 0x%x\n", running_offset);
10028 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10030 TRACE("impfiles at: 0x%x\n", running_offset);
10031 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10033 TRACE("namehashtab at: 0x%x\n", running_offset);
10034 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10036 TRACE("nametab at: 0x%x\n", running_offset);
10037 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10039 TRACE("stringtab at: 0x%x\n", running_offset);
10040 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10042 TRACE("typdesc at: 0x%x\n", running_offset);
10043 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10045 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10046 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10048 TRACE("custdata at: 0x%x\n", running_offset);
10049 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10051 TRACE("cdguids at: 0x%x\n", running_offset);
10052 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10054 TRACE("res0e at: 0x%x\n", running_offset);
10055 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10057 TRACE("res0f at: 0x%x\n", running_offset);
10058 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10060 TRACE("aux_seg at: 0x%x\n", running_offset);
10062 WMSFT_fixup_typeinfos(This, &file, running_offset);
10064 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10065 FILE_ATTRIBUTE_NORMAL, 0);
10066 if (outfile == INVALID_HANDLE_VALUE){
10067 WMSFT_free_file(&file);
10068 heap_free(junk);
10069 return TYPE_E_IOERROR;
10072 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10073 if (!br) {
10074 WMSFT_free_file(&file);
10075 CloseHandle(outfile);
10076 heap_free(junk);
10077 return TYPE_E_IOERROR;
10080 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10081 heap_free(junk);
10082 if (!br) {
10083 WMSFT_free_file(&file);
10084 CloseHandle(outfile);
10085 return TYPE_E_IOERROR;
10088 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10089 if (!br) {
10090 WMSFT_free_file(&file);
10091 CloseHandle(outfile);
10092 return TYPE_E_IOERROR;
10095 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10096 WMSFT_write_segment(outfile, &file.guidhash_seg);
10097 WMSFT_write_segment(outfile, &file.guid_seg);
10098 WMSFT_write_segment(outfile, &file.ref_seg);
10099 WMSFT_write_segment(outfile, &file.impinfo_seg);
10100 WMSFT_write_segment(outfile, &file.impfile_seg);
10101 WMSFT_write_segment(outfile, &file.namehash_seg);
10102 WMSFT_write_segment(outfile, &file.name_seg);
10103 WMSFT_write_segment(outfile, &file.string_seg);
10104 WMSFT_write_segment(outfile, &file.typdesc_seg);
10105 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10106 WMSFT_write_segment(outfile, &file.custdata_seg);
10107 WMSFT_write_segment(outfile, &file.cdguids_seg);
10108 WMSFT_write_segment(outfile, &file.aux_seg);
10110 WMSFT_free_file(&file);
10112 CloseHandle(outfile);
10114 return S_OK;
10117 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10118 LPOLESTR name)
10120 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10121 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10122 return E_NOTIMPL;
10125 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10126 REFGUID guid, VARIANT *varVal)
10128 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10129 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
10130 return E_NOTIMPL;
10133 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10134 ULONG helpStringContext)
10136 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10137 FIXME("%p %u - stub\n", This, helpStringContext);
10138 return E_NOTIMPL;
10141 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10142 LPOLESTR filename)
10144 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10145 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10147 if (!filename)
10148 return E_INVALIDARG;
10150 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10152 return S_OK;
10155 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10156 ICreateTypeLib2_fnQueryInterface,
10157 ICreateTypeLib2_fnAddRef,
10158 ICreateTypeLib2_fnRelease,
10159 ICreateTypeLib2_fnCreateTypeInfo,
10160 ICreateTypeLib2_fnSetName,
10161 ICreateTypeLib2_fnSetVersion,
10162 ICreateTypeLib2_fnSetGuid,
10163 ICreateTypeLib2_fnSetDocString,
10164 ICreateTypeLib2_fnSetHelpFileName,
10165 ICreateTypeLib2_fnSetHelpContext,
10166 ICreateTypeLib2_fnSetLcid,
10167 ICreateTypeLib2_fnSetLibFlags,
10168 ICreateTypeLib2_fnSaveAllChanges,
10169 ICreateTypeLib2_fnDeleteTypeInfo,
10170 ICreateTypeLib2_fnSetCustData,
10171 ICreateTypeLib2_fnSetHelpStringContext,
10172 ICreateTypeLib2_fnSetHelpStringDll
10175 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10176 REFIID riid, void **object)
10178 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10180 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10183 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10185 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10187 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10190 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10192 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10194 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10197 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10198 REFGUID guid)
10200 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10202 TRACE("%p %s\n", This, debugstr_guid(guid));
10204 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10206 return S_OK;
10209 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10210 UINT typeFlags)
10212 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10213 WORD old_flags;
10214 HRESULT hres;
10216 TRACE("%p %x\n", This, typeFlags);
10218 if (typeFlags & TYPEFLAG_FDUAL) {
10219 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10220 ITypeLib *stdole;
10221 ITypeInfo *dispatch;
10222 HREFTYPE hreftype;
10223 HRESULT hres;
10225 hres = LoadTypeLib(stdole2tlb, &stdole);
10226 if(FAILED(hres))
10227 return hres;
10229 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10230 ITypeLib_Release(stdole);
10231 if(FAILED(hres))
10232 return hres;
10234 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10235 ITypeInfo_Release(dispatch);
10236 if(FAILED(hres))
10237 return hres;
10240 old_flags = This->wTypeFlags;
10241 This->wTypeFlags = typeFlags;
10243 hres = ICreateTypeInfo2_LayOut(iface);
10244 if (FAILED(hres)) {
10245 This->wTypeFlags = old_flags;
10246 return hres;
10249 return S_OK;
10252 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10253 LPOLESTR doc)
10255 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10257 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10259 if (!doc)
10260 return E_INVALIDARG;
10262 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10264 return S_OK;
10267 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10268 DWORD helpContext)
10270 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10272 TRACE("%p %d\n", This, helpContext);
10274 This->dwHelpContext = helpContext;
10276 return S_OK;
10279 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10280 WORD majorVerNum, WORD minorVerNum)
10282 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10284 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10286 This->wMajorVerNum = majorVerNum;
10287 This->wMinorVerNum = minorVerNum;
10289 return S_OK;
10292 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10293 ITypeInfo *typeInfo, HREFTYPE *refType)
10295 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10296 UINT index;
10297 ITypeLib *container;
10298 TLBRefType *ref_type;
10299 TLBImpLib *implib;
10300 TYPEATTR *typeattr;
10301 TLIBATTR *libattr;
10302 HRESULT hres;
10304 TRACE("%p %p %p\n", This, typeInfo, refType);
10306 if (!typeInfo || !refType)
10307 return E_INVALIDARG;
10309 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10310 if (FAILED(hres))
10311 return hres;
10313 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10314 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10316 ITypeLib_Release(container);
10318 *refType = target->hreftype;
10320 return S_OK;
10323 hres = ITypeLib_GetLibAttr(container, &libattr);
10324 if (FAILED(hres)) {
10325 ITypeLib_Release(container);
10326 return hres;
10329 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10330 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10331 implib->lcid == libattr->lcid &&
10332 implib->wVersionMajor == libattr->wMajorVerNum &&
10333 implib->wVersionMinor == libattr->wMinorVerNum)
10334 break;
10337 if(&implib->entry == &This->pTypeLib->implib_list){
10338 implib = heap_alloc_zero(sizeof(TLBImpLib));
10340 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10341 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10342 implib->name = SysAllocString(our_container->path);
10343 }else{
10344 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10345 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10346 if(FAILED(hres)){
10347 implib->name = NULL;
10348 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10352 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10353 implib->lcid = libattr->lcid;
10354 implib->wVersionMajor = libattr->wMajorVerNum;
10355 implib->wVersionMinor = libattr->wMinorVerNum;
10357 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10360 ITypeLib_ReleaseTLibAttr(container, libattr);
10361 ITypeLib_Release(container);
10363 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10364 if (FAILED(hres))
10365 return hres;
10367 index = 0;
10368 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10369 if(ref_type->index == TLB_REF_USE_GUID &&
10370 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10371 ref_type->tkind == typeattr->typekind)
10372 break;
10373 ++index;
10376 if(&ref_type->entry == &This->pTypeLib->ref_list){
10377 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10379 ref_type->tkind = typeattr->typekind;
10380 ref_type->pImpTLInfo = implib;
10381 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10383 ref_type->index = TLB_REF_USE_GUID;
10385 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10387 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10390 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10392 *refType = ref_type->reference | 0x1;
10394 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10395 This->pTypeLib->dispatch_href = *refType;
10397 return S_OK;
10400 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10401 UINT index, FUNCDESC *funcDesc)
10403 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10404 TLBFuncDesc tmp_func_desc, *func_desc;
10405 int buf_size, i;
10406 char *buffer;
10407 HRESULT hres;
10409 TRACE("%p %u %p\n", This, index, funcDesc);
10411 if (!funcDesc || funcDesc->oVft & 3)
10412 return E_INVALIDARG;
10414 switch (This->typekind) {
10415 case TKIND_MODULE:
10416 if (funcDesc->funckind != FUNC_STATIC)
10417 return TYPE_E_BADMODULEKIND;
10418 break;
10419 case TKIND_DISPATCH:
10420 if (funcDesc->funckind != FUNC_DISPATCH)
10421 return TYPE_E_BADMODULEKIND;
10422 break;
10423 default:
10424 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10425 return TYPE_E_BADMODULEKIND;
10428 if (index > This->cFuncs)
10429 return TYPE_E_ELEMENTNOTFOUND;
10431 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10432 !funcDesc->cParams)
10433 return TYPE_E_INCONSISTENTPROPFUNCS;
10435 #ifdef _WIN64
10436 if(This->pTypeLib->syskind == SYS_WIN64 &&
10437 funcDesc->oVft % 8 != 0)
10438 return E_INVALIDARG;
10439 #endif
10441 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10442 TLBFuncDesc_Constructor(&tmp_func_desc);
10444 tmp_func_desc.funcdesc = *funcDesc;
10446 if (tmp_func_desc.funcdesc.oVft != 0)
10447 tmp_func_desc.funcdesc.oVft |= 1;
10449 if (funcDesc->cScodes) {
10450 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10451 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10452 } else
10453 tmp_func_desc.funcdesc.lprgscode = NULL;
10455 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10456 for (i = 0; i < funcDesc->cParams; ++i) {
10457 buf_size += sizeof(ELEMDESC);
10458 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10460 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10461 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10463 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10464 if (FAILED(hres)) {
10465 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10466 heap_free(tmp_func_desc.funcdesc.lprgscode);
10467 return hres;
10470 for (i = 0; i < funcDesc->cParams; ++i) {
10471 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10472 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10473 if (FAILED(hres)) {
10474 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10475 heap_free(tmp_func_desc.funcdesc.lprgscode);
10476 return hres;
10478 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10479 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10480 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10481 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10482 if (FAILED(hres)) {
10483 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10484 heap_free(tmp_func_desc.funcdesc.lprgscode);
10485 return hres;
10490 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10492 if (This->funcdescs) {
10493 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10494 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10496 if (index < This->cFuncs) {
10497 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10498 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10499 func_desc = This->funcdescs + index;
10500 } else
10501 func_desc = This->funcdescs + This->cFuncs;
10503 /* move custdata lists to the new memory location */
10504 for(i = 0; i < This->cFuncs + 1; ++i){
10505 if(index != i){
10506 TLBFuncDesc *fd = &This->funcdescs[i];
10507 if(fd->custdata_list.prev == fd->custdata_list.next)
10508 list_init(&fd->custdata_list);
10509 else{
10510 fd->custdata_list.prev->next = &fd->custdata_list;
10511 fd->custdata_list.next->prev = &fd->custdata_list;
10515 } else
10516 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10518 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10519 list_init(&func_desc->custdata_list);
10521 ++This->cFuncs;
10523 This->needs_layout = TRUE;
10525 return S_OK;
10528 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10529 UINT index, HREFTYPE refType)
10531 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10532 TLBImplType *impl_type;
10533 HRESULT hres;
10535 TRACE("%p %u %d\n", This, index, refType);
10537 switch(This->typekind){
10538 case TKIND_COCLASS: {
10539 if (index == -1) {
10540 FIXME("Unhandled index: -1\n");
10541 return E_NOTIMPL;
10544 if(index != This->cImplTypes)
10545 return TYPE_E_ELEMENTNOTFOUND;
10547 break;
10549 case TKIND_INTERFACE:
10550 case TKIND_DISPATCH:
10551 if (index != 0 || This->cImplTypes)
10552 return TYPE_E_ELEMENTNOTFOUND;
10553 break;
10554 default:
10555 FIXME("Unimplemented typekind: %d\n", This->typekind);
10556 return E_NOTIMPL;
10559 if (This->impltypes){
10560 UINT i;
10562 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10563 sizeof(TLBImplType) * (This->cImplTypes + 1));
10565 if (index < This->cImplTypes) {
10566 memmove(This->impltypes + index + 1, This->impltypes + index,
10567 (This->cImplTypes - index) * sizeof(TLBImplType));
10568 impl_type = This->impltypes + index;
10569 } else
10570 impl_type = This->impltypes + This->cImplTypes;
10572 /* move custdata lists to the new memory location */
10573 for(i = 0; i < This->cImplTypes + 1; ++i){
10574 if(index != i){
10575 TLBImplType *it = &This->impltypes[i];
10576 if(it->custdata_list.prev == it->custdata_list.next)
10577 list_init(&it->custdata_list);
10578 else{
10579 it->custdata_list.prev->next = &it->custdata_list;
10580 it->custdata_list.next->prev = &it->custdata_list;
10584 } else
10585 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10587 memset(impl_type, 0, sizeof(TLBImplType));
10588 TLBImplType_Constructor(impl_type);
10589 impl_type->hRef = refType;
10591 ++This->cImplTypes;
10593 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10594 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10596 hres = ICreateTypeInfo2_LayOut(iface);
10597 if (FAILED(hres))
10598 return hres;
10600 return S_OK;
10603 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10604 UINT index, INT implTypeFlags)
10606 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10607 TLBImplType *impl_type = &This->impltypes[index];
10609 TRACE("%p %u %x\n", This, index, implTypeFlags);
10611 if (This->typekind != TKIND_COCLASS)
10612 return TYPE_E_BADMODULEKIND;
10614 if (index >= This->cImplTypes)
10615 return TYPE_E_ELEMENTNOTFOUND;
10617 impl_type->implflags = implTypeFlags;
10619 return S_OK;
10622 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10623 WORD alignment)
10625 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10627 TRACE("%p %d\n", This, alignment);
10629 This->cbAlignment = alignment;
10631 return S_OK;
10634 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10635 LPOLESTR schema)
10637 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10639 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10641 if (!schema)
10642 return E_INVALIDARG;
10644 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10646 This->lpstrSchema = This->Schema->str;
10648 return S_OK;
10651 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10652 UINT index, VARDESC *varDesc)
10654 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10655 TLBVarDesc *var_desc;
10657 TRACE("%p %u %p\n", This, index, varDesc);
10659 if (This->vardescs){
10660 UINT i;
10662 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10663 sizeof(TLBVarDesc) * (This->cVars + 1));
10665 if (index < This->cVars) {
10666 memmove(This->vardescs + index + 1, This->vardescs + index,
10667 (This->cVars - index) * sizeof(TLBVarDesc));
10668 var_desc = This->vardescs + index;
10669 } else
10670 var_desc = This->vardescs + This->cVars;
10672 /* move custdata lists to the new memory location */
10673 for(i = 0; i < This->cVars + 1; ++i){
10674 if(index != i){
10675 TLBVarDesc *var = &This->vardescs[i];
10676 if(var->custdata_list.prev == var->custdata_list.next)
10677 list_init(&var->custdata_list);
10678 else{
10679 var->custdata_list.prev->next = &var->custdata_list;
10680 var->custdata_list.next->prev = &var->custdata_list;
10684 } else
10685 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10687 TLBVarDesc_Constructor(var_desc);
10688 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10689 var_desc->vardesc = *var_desc->vardesc_create;
10691 ++This->cVars;
10693 This->needs_layout = TRUE;
10695 return S_OK;
10698 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10699 UINT index, LPOLESTR *names, UINT numNames)
10701 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10702 TLBFuncDesc *func_desc = &This->funcdescs[index];
10703 int i;
10705 TRACE("%p %u %p %u\n", This, index, names, numNames);
10707 if (!names)
10708 return E_INVALIDARG;
10710 if (index >= This->cFuncs || numNames == 0)
10711 return TYPE_E_ELEMENTNOTFOUND;
10713 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10714 if(numNames > func_desc->funcdesc.cParams)
10715 return TYPE_E_ELEMENTNOTFOUND;
10716 } else
10717 if(numNames > func_desc->funcdesc.cParams + 1)
10718 return TYPE_E_ELEMENTNOTFOUND;
10720 for(i = 0; i < This->cFuncs; ++i) {
10721 TLBFuncDesc *iter = &This->funcdescs[i];
10722 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10723 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10724 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10725 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10726 continue;
10727 return TYPE_E_AMBIGUOUSNAME;
10731 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10733 for (i = 1; i < numNames; ++i) {
10734 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10735 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10738 return S_OK;
10741 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10742 UINT index, LPOLESTR name)
10744 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10746 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10748 if(!name)
10749 return E_INVALIDARG;
10751 if(index >= This->cVars)
10752 return TYPE_E_ELEMENTNOTFOUND;
10754 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10755 return S_OK;
10758 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10759 TYPEDESC *tdescAlias)
10761 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10762 HRESULT hr;
10764 TRACE("%p %p\n", This, tdescAlias);
10766 if(!tdescAlias)
10767 return E_INVALIDARG;
10769 if(This->typekind != TKIND_ALIAS)
10770 return TYPE_E_BADMODULEKIND;
10772 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->cbSizeInstance, &This->cbAlignment);
10773 if(FAILED(hr))
10774 return hr;
10776 heap_free(This->tdescAlias);
10777 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10778 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10780 return S_OK;
10783 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10784 UINT index, LPOLESTR dllName, LPOLESTR procName)
10786 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10787 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10788 return E_NOTIMPL;
10791 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10792 UINT index, LPOLESTR docString)
10794 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10795 TLBFuncDesc *func_desc = &This->funcdescs[index];
10797 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10799 if(!docString)
10800 return E_INVALIDARG;
10802 if(index >= This->cFuncs)
10803 return TYPE_E_ELEMENTNOTFOUND;
10805 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10807 return S_OK;
10810 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10811 UINT index, LPOLESTR docString)
10813 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10814 TLBVarDesc *var_desc = &This->vardescs[index];
10816 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10818 if(!docString)
10819 return E_INVALIDARG;
10821 if(index >= This->cVars)
10822 return TYPE_E_ELEMENTNOTFOUND;
10824 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10826 return S_OK;
10829 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10830 UINT index, DWORD helpContext)
10832 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10833 TLBFuncDesc *func_desc = &This->funcdescs[index];
10835 TRACE("%p %u %d\n", This, index, helpContext);
10837 if(index >= This->cFuncs)
10838 return TYPE_E_ELEMENTNOTFOUND;
10840 func_desc->helpcontext = helpContext;
10842 return S_OK;
10845 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10846 UINT index, DWORD helpContext)
10848 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10849 TLBVarDesc *var_desc = &This->vardescs[index];
10851 TRACE("%p %u %d\n", This, index, helpContext);
10853 if(index >= This->cVars)
10854 return TYPE_E_ELEMENTNOTFOUND;
10856 var_desc->HelpContext = helpContext;
10858 return S_OK;
10861 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10862 UINT index, BSTR bstrMops)
10864 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10865 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10866 return E_NOTIMPL;
10869 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10870 IDLDESC *idlDesc)
10872 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10874 TRACE("%p %p\n", This, idlDesc);
10876 if (!idlDesc)
10877 return E_INVALIDARG;
10879 This->idldescType.dwReserved = idlDesc->dwReserved;
10880 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10882 return S_OK;
10885 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10887 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10888 ITypeInfo *tinfo;
10889 TLBFuncDesc *func_desc;
10890 UINT user_vft = 0, i, depth = 0;
10891 HRESULT hres = S_OK;
10893 TRACE("%p\n", This);
10895 This->needs_layout = FALSE;
10897 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10898 if (FAILED(hres))
10899 return hres;
10901 if (This->typekind == TKIND_INTERFACE) {
10902 ITypeInfo *inh;
10903 TYPEATTR *attr;
10904 HREFTYPE inh_href;
10906 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10908 if (SUCCEEDED(hres)) {
10909 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10911 if (SUCCEEDED(hres)) {
10912 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10913 if (FAILED(hres)) {
10914 ITypeInfo_Release(inh);
10915 ITypeInfo_Release(tinfo);
10916 return hres;
10918 This->cbSizeVft = attr->cbSizeVft;
10919 ITypeInfo_ReleaseTypeAttr(inh, attr);
10922 ++depth;
10923 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10924 if(SUCCEEDED(hres)){
10925 ITypeInfo *next;
10926 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10927 if(SUCCEEDED(hres)){
10928 ITypeInfo_Release(inh);
10929 inh = next;
10932 }while(SUCCEEDED(hres));
10933 hres = S_OK;
10935 ITypeInfo_Release(inh);
10936 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10937 This->cbSizeVft = 0;
10938 hres = S_OK;
10939 } else {
10940 ITypeInfo_Release(tinfo);
10941 return hres;
10943 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10944 This->cbSizeVft = 0;
10945 hres = S_OK;
10946 } else {
10947 ITypeInfo_Release(tinfo);
10948 return hres;
10950 } else if (This->typekind == TKIND_DISPATCH)
10951 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10952 else
10953 This->cbSizeVft = 0;
10955 func_desc = This->funcdescs;
10956 i = 0;
10957 while (i < This->cFuncs) {
10958 if (!(func_desc->funcdesc.oVft & 0x1))
10959 func_desc->funcdesc.oVft = This->cbSizeVft;
10961 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10962 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10964 This->cbSizeVft += This->pTypeLib->ptr_size;
10966 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10967 TLBFuncDesc *iter;
10968 UINT j = 0;
10969 BOOL reset = FALSE;
10971 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10973 iter = This->funcdescs;
10974 while (j < This->cFuncs) {
10975 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10976 if (!reset) {
10977 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10978 reset = TRUE;
10979 } else
10980 ++func_desc->funcdesc.memid;
10981 iter = This->funcdescs;
10982 j = 0;
10983 } else {
10984 ++iter;
10985 ++j;
10990 ++func_desc;
10991 ++i;
10994 if (user_vft > This->cbSizeVft)
10995 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10997 for(i = 0; i < This->cVars; ++i){
10998 TLBVarDesc *var_desc = &This->vardescs[i];
10999 if(var_desc->vardesc.memid == MEMBERID_NIL){
11000 UINT j = 0;
11001 BOOL reset = FALSE;
11002 TLBVarDesc *iter;
11004 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11006 iter = This->vardescs;
11007 while (j < This->cVars) {
11008 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11009 if (!reset) {
11010 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->cVars;
11011 reset = TRUE;
11012 } else
11013 ++var_desc->vardesc.memid;
11014 iter = This->vardescs;
11015 j = 0;
11016 } else {
11017 ++iter;
11018 ++j;
11024 ITypeInfo_Release(tinfo);
11025 return hres;
11028 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11029 UINT index)
11031 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11032 FIXME("%p %u - stub\n", This, index);
11033 return E_NOTIMPL;
11036 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11037 MEMBERID memid, INVOKEKIND invKind)
11039 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11040 FIXME("%p %x %d - stub\n", This, memid, invKind);
11041 return E_NOTIMPL;
11044 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11045 UINT index)
11047 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11048 FIXME("%p %u - stub\n", This, index);
11049 return E_NOTIMPL;
11052 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11053 MEMBERID memid)
11055 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11056 FIXME("%p %x - stub\n", This, memid);
11057 return E_NOTIMPL;
11060 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11061 UINT index)
11063 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11064 FIXME("%p %u - stub\n", This, index);
11065 return E_NOTIMPL;
11068 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11069 REFGUID guid, VARIANT *varVal)
11071 TLBGuid *tlbguid;
11073 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11075 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11077 if (!guid || !varVal)
11078 return E_INVALIDARG;
11080 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11082 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11085 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11086 UINT index, REFGUID guid, VARIANT *varVal)
11088 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11089 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11090 return E_NOTIMPL;
11093 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11094 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11096 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11097 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11098 return E_NOTIMPL;
11101 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11102 UINT index, REFGUID guid, VARIANT *varVal)
11104 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11105 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11106 return E_NOTIMPL;
11109 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11110 UINT index, REFGUID guid, VARIANT *varVal)
11112 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11113 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11114 return E_NOTIMPL;
11117 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11118 ULONG helpStringContext)
11120 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11122 TRACE("%p %u\n", This, helpStringContext);
11124 This->dwHelpStringContext = helpStringContext;
11126 return S_OK;
11129 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11130 UINT index, ULONG helpStringContext)
11132 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11133 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11134 return E_NOTIMPL;
11137 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11138 UINT index, ULONG helpStringContext)
11140 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11141 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11142 return E_NOTIMPL;
11145 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11147 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11148 FIXME("%p - stub\n", This);
11149 return E_NOTIMPL;
11152 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11153 LPOLESTR name)
11155 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11157 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11159 if (!name)
11160 return E_INVALIDARG;
11162 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11164 return S_OK;
11167 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11168 ICreateTypeInfo2_fnQueryInterface,
11169 ICreateTypeInfo2_fnAddRef,
11170 ICreateTypeInfo2_fnRelease,
11171 ICreateTypeInfo2_fnSetGuid,
11172 ICreateTypeInfo2_fnSetTypeFlags,
11173 ICreateTypeInfo2_fnSetDocString,
11174 ICreateTypeInfo2_fnSetHelpContext,
11175 ICreateTypeInfo2_fnSetVersion,
11176 ICreateTypeInfo2_fnAddRefTypeInfo,
11177 ICreateTypeInfo2_fnAddFuncDesc,
11178 ICreateTypeInfo2_fnAddImplType,
11179 ICreateTypeInfo2_fnSetImplTypeFlags,
11180 ICreateTypeInfo2_fnSetAlignment,
11181 ICreateTypeInfo2_fnSetSchema,
11182 ICreateTypeInfo2_fnAddVarDesc,
11183 ICreateTypeInfo2_fnSetFuncAndParamNames,
11184 ICreateTypeInfo2_fnSetVarName,
11185 ICreateTypeInfo2_fnSetTypeDescAlias,
11186 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11187 ICreateTypeInfo2_fnSetFuncDocString,
11188 ICreateTypeInfo2_fnSetVarDocString,
11189 ICreateTypeInfo2_fnSetFuncHelpContext,
11190 ICreateTypeInfo2_fnSetVarHelpContext,
11191 ICreateTypeInfo2_fnSetMops,
11192 ICreateTypeInfo2_fnSetTypeIdldesc,
11193 ICreateTypeInfo2_fnLayOut,
11194 ICreateTypeInfo2_fnDeleteFuncDesc,
11195 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11196 ICreateTypeInfo2_fnDeleteVarDesc,
11197 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11198 ICreateTypeInfo2_fnDeleteImplType,
11199 ICreateTypeInfo2_fnSetCustData,
11200 ICreateTypeInfo2_fnSetFuncCustData,
11201 ICreateTypeInfo2_fnSetParamCustData,
11202 ICreateTypeInfo2_fnSetVarCustData,
11203 ICreateTypeInfo2_fnSetImplTypeCustData,
11204 ICreateTypeInfo2_fnSetHelpStringContext,
11205 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11206 ICreateTypeInfo2_fnSetVarHelpStringContext,
11207 ICreateTypeInfo2_fnInvalidate,
11208 ICreateTypeInfo2_fnSetName
11211 /******************************************************************************
11212 * ClearCustData (OLEAUT32.171)
11214 * Clear a custom data type's data.
11216 * PARAMS
11217 * lpCust [I] The custom data type instance
11219 * RETURNS
11220 * Nothing.
11222 void WINAPI ClearCustData(CUSTDATA *lpCust)
11224 if (lpCust && lpCust->cCustData)
11226 if (lpCust->prgCustData)
11228 DWORD i;
11230 for (i = 0; i < lpCust->cCustData; i++)
11231 VariantClear(&lpCust->prgCustData[i].varValue);
11233 /* FIXME - Should be using a per-thread IMalloc */
11234 heap_free(lpCust->prgCustData);
11235 lpCust->prgCustData = NULL;
11237 lpCust->cCustData = 0;