oleaut32: Return FALSE from SystemTimeToVariantTime if day > 31 or year is negative.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob0dd3f645a758734d7db6343ae30426cda66c615a
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 0;
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_ALWAYS,
3409 FILE_ATTRIBUTE_NORMAL, NULL);
3410 if(h != INVALID_HANDLE_VALUE){
3411 FILE_NAME_INFORMATION *info;
3412 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3413 BOOL br;
3415 info = (FILE_NAME_INFORMATION*)data;
3416 /* GetFileInformationByHandleEx returns the path of the file without
3417 * WOW64 redirection */
3418 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3419 if(br){
3420 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3421 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3423 CloseHandle(h);
3426 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3428 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3429 EnterCriticalSection(&cache_section);
3430 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3432 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3434 TRACE("cache hit\n");
3435 *ppTypeLib = &entry->ITypeLib2_iface;
3436 ITypeLib2_AddRef(*ppTypeLib);
3437 LeaveCriticalSection(&cache_section);
3438 return S_OK;
3441 LeaveCriticalSection(&cache_section);
3443 /* now actually load and parse the typelib */
3445 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3446 if (ret == TYPE_E_CANTLOADLIBRARY)
3447 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3448 if (ret == TYPE_E_CANTLOADLIBRARY)
3449 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3450 if (SUCCEEDED(ret))
3452 if (dwTLBLength >= 4)
3454 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3455 if (dwSignature == MSFT_SIGNATURE)
3456 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3457 else if (dwSignature == SLTG_SIGNATURE)
3458 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3459 else
3461 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3462 ret = TYPE_E_CANTLOADLIBRARY;
3465 else
3466 ret = TYPE_E_CANTLOADLIBRARY;
3467 IUnknown_Release(pFile);
3470 if(*ppTypeLib) {
3471 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3473 TRACE("adding to cache\n");
3474 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3475 lstrcpyW(impl->path, pszPath);
3476 /* We should really canonicalise the path here. */
3477 impl->index = index;
3479 /* FIXME: check if it has added already in the meantime */
3480 EnterCriticalSection(&cache_section);
3481 list_add_head(&tlb_cache, &impl->entry);
3482 LeaveCriticalSection(&cache_section);
3483 ret = S_OK;
3485 else
3487 if(ret != E_FAIL)
3488 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3490 ret = TYPE_E_CANTLOADLIBRARY;
3494 return ret;
3497 /*================== ITypeLib(2) Methods ===================================*/
3499 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3501 ITypeLibImpl* pTypeLibImpl;
3503 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3504 if (!pTypeLibImpl) return NULL;
3506 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3507 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3508 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3509 pTypeLibImpl->ref = 1;
3511 list_init(&pTypeLibImpl->implib_list);
3512 list_init(&pTypeLibImpl->custdata_list);
3513 list_init(&pTypeLibImpl->name_list);
3514 list_init(&pTypeLibImpl->string_list);
3515 list_init(&pTypeLibImpl->guid_list);
3516 list_init(&pTypeLibImpl->ref_list);
3517 pTypeLibImpl->dispatch_href = -1;
3519 return pTypeLibImpl;
3522 /****************************************************************************
3523 * ITypeLib2_Constructor_MSFT
3525 * loading an MSFT typelib from an in-memory image
3527 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3529 TLBContext cx;
3530 LONG lPSegDir;
3531 MSFT_Header tlbHeader;
3532 MSFT_SegDir tlbSegDir;
3533 ITypeLibImpl * pTypeLibImpl;
3534 int i;
3536 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3538 pTypeLibImpl = TypeLibImpl_Constructor();
3539 if (!pTypeLibImpl) return NULL;
3541 /* get pointer to beginning of typelib data */
3542 cx.pos = 0;
3543 cx.oStart=0;
3544 cx.mapping = pLib;
3545 cx.pLibInfo = pTypeLibImpl;
3546 cx.length = dwTLBLength;
3548 /* read header */
3549 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3550 TRACE_(typelib)("header:\n");
3551 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3552 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3553 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3554 return NULL;
3556 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3558 /* there is a small amount of information here until the next important
3559 * part:
3560 * the segment directory . Try to calculate the amount of data */
3561 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3563 /* now read the segment directory */
3564 TRACE("read segment directory (at %d)\n",lPSegDir);
3565 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3566 cx.pTblDir = &tlbSegDir;
3568 /* just check two entries */
3569 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3571 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3572 heap_free(pTypeLibImpl);
3573 return NULL;
3576 MSFT_ReadAllNames(&cx);
3577 MSFT_ReadAllStrings(&cx);
3578 MSFT_ReadAllGuids(&cx);
3580 /* now fill our internal data */
3581 /* TLIBATTR fields */
3582 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3584 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3585 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3586 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3587 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3588 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3590 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3591 pTypeLibImpl->lcid = tlbHeader.lcid;
3593 /* name, eventually add to a hash table */
3594 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3596 /* help info */
3597 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3598 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3600 if( tlbHeader.varflags & HELPDLLFLAG)
3602 int offset;
3603 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3604 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3607 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3609 /* custom data */
3610 if(tlbHeader.CustomDataOffset >= 0)
3612 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3615 /* fill in type descriptions */
3616 if(tlbSegDir.pTypdescTab.length > 0)
3618 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3619 INT16 td[4];
3620 pTypeLibImpl->ctTypeDesc = cTD;
3621 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3622 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3623 for(i=0; i<cTD; )
3625 /* FIXME: add several sanity checks here */
3626 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3627 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3629 /* FIXME: check safearray */
3630 if(td[3] < 0)
3631 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3632 else
3633 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3635 else if(td[0] == VT_CARRAY)
3637 /* array descr table here */
3638 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3640 else if(td[0] == VT_USERDEFINED)
3642 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3644 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3647 /* second time around to fill the array subscript info */
3648 for(i=0;i<cTD;i++)
3650 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3651 if(tlbSegDir.pArrayDescriptions.offset>0)
3653 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3654 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3656 if(td[1]<0)
3657 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3658 else
3659 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3661 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3663 for(j = 0; j<td[2]; j++)
3665 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3666 sizeof(INT), &cx, DO_NOT_SEEK);
3667 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3668 sizeof(INT), &cx, DO_NOT_SEEK);
3671 else
3673 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3674 ERR("didn't find array description data\n");
3679 /* imported type libs */
3680 if(tlbSegDir.pImpFiles.offset>0)
3682 TLBImpLib *pImpLib;
3683 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3684 UINT16 size;
3686 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3688 char *name;
3690 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3691 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3692 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3694 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3695 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3696 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3697 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3699 size >>= 2;
3700 name = heap_alloc_zero(size+1);
3701 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3702 pImpLib->name = TLB_MultiByteToBSTR(name);
3703 heap_free(name);
3705 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3706 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3708 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3712 MSFT_ReadAllRefs(&cx);
3714 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3716 /* type infos */
3717 if(tlbHeader.nrtypeinfos >= 0 )
3719 ITypeInfoImpl **ppTI;
3721 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3723 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3725 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3727 ++ppTI;
3728 (pTypeLibImpl->TypeInfoCount)++;
3732 #ifdef _WIN64
3733 if(pTypeLibImpl->syskind == SYS_WIN32){
3734 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3735 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3737 #endif
3739 TRACE("(%p)\n", pTypeLibImpl);
3740 return &pTypeLibImpl->ITypeLib2_iface;
3744 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3746 char b[3];
3747 int i;
3748 short s;
3750 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3751 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3752 return FALSE;
3755 guid->Data4[0] = s >> 8;
3756 guid->Data4[1] = s & 0xff;
3758 b[2] = '\0';
3759 for(i = 0; i < 6; i++) {
3760 memcpy(b, str + 24 + 2 * i, 2);
3761 guid->Data4[i + 2] = strtol(b, NULL, 16);
3763 return TRUE;
3766 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3768 WORD bytelen;
3769 DWORD len;
3770 BSTR tmp_str;
3772 *pStr = NULL;
3773 bytelen = *(const WORD*)ptr;
3774 if(bytelen == 0xffff) return 2;
3776 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3777 tmp_str = SysAllocStringLen(NULL, len);
3778 if (tmp_str) {
3779 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3780 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3781 SysFreeString(tmp_str);
3783 return bytelen + 2;
3786 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3788 WORD bytelen;
3790 *str = NULL;
3791 bytelen = *(const WORD*)ptr;
3792 if(bytelen == 0xffff) return 2;
3793 *str = heap_alloc(bytelen + 1);
3794 memcpy(*str, ptr + 2, bytelen);
3795 (*str)[bytelen] = '\0';
3796 return bytelen + 2;
3799 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3801 BSTR tmp_str;
3802 TLBString *tlbstr;
3804 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3805 if (tlbstr->offset == offset)
3806 return tlbstr;
3809 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3810 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3811 SysFreeString(tmp_str);
3813 return tlbstr;
3816 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3818 char *ptr = pLibBlk;
3819 WORD w;
3821 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3822 FIXME("libblk magic = %04x\n", w);
3823 return 0;
3826 ptr += 6;
3827 if((w = *(WORD*)ptr) != 0xffff) {
3828 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3829 ptr += w;
3831 ptr += 2;
3833 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3835 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3837 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3838 ptr += 4;
3840 pTypeLibImpl->syskind = *(WORD*)ptr;
3841 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3842 ptr += 2;
3844 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3845 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3846 else
3847 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3848 ptr += 2;
3850 ptr += 4; /* skip res12 */
3852 pTypeLibImpl->libflags = *(WORD*)ptr;
3853 ptr += 2;
3855 pTypeLibImpl->ver_major = *(WORD*)ptr;
3856 ptr += 2;
3858 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3859 ptr += 2;
3861 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3862 ptr += sizeof(GUID);
3864 return ptr - (char*)pLibBlk;
3867 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3868 typedef struct
3870 unsigned int num;
3871 HREFTYPE refs[1];
3872 } sltg_ref_lookup_t;
3874 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3875 HREFTYPE *typelib_ref)
3877 if(table && typeinfo_ref < table->num)
3879 *typelib_ref = table->refs[typeinfo_ref];
3880 return S_OK;
3883 ERR_(typelib)("Unable to find reference\n");
3884 *typelib_ref = -1;
3885 return E_FAIL;
3888 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3890 BOOL done = FALSE;
3892 while(!done) {
3893 if((*pType & 0xe00) == 0xe00) {
3894 pTD->vt = VT_PTR;
3895 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3896 pTD = pTD->u.lptdesc;
3898 switch(*pType & 0x3f) {
3899 case VT_PTR:
3900 pTD->vt = VT_PTR;
3901 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3902 pTD = pTD->u.lptdesc;
3903 break;
3905 case VT_USERDEFINED:
3906 pTD->vt = VT_USERDEFINED;
3907 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3908 done = TRUE;
3909 break;
3911 case VT_CARRAY:
3913 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3914 array */
3916 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3918 pTD->vt = VT_CARRAY;
3919 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3920 pTD->u.lpadesc->cDims = pSA->cDims;
3921 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3922 pSA->cDims * sizeof(SAFEARRAYBOUND));
3924 pTD = &pTD->u.lpadesc->tdescElem;
3925 break;
3928 case VT_SAFEARRAY:
3930 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3931 useful? */
3933 pType++;
3934 pTD->vt = VT_SAFEARRAY;
3935 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3936 pTD = pTD->u.lptdesc;
3937 break;
3939 default:
3940 pTD->vt = *pType & 0x3f;
3941 done = TRUE;
3942 break;
3944 pType++;
3946 return pType;
3949 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3950 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3952 /* Handle [in/out] first */
3953 if((*pType & 0xc000) == 0xc000)
3954 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3955 else if(*pType & 0x8000)
3956 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3957 else if(*pType & 0x4000)
3958 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3959 else
3960 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3962 if(*pType & 0x2000)
3963 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3965 if(*pType & 0x80)
3966 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3968 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3972 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3973 char *pNameTable)
3975 unsigned int ref;
3976 char *name;
3977 TLBRefType *ref_type;
3978 sltg_ref_lookup_t *table;
3979 HREFTYPE typelib_ref;
3981 if(pRef->magic != SLTG_REF_MAGIC) {
3982 FIXME("Ref magic = %x\n", pRef->magic);
3983 return NULL;
3985 name = ( (char*)pRef->names + pRef->number);
3987 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3988 table->num = pRef->number >> 3;
3990 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3992 /* We don't want the first href to be 0 */
3993 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3995 for(ref = 0; ref < pRef->number >> 3; ref++) {
3996 char *refname;
3997 unsigned int lib_offs, type_num;
3999 ref_type = heap_alloc_zero(sizeof(TLBRefType));
4001 name += SLTG_ReadStringA(name, &refname);
4002 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
4003 FIXME_(typelib)("Can't sscanf ref\n");
4004 if(lib_offs != 0xffff) {
4005 TLBImpLib *import;
4007 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
4008 if(import->offset == lib_offs)
4009 break;
4011 if(&import->entry == &pTL->implib_list) {
4012 char fname[MAX_PATH+1];
4013 int len;
4014 GUID tmpguid;
4016 import = heap_alloc_zero(sizeof(*import));
4017 import->offset = lib_offs;
4018 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
4019 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
4020 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
4021 &import->wVersionMajor,
4022 &import->wVersionMinor,
4023 &import->lcid, fname) != 4) {
4024 FIXME_(typelib)("can't sscanf ref %s\n",
4025 pNameTable + lib_offs + 40);
4027 len = strlen(fname);
4028 if(fname[len-1] != '#')
4029 FIXME("fname = %s\n", fname);
4030 fname[len-1] = '\0';
4031 import->name = TLB_MultiByteToBSTR(fname);
4032 list_add_tail(&pTL->implib_list, &import->entry);
4034 ref_type->pImpTLInfo = import;
4036 /* Store a reference to IDispatch */
4037 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
4038 pTL->dispatch_href = typelib_ref;
4040 } else { /* internal ref */
4041 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
4043 ref_type->reference = typelib_ref;
4044 ref_type->index = type_num;
4046 heap_free(refname);
4047 list_add_tail(&pTL->ref_list, &ref_type->entry);
4049 table->refs[ref] = typelib_ref;
4050 typelib_ref += 4;
4052 if((BYTE)*name != SLTG_REF_MAGIC)
4053 FIXME_(typelib)("End of ref block magic = %x\n", *name);
4054 dump_TLBRefType(pTL);
4055 return table;
4058 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
4059 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
4061 SLTG_ImplInfo *info;
4062 TLBImplType *pImplType;
4063 /* I don't really get this structure, usually it's 0x16 bytes
4064 long, but iuser.tlb contains some that are 0x18 bytes long.
4065 That's ok because we can use the next ptr to jump to the next
4066 one. But how do we know the length of the last one? The WORD
4067 at offs 0x8 might be the clue. For now I'm just assuming that
4068 the last one is the regular 0x16 bytes. */
4070 info = (SLTG_ImplInfo*)pBlk;
4071 while(1){
4072 pTI->cImplTypes++;
4073 if(info->next == 0xffff)
4074 break;
4075 info = (SLTG_ImplInfo*)(pBlk + info->next);
4078 info = (SLTG_ImplInfo*)pBlk;
4079 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
4080 pImplType = pTI->impltypes;
4081 while(1) {
4082 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4083 pImplType->implflags = info->impltypeflags;
4084 ++pImplType;
4086 if(info->next == 0xffff)
4087 break;
4088 if(OneOnly)
4089 FIXME_(typelib)("Interface inheriting more than one interface\n");
4090 info = (SLTG_ImplInfo*)(pBlk + info->next);
4092 info++; /* see comment at top of function */
4093 return (char*)info;
4096 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4097 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4099 TLBVarDesc *pVarDesc;
4100 const TLBString *prevName = NULL;
4101 SLTG_Variable *pItem;
4102 unsigned short i;
4103 WORD *pType;
4105 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4107 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4108 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4110 pVarDesc->vardesc.memid = pItem->memid;
4112 if (pItem->magic != SLTG_VAR_MAGIC &&
4113 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4114 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4115 return;
4118 if (pItem->name == 0xfffe)
4119 pVarDesc->Name = prevName;
4120 else
4121 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4123 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4124 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4125 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4127 if(pItem->flags & 0x02)
4128 pType = &pItem->type;
4129 else
4130 pType = (WORD*)(pBlk + pItem->type);
4132 if (pItem->flags & ~0xda)
4133 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4135 SLTG_DoElem(pType, pBlk,
4136 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4138 if (TRACE_ON(typelib)) {
4139 char buf[300];
4140 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4141 TRACE_(typelib)("elemdescVar: %s\n", buf);
4144 if (pItem->flags & 0x40) {
4145 TRACE_(typelib)("VAR_DISPATCH\n");
4146 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4148 else if (pItem->flags & 0x10) {
4149 TRACE_(typelib)("VAR_CONST\n");
4150 pVarDesc->vardesc.varkind = VAR_CONST;
4151 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4152 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4153 if (pItem->flags & 0x08)
4154 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4155 else {
4156 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4158 case VT_LPSTR:
4159 case VT_LPWSTR:
4160 case VT_BSTR:
4162 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4163 BSTR str;
4164 TRACE_(typelib)("len = %u\n", len);
4165 if (len == 0xffff) {
4166 str = NULL;
4167 } else {
4168 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4169 str = SysAllocStringLen(NULL, alloc_len);
4170 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4172 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4173 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4174 break;
4176 case VT_I2:
4177 case VT_UI2:
4178 case VT_I4:
4179 case VT_UI4:
4180 case VT_INT:
4181 case VT_UINT:
4182 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4183 *(INT*)(pBlk + pItem->byte_offs);
4184 break;
4185 default:
4186 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4190 else {
4191 TRACE_(typelib)("VAR_PERINSTANCE\n");
4192 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4193 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4196 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4197 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4199 if (pItem->flags & 0x80)
4200 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4202 prevName = pVarDesc->Name;
4204 pTI->cVars = cVars;
4207 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4208 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4210 SLTG_Function *pFunc;
4211 unsigned short i;
4212 TLBFuncDesc *pFuncDesc;
4214 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4216 pFuncDesc = pTI->funcdescs;
4217 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4218 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4220 int param;
4221 WORD *pType, *pArg;
4223 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4224 case SLTG_FUNCTION_MAGIC:
4225 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4226 break;
4227 case SLTG_DISPATCH_FUNCTION_MAGIC:
4228 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4229 break;
4230 case SLTG_STATIC_FUNCTION_MAGIC:
4231 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4232 break;
4233 default:
4234 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4235 continue;
4237 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4239 pFuncDesc->funcdesc.memid = pFunc->dispid;
4240 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4241 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4242 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4243 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4244 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4246 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4247 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4249 if(pFunc->retnextopt & 0x80)
4250 pType = &pFunc->rettype;
4251 else
4252 pType = (WORD*)(pBlk + pFunc->rettype);
4254 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4256 pFuncDesc->funcdesc.lprgelemdescParam =
4257 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4258 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4260 pArg = (WORD*)(pBlk + pFunc->arg_off);
4262 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4263 char *paramName = pNameTable + *pArg;
4264 BOOL HaveOffs;
4265 /* If arg type follows then paramName points to the 2nd
4266 letter of the name, else the next WORD is an offset to
4267 the arg type and paramName points to the first letter.
4268 So let's take one char off paramName and see if we're
4269 pointing at an alpha-numeric char. However if *pArg is
4270 0xffff or 0xfffe then the param has no name, the former
4271 meaning that the next WORD is the type, the latter
4272 meaning that the next WORD is an offset to the type. */
4274 HaveOffs = FALSE;
4275 if(*pArg == 0xffff)
4276 paramName = NULL;
4277 else if(*pArg == 0xfffe) {
4278 paramName = NULL;
4279 HaveOffs = TRUE;
4281 else if(paramName[-1] && !isalnum(paramName[-1]))
4282 HaveOffs = TRUE;
4284 pArg++;
4286 if(HaveOffs) { /* the next word is an offset to type */
4287 pType = (WORD*)(pBlk + *pArg);
4288 SLTG_DoElem(pType, pBlk,
4289 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4290 pArg++;
4291 } else {
4292 if(paramName)
4293 paramName--;
4294 pArg = SLTG_DoElem(pArg, pBlk,
4295 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4298 /* Are we an optional param ? */
4299 if(pFuncDesc->funcdesc.cParams - param <=
4300 pFuncDesc->funcdesc.cParamsOpt)
4301 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4303 if(paramName) {
4304 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4305 paramName - pNameTable, pTI->pTypeLib);
4306 } else {
4307 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4311 pTI->cFuncs = cFuncs;
4314 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4315 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4316 SLTG_TypeInfoTail *pTITail)
4318 char *pFirstItem;
4319 sltg_ref_lookup_t *ref_lookup = NULL;
4321 if(pTIHeader->href_table != 0xffffffff) {
4322 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4323 pNameTable);
4326 pFirstItem = pBlk;
4328 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4329 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4331 heap_free(ref_lookup);
4335 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4336 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4337 const SLTG_TypeInfoTail *pTITail)
4339 char *pFirstItem;
4340 sltg_ref_lookup_t *ref_lookup = NULL;
4342 if(pTIHeader->href_table != 0xffffffff) {
4343 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4344 pNameTable);
4347 pFirstItem = pBlk;
4349 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4350 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4353 if (pTITail->funcs_off != 0xffff)
4354 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4356 heap_free(ref_lookup);
4358 if (TRACE_ON(typelib))
4359 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4362 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4363 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4364 const SLTG_TypeInfoTail *pTITail)
4366 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4369 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4370 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4371 const SLTG_TypeInfoTail *pTITail)
4373 WORD *pType;
4374 sltg_ref_lookup_t *ref_lookup = NULL;
4376 if (pTITail->simple_alias) {
4377 /* if simple alias, no more processing required */
4378 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4379 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4380 return;
4383 if(pTIHeader->href_table != 0xffffffff) {
4384 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4385 pNameTable);
4388 /* otherwise it is an offset to a type */
4389 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4391 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4392 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4394 heap_free(ref_lookup);
4397 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4398 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4399 const SLTG_TypeInfoTail *pTITail)
4401 sltg_ref_lookup_t *ref_lookup = NULL;
4402 if (pTIHeader->href_table != 0xffffffff)
4403 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4404 pNameTable);
4406 if (pTITail->vars_off != 0xffff)
4407 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4409 if (pTITail->funcs_off != 0xffff)
4410 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4412 if (pTITail->impls_off != 0xffff)
4413 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4415 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4416 * of dispinterface functions including the IDispatch ones, so
4417 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4418 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4420 heap_free(ref_lookup);
4421 if (TRACE_ON(typelib))
4422 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4425 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4426 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4427 const SLTG_TypeInfoTail *pTITail)
4429 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4432 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4433 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4434 const SLTG_TypeInfoTail *pTITail)
4436 sltg_ref_lookup_t *ref_lookup = NULL;
4437 if (pTIHeader->href_table != 0xffffffff)
4438 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4439 pNameTable);
4441 if (pTITail->vars_off != 0xffff)
4442 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4444 if (pTITail->funcs_off != 0xffff)
4445 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4446 heap_free(ref_lookup);
4447 if (TRACE_ON(typelib))
4448 dump_TypeInfo(pTI);
4451 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4452 manageable copy of it into this */
4453 typedef struct {
4454 WORD small_no;
4455 char *index_name;
4456 char *other_name;
4457 WORD res1a;
4458 WORD name_offs;
4459 WORD more_bytes;
4460 char *extra;
4461 WORD res20;
4462 DWORD helpcontext;
4463 WORD res26;
4464 GUID uuid;
4465 } SLTG_InternalOtherTypeInfo;
4467 /****************************************************************************
4468 * ITypeLib2_Constructor_SLTG
4470 * loading a SLTG typelib from an in-memory image
4472 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4474 ITypeLibImpl *pTypeLibImpl;
4475 SLTG_Header *pHeader;
4476 SLTG_BlkEntry *pBlkEntry;
4477 SLTG_Magic *pMagic;
4478 SLTG_Index *pIndex;
4479 SLTG_Pad9 *pPad9;
4480 LPVOID pBlk, pFirstBlk;
4481 SLTG_LibBlk *pLibBlk;
4482 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4483 char *pAfterOTIBlks = NULL;
4484 char *pNameTable, *ptr;
4485 int i;
4486 DWORD len, order;
4487 ITypeInfoImpl **ppTypeInfoImpl;
4489 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4492 pTypeLibImpl = TypeLibImpl_Constructor();
4493 if (!pTypeLibImpl) return NULL;
4495 pHeader = pLib;
4497 TRACE_(typelib)("header:\n");
4498 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4499 pHeader->nrOfFileBlks );
4500 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4501 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4502 pHeader->SLTG_magic);
4503 return NULL;
4506 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4507 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4509 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4510 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4512 /* Next we have a magic block */
4513 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4515 /* Let's see if we're still in sync */
4516 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4517 sizeof(SLTG_COMPOBJ_MAGIC))) {
4518 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4519 return NULL;
4521 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4522 sizeof(SLTG_DIR_MAGIC))) {
4523 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4524 return NULL;
4527 pIndex = (SLTG_Index*)(pMagic+1);
4529 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4531 pFirstBlk = pPad9 + 1;
4533 /* We'll set up a ptr to the main library block, which is the last one. */
4535 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4536 pBlkEntry[order].next != 0;
4537 order = pBlkEntry[order].next - 1, i++) {
4538 pBlk = (char*)pBlk + pBlkEntry[order].len;
4540 pLibBlk = pBlk;
4542 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4544 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4545 interspersed */
4547 len += 0x40;
4549 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4551 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4554 ptr = (char*)pLibBlk + len;
4556 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4557 WORD w, extra;
4558 len = 0;
4560 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4562 w = *(WORD*)(ptr + 2);
4563 if(w != 0xffff) {
4564 len += w;
4565 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4566 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4567 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4569 w = *(WORD*)(ptr + 4 + len);
4570 if(w != 0xffff) {
4571 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4572 len += w;
4573 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4574 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4575 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4577 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4578 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4579 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4580 if(extra) {
4581 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4582 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4583 len += extra;
4585 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4586 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4587 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4588 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4589 len += sizeof(SLTG_OtherTypeInfo);
4590 ptr += len;
4593 pAfterOTIBlks = ptr;
4595 /* Skip this WORD and get the next DWORD */
4596 len = *(DWORD*)(pAfterOTIBlks + 2);
4598 /* Now add this to pLibBLk look at what we're pointing at and
4599 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4600 dust and we should be pointing at the beginning of the name
4601 table */
4603 pNameTable = (char*)pLibBlk + len;
4605 switch(*(WORD*)pNameTable) {
4606 case 0xffff:
4607 break;
4608 case 0x0200:
4609 pNameTable += 0x20;
4610 break;
4611 default:
4612 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4613 break;
4616 pNameTable += 0x216;
4618 pNameTable += 2;
4620 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4622 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4625 /* Hopefully we now have enough ptrs set up to actually read in
4626 some TypeInfos. It's not clear which order to do them in, so
4627 I'll just follow the links along the BlkEntry chain and read
4628 them in the order in which they are in the file */
4630 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4631 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4633 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4634 pBlkEntry[order].next != 0;
4635 order = pBlkEntry[order].next - 1, i++) {
4637 SLTG_TypeInfoHeader *pTIHeader;
4638 SLTG_TypeInfoTail *pTITail;
4639 SLTG_MemberHeader *pMemHeader;
4641 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4642 FIXME_(typelib)("Index strings don't match\n");
4643 heap_free(pOtherTypeInfoBlks);
4644 return NULL;
4647 pTIHeader = pBlk;
4648 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4649 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4650 heap_free(pOtherTypeInfoBlks);
4651 return NULL;
4653 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4654 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4655 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4657 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4658 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4659 (*ppTypeInfoImpl)->index = i;
4660 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4661 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4662 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4663 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4664 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4665 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4666 (*ppTypeInfoImpl)->wTypeFlags =
4667 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4669 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4670 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4672 if((pTIHeader->typeflags1 & 7) != 2)
4673 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4674 if(pTIHeader->typeflags3 != 2)
4675 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4677 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4678 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4679 typekind_desc[pTIHeader->typekind],
4680 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4681 (*ppTypeInfoImpl)->wTypeFlags);
4683 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4685 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4687 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4688 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4689 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4691 switch(pTIHeader->typekind) {
4692 case TKIND_ENUM:
4693 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4694 pTIHeader, pTITail);
4695 break;
4697 case TKIND_RECORD:
4698 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4699 pTIHeader, pTITail);
4700 break;
4702 case TKIND_INTERFACE:
4703 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4704 pTIHeader, pTITail);
4705 break;
4707 case TKIND_COCLASS:
4708 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4709 pTIHeader, pTITail);
4710 break;
4712 case TKIND_ALIAS:
4713 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4714 pTIHeader, pTITail);
4715 break;
4717 case TKIND_DISPATCH:
4718 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4719 pTIHeader, pTITail);
4720 break;
4722 case TKIND_MODULE:
4723 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4724 pTIHeader, pTITail);
4725 break;
4727 default:
4728 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4729 break;
4733 /* could get cFuncs, cVars and cImplTypes from here
4734 but we've already set those */
4735 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4736 X(06);
4737 X(16);
4738 X(18);
4739 X(1a);
4740 X(1e);
4741 X(24);
4742 X(26);
4743 X(2a);
4744 X(2c);
4745 X(2e);
4746 X(30);
4747 X(32);
4748 X(34);
4749 #undef X
4750 ++ppTypeInfoImpl;
4751 pBlk = (char*)pBlk + pBlkEntry[order].len;
4754 if(i != pTypeLibImpl->TypeInfoCount) {
4755 FIXME("Somehow processed %d TypeInfos\n", i);
4756 heap_free(pOtherTypeInfoBlks);
4757 return NULL;
4760 heap_free(pOtherTypeInfoBlks);
4761 return &pTypeLibImpl->ITypeLib2_iface;
4764 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4766 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4768 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4770 if(IsEqualIID(riid, &IID_IUnknown) ||
4771 IsEqualIID(riid,&IID_ITypeLib)||
4772 IsEqualIID(riid,&IID_ITypeLib2))
4774 *ppv = &This->ITypeLib2_iface;
4776 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4777 IsEqualIID(riid, &IID_ICreateTypeLib2))
4779 *ppv = &This->ICreateTypeLib2_iface;
4781 else
4783 *ppv = NULL;
4784 TRACE("-- Interface: E_NOINTERFACE\n");
4785 return E_NOINTERFACE;
4788 IUnknown_AddRef((IUnknown*)*ppv);
4789 return S_OK;
4792 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4794 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4795 ULONG ref = InterlockedIncrement(&This->ref);
4797 TRACE("(%p) ref=%u\n", This, ref);
4799 return ref;
4802 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4804 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4805 ULONG ref = InterlockedDecrement(&This->ref);
4807 TRACE("(%p) ref=%u\n",This, ref);
4809 if (!ref)
4811 TLBImpLib *pImpLib, *pImpLibNext;
4812 TLBRefType *ref_type;
4813 TLBString *tlbstr, *tlbstr_next;
4814 TLBGuid *tlbguid, *tlbguid_next;
4815 void *cursor2;
4816 int i;
4818 /* remove cache entry */
4819 if(This->path)
4821 TRACE("removing from cache list\n");
4822 EnterCriticalSection(&cache_section);
4823 if(This->entry.next)
4824 list_remove(&This->entry);
4825 LeaveCriticalSection(&cache_section);
4826 heap_free(This->path);
4828 TRACE(" destroying ITypeLib(%p)\n",This);
4830 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4831 list_remove(&tlbstr->entry);
4832 SysFreeString(tlbstr->str);
4833 heap_free(tlbstr);
4836 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4837 list_remove(&tlbstr->entry);
4838 SysFreeString(tlbstr->str);
4839 heap_free(tlbstr);
4842 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4843 list_remove(&tlbguid->entry);
4844 heap_free(tlbguid);
4847 TLB_FreeCustData(&This->custdata_list);
4849 for (i = 0; i < This->ctTypeDesc; i++)
4850 if (This->pTypeDesc[i].vt == VT_CARRAY)
4851 heap_free(This->pTypeDesc[i].u.lpadesc);
4853 heap_free(This->pTypeDesc);
4855 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4857 if (pImpLib->pImpTypeLib)
4858 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4859 SysFreeString(pImpLib->name);
4861 list_remove(&pImpLib->entry);
4862 heap_free(pImpLib);
4865 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4867 list_remove(&ref_type->entry);
4868 heap_free(ref_type);
4871 for (i = 0; i < This->TypeInfoCount; ++i){
4872 heap_free(This->typeinfos[i]->tdescAlias);
4873 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4875 heap_free(This->typeinfos);
4876 heap_free(This);
4877 return 0;
4880 return ref;
4883 /* ITypeLib::GetTypeInfoCount
4885 * Returns the number of type descriptions in the type library
4887 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4889 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4890 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4891 return This->TypeInfoCount;
4894 /* ITypeLib::GetTypeInfo
4896 * retrieves the specified type description in the library.
4898 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4899 ITypeLib2 *iface,
4900 UINT index,
4901 ITypeInfo **ppTInfo)
4903 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4905 TRACE("%p %u %p\n", This, index, ppTInfo);
4907 if(!ppTInfo)
4908 return E_INVALIDARG;
4910 if(index >= This->TypeInfoCount)
4911 return TYPE_E_ELEMENTNOTFOUND;
4913 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4914 ITypeInfo_AddRef(*ppTInfo);
4916 return S_OK;
4920 /* ITypeLibs::GetTypeInfoType
4922 * Retrieves the type of a type description.
4924 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4925 ITypeLib2 *iface,
4926 UINT index,
4927 TYPEKIND *pTKind)
4929 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4931 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4933 if(!pTKind)
4934 return E_INVALIDARG;
4936 if(index >= This->TypeInfoCount)
4937 return TYPE_E_ELEMENTNOTFOUND;
4939 *pTKind = This->typeinfos[index]->typekind;
4941 return S_OK;
4944 /* ITypeLib::GetTypeInfoOfGuid
4946 * Retrieves the type description that corresponds to the specified GUID.
4949 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4950 ITypeLib2 *iface,
4951 REFGUID guid,
4952 ITypeInfo **ppTInfo)
4954 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4955 int i;
4957 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4959 for(i = 0; i < This->TypeInfoCount; ++i){
4960 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4961 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4962 ITypeInfo_AddRef(*ppTInfo);
4963 return S_OK;
4967 return TYPE_E_ELEMENTNOTFOUND;
4970 /* ITypeLib::GetLibAttr
4972 * Retrieves the structure that contains the library's attributes.
4975 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4976 ITypeLib2 *iface,
4977 LPTLIBATTR *attr)
4979 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4981 TRACE("(%p, %p)\n", This, attr);
4983 if (!attr) return E_INVALIDARG;
4985 *attr = heap_alloc(sizeof(**attr));
4986 if (!*attr) return E_OUTOFMEMORY;
4988 (*attr)->guid = *TLB_get_guid_null(This->guid);
4989 (*attr)->lcid = This->set_lcid;
4990 (*attr)->syskind = This->syskind;
4991 (*attr)->wMajorVerNum = This->ver_major;
4992 (*attr)->wMinorVerNum = This->ver_minor;
4993 (*attr)->wLibFlags = This->libflags;
4995 return S_OK;
4998 /* ITypeLib::GetTypeComp
5000 * Enables a client compiler to bind to a library's types, variables,
5001 * constants, and global functions.
5004 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
5005 ITypeLib2 *iface,
5006 ITypeComp **ppTComp)
5008 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5010 TRACE("(%p)->(%p)\n",This,ppTComp);
5011 *ppTComp = &This->ITypeComp_iface;
5012 ITypeComp_AddRef(*ppTComp);
5014 return S_OK;
5017 /* ITypeLib::GetDocumentation
5019 * Retrieves the library's documentation string, the complete Help file name
5020 * and path, and the context identifier for the library Help topic in the Help
5021 * file.
5023 * On a successful return all non-null BSTR pointers will have been set,
5024 * possibly to NULL.
5026 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
5027 ITypeLib2 *iface,
5028 INT index,
5029 BSTR *pBstrName,
5030 BSTR *pBstrDocString,
5031 DWORD *pdwHelpContext,
5032 BSTR *pBstrHelpFile)
5034 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5035 HRESULT result = E_INVALIDARG;
5036 ITypeInfo *pTInfo;
5038 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
5039 This, index,
5040 pBstrName, pBstrDocString,
5041 pdwHelpContext, pBstrHelpFile);
5043 if(index<0)
5045 /* documentation for the typelib */
5046 if(pBstrName)
5048 if (This->Name)
5050 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
5051 goto memerr1;
5053 else
5054 *pBstrName = NULL;
5056 if(pBstrDocString)
5058 if (This->DocString)
5060 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
5061 goto memerr2;
5063 else
5064 *pBstrDocString = NULL;
5066 if(pdwHelpContext)
5068 *pdwHelpContext = This->dwHelpContext;
5070 if(pBstrHelpFile)
5072 if (This->HelpFile)
5074 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5075 goto memerr3;
5077 else
5078 *pBstrHelpFile = NULL;
5081 result = S_OK;
5083 else
5085 /* for a typeinfo */
5086 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5088 if(SUCCEEDED(result))
5090 result = ITypeInfo_GetDocumentation(pTInfo,
5091 MEMBERID_NIL,
5092 pBstrName,
5093 pBstrDocString,
5094 pdwHelpContext, pBstrHelpFile);
5096 ITypeInfo_Release(pTInfo);
5099 return result;
5100 memerr3:
5101 if (pBstrDocString) SysFreeString (*pBstrDocString);
5102 memerr2:
5103 if (pBstrName) SysFreeString (*pBstrName);
5104 memerr1:
5105 return STG_E_INSUFFICIENTMEMORY;
5108 /* ITypeLib::IsName
5110 * Indicates whether a passed-in string contains the name of a type or member
5111 * described in the library.
5114 static HRESULT WINAPI ITypeLib2_fnIsName(
5115 ITypeLib2 *iface,
5116 LPOLESTR szNameBuf,
5117 ULONG lHashVal,
5118 BOOL *pfName)
5120 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5121 int tic;
5122 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5124 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5125 pfName);
5127 *pfName=TRUE;
5128 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5129 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5130 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5131 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5132 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5133 int pc;
5134 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5135 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5136 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5137 goto ITypeLib2_fnIsName_exit;
5140 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
5141 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5142 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5146 *pfName=FALSE;
5148 ITypeLib2_fnIsName_exit:
5149 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5150 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5152 return S_OK;
5155 /* ITypeLib::FindName
5157 * Finds occurrences of a type description in a type library. This may be used
5158 * to quickly verify that a name exists in a type library.
5161 static HRESULT WINAPI ITypeLib2_fnFindName(
5162 ITypeLib2 *iface,
5163 LPOLESTR name,
5164 ULONG hash,
5165 ITypeInfo **ppTInfo,
5166 MEMBERID *memid,
5167 UINT16 *found)
5169 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5170 int tic;
5171 UINT count = 0;
5172 UINT len;
5174 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5176 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5177 return E_INVALIDARG;
5179 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5180 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
5181 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5182 TLBVarDesc *var;
5183 UINT fdc;
5185 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
5186 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5187 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5188 int pc;
5190 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
5191 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
5192 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
5193 goto ITypeLib2_fnFindName_exit;
5197 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
5198 if (var)
5199 goto ITypeLib2_fnFindName_exit;
5201 continue;
5202 ITypeLib2_fnFindName_exit:
5203 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5204 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5205 count++;
5207 TRACE("found %d typeinfos\n", count);
5209 *found = count;
5211 return S_OK;
5214 /* ITypeLib::ReleaseTLibAttr
5216 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5219 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5220 ITypeLib2 *iface,
5221 TLIBATTR *pTLibAttr)
5223 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5224 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5225 heap_free(pTLibAttr);
5228 /* ITypeLib2::GetCustData
5230 * gets the custom data
5232 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5233 ITypeLib2 * iface,
5234 REFGUID guid,
5235 VARIANT *pVarVal)
5237 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5238 TLBCustData *pCData;
5240 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5242 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5243 if(!pCData)
5244 return TYPE_E_ELEMENTNOTFOUND;
5246 VariantInit(pVarVal);
5247 VariantCopy(pVarVal, &pCData->data);
5249 return S_OK;
5252 /* ITypeLib2::GetLibStatistics
5254 * Returns statistics about a type library that are required for efficient
5255 * sizing of hash tables.
5258 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5259 ITypeLib2 * iface,
5260 ULONG *pcUniqueNames,
5261 ULONG *pcchUniqueNames)
5263 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5265 FIXME("(%p): stub!\n", This);
5267 if(pcUniqueNames) *pcUniqueNames=1;
5268 if(pcchUniqueNames) *pcchUniqueNames=1;
5269 return S_OK;
5272 /* ITypeLib2::GetDocumentation2
5274 * Retrieves the library's documentation string, the complete Help file name
5275 * and path, the localization context to use, and the context ID for the
5276 * library Help topic in the Help file.
5279 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5280 ITypeLib2 * iface,
5281 INT index,
5282 LCID lcid,
5283 BSTR *pbstrHelpString,
5284 DWORD *pdwHelpStringContext,
5285 BSTR *pbstrHelpStringDll)
5287 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5288 HRESULT result;
5289 ITypeInfo *pTInfo;
5291 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5293 /* the help string should be obtained from the helpstringdll,
5294 * using the _DLLGetDocumentation function, based on the supplied
5295 * lcid. Nice to do sometime...
5297 if(index<0)
5299 /* documentation for the typelib */
5300 if(pbstrHelpString)
5301 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5302 if(pdwHelpStringContext)
5303 *pdwHelpStringContext=This->dwHelpContext;
5304 if(pbstrHelpStringDll)
5305 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5307 result = S_OK;
5309 else
5311 /* for a typeinfo */
5312 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5314 if(SUCCEEDED(result))
5316 ITypeInfo2 * pTInfo2;
5317 result = ITypeInfo_QueryInterface(pTInfo,
5318 &IID_ITypeInfo2,
5319 (LPVOID*) &pTInfo2);
5321 if(SUCCEEDED(result))
5323 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5324 MEMBERID_NIL,
5325 lcid,
5326 pbstrHelpString,
5327 pdwHelpStringContext,
5328 pbstrHelpStringDll);
5330 ITypeInfo2_Release(pTInfo2);
5333 ITypeInfo_Release(pTInfo);
5336 return result;
5339 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5341 TLBCustData *pCData;
5342 unsigned int ct;
5343 CUSTDATAITEM *cdi;
5345 ct = list_count(custdata_list);
5347 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5348 if(!pCustData->prgCustData)
5349 return E_OUTOFMEMORY;
5351 pCustData->cCustData = ct;
5353 cdi = pCustData->prgCustData;
5354 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5355 cdi->guid = *TLB_get_guid_null(pCData->guid);
5356 VariantCopy(&cdi->varValue, &pCData->data);
5357 ++cdi;
5360 return S_OK;
5364 /* ITypeLib2::GetAllCustData
5366 * Gets all custom data items for the library.
5369 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5370 ITypeLib2 * iface,
5371 CUSTDATA *pCustData)
5373 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5374 TRACE("(%p)->(%p)\n", This, pCustData);
5375 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5378 static const ITypeLib2Vtbl tlbvt = {
5379 ITypeLib2_fnQueryInterface,
5380 ITypeLib2_fnAddRef,
5381 ITypeLib2_fnRelease,
5382 ITypeLib2_fnGetTypeInfoCount,
5383 ITypeLib2_fnGetTypeInfo,
5384 ITypeLib2_fnGetTypeInfoType,
5385 ITypeLib2_fnGetTypeInfoOfGuid,
5386 ITypeLib2_fnGetLibAttr,
5387 ITypeLib2_fnGetTypeComp,
5388 ITypeLib2_fnGetDocumentation,
5389 ITypeLib2_fnIsName,
5390 ITypeLib2_fnFindName,
5391 ITypeLib2_fnReleaseTLibAttr,
5393 ITypeLib2_fnGetCustData,
5394 ITypeLib2_fnGetLibStatistics,
5395 ITypeLib2_fnGetDocumentation2,
5396 ITypeLib2_fnGetAllCustData
5400 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5402 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5404 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5407 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5409 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5411 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5414 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5416 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5418 return ITypeLib2_Release(&This->ITypeLib2_iface);
5421 static HRESULT WINAPI ITypeLibComp_fnBind(
5422 ITypeComp * iface,
5423 OLECHAR * szName,
5424 ULONG lHash,
5425 WORD wFlags,
5426 ITypeInfo ** ppTInfo,
5427 DESCKIND * pDescKind,
5428 BINDPTR * pBindPtr)
5430 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5431 BOOL typemismatch = FALSE;
5432 int i;
5434 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5436 *pDescKind = DESCKIND_NONE;
5437 pBindPtr->lptcomp = NULL;
5438 *ppTInfo = NULL;
5440 for(i = 0; i < This->TypeInfoCount; ++i){
5441 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5442 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5444 /* FIXME: check wFlags here? */
5445 /* FIXME: we should use a hash table to look this info up using lHash
5446 * instead of an O(n) search */
5447 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5448 (pTypeInfo->typekind == TKIND_MODULE))
5450 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5452 *pDescKind = DESCKIND_TYPECOMP;
5453 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5454 ITypeComp_AddRef(pBindPtr->lptcomp);
5455 TRACE("module or enum: %s\n", debugstr_w(szName));
5456 return S_OK;
5460 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5461 (pTypeInfo->typekind == TKIND_ENUM))
5463 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5464 HRESULT hr;
5466 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5467 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5469 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5470 return S_OK;
5472 else if (hr == TYPE_E_TYPEMISMATCH)
5473 typemismatch = TRUE;
5476 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5477 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5479 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5480 HRESULT hr;
5481 ITypeInfo *subtypeinfo;
5482 BINDPTR subbindptr;
5483 DESCKIND subdesckind;
5485 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5486 &subtypeinfo, &subdesckind, &subbindptr);
5487 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5489 TYPEDESC tdesc_appobject;
5490 const VARDESC vardesc_appobject =
5492 -2, /* memid */
5493 NULL, /* lpstrSchema */
5495 0 /* oInst */
5498 /* ELEMDESC */
5500 /* TYPEDESC */
5502 &tdesc_appobject
5504 VT_PTR
5507 0, /* wVarFlags */
5508 VAR_STATIC /* varkind */
5511 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5512 tdesc_appobject.vt = VT_USERDEFINED;
5514 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5516 /* cleanup things filled in by Bind call so we can put our
5517 * application object data in there instead */
5518 switch (subdesckind)
5520 case DESCKIND_FUNCDESC:
5521 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5522 break;
5523 case DESCKIND_VARDESC:
5524 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5525 break;
5526 default:
5527 break;
5529 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5531 if (pTypeInfo->hreftype == -1)
5532 FIXME("no hreftype for interface %p\n", pTypeInfo);
5534 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5535 if (FAILED(hr))
5536 return hr;
5538 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5539 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5540 ITypeInfo_AddRef(*ppTInfo);
5541 return S_OK;
5543 else if (hr == TYPE_E_TYPEMISMATCH)
5544 typemismatch = TRUE;
5548 if (typemismatch)
5550 TRACE("type mismatch %s\n", debugstr_w(szName));
5551 return TYPE_E_TYPEMISMATCH;
5553 else
5555 TRACE("name not found %s\n", debugstr_w(szName));
5556 return S_OK;
5560 static HRESULT WINAPI ITypeLibComp_fnBindType(
5561 ITypeComp * iface,
5562 OLECHAR * szName,
5563 ULONG lHash,
5564 ITypeInfo ** ppTInfo,
5565 ITypeComp ** ppTComp)
5567 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5568 ITypeInfoImpl *info;
5570 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5572 if(!szName || !ppTInfo || !ppTComp)
5573 return E_INVALIDARG;
5575 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5576 if(!info){
5577 *ppTInfo = NULL;
5578 *ppTComp = NULL;
5579 return S_OK;
5582 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5583 ITypeInfo_AddRef(*ppTInfo);
5584 *ppTComp = &info->ITypeComp_iface;
5585 ITypeComp_AddRef(*ppTComp);
5587 return S_OK;
5590 static const ITypeCompVtbl tlbtcvt =
5593 ITypeLibComp_fnQueryInterface,
5594 ITypeLibComp_fnAddRef,
5595 ITypeLibComp_fnRelease,
5597 ITypeLibComp_fnBind,
5598 ITypeLibComp_fnBindType
5601 /*================== ITypeInfo(2) Methods ===================================*/
5602 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5604 ITypeInfoImpl *pTypeInfoImpl;
5606 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5607 if (pTypeInfoImpl)
5609 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5610 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5611 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5612 pTypeInfoImpl->ref = 0;
5613 pTypeInfoImpl->hreftype = -1;
5614 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5615 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5616 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5617 list_init(pTypeInfoImpl->pcustdata_list);
5619 TRACE("(%p)\n", pTypeInfoImpl);
5620 return pTypeInfoImpl;
5623 /* ITypeInfo::QueryInterface
5625 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5626 ITypeInfo2 *iface,
5627 REFIID riid,
5628 VOID **ppvObject)
5630 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5632 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5634 *ppvObject=NULL;
5635 if(IsEqualIID(riid, &IID_IUnknown) ||
5636 IsEqualIID(riid,&IID_ITypeInfo)||
5637 IsEqualIID(riid,&IID_ITypeInfo2))
5638 *ppvObject = This;
5639 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5640 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5641 *ppvObject = &This->ICreateTypeInfo2_iface;
5643 if(*ppvObject){
5644 ITypeInfo2_AddRef(iface);
5645 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5646 return S_OK;
5648 TRACE("-- Interface: E_NOINTERFACE\n");
5649 return E_NOINTERFACE;
5652 /* ITypeInfo::AddRef
5654 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5656 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5657 ULONG ref = InterlockedIncrement(&This->ref);
5659 TRACE("(%p)->ref is %u\n",This, ref);
5661 if (ref == 1 /* incremented from 0 */)
5662 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5664 return ref;
5667 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5669 UINT i;
5671 TRACE("destroying ITypeInfo(%p)\n",This);
5673 for (i = 0; i < This->cFuncs; ++i)
5675 int j;
5676 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5677 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5679 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5680 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5681 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5682 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5684 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5685 heap_free(pFInfo->pParamDesc);
5686 TLB_FreeCustData(&pFInfo->custdata_list);
5688 heap_free(This->funcdescs);
5690 for(i = 0; i < This->cVars; ++i)
5692 TLBVarDesc *pVInfo = &This->vardescs[i];
5693 if (pVInfo->vardesc_create) {
5694 TLB_FreeVarDesc(pVInfo->vardesc_create);
5695 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5696 VariantClear(pVInfo->vardesc.u.lpvarValue);
5697 heap_free(pVInfo->vardesc.u.lpvarValue);
5699 TLB_FreeCustData(&pVInfo->custdata_list);
5701 heap_free(This->vardescs);
5703 if(This->impltypes){
5704 for (i = 0; i < This->cImplTypes; ++i){
5705 TLBImplType *pImpl = &This->impltypes[i];
5706 TLB_FreeCustData(&pImpl->custdata_list);
5708 heap_free(This->impltypes);
5711 TLB_FreeCustData(&This->custdata_list);
5713 heap_free(This);
5716 /* ITypeInfo::Release
5718 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5720 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5721 ULONG ref = InterlockedDecrement(&This->ref);
5723 TRACE("(%p)->(%u)\n",This, ref);
5725 if (!ref)
5727 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5728 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5729 if (not_attached_to_typelib)
5730 heap_free(This);
5731 /* otherwise This will be freed when typelib is freed */
5734 return ref;
5737 /* ITypeInfo::GetTypeAttr
5739 * Retrieves a TYPEATTR structure that contains the attributes of the type
5740 * description.
5743 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5744 LPTYPEATTR *ppTypeAttr)
5746 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5747 SIZE_T size;
5749 TRACE("(%p)\n",This);
5751 size = sizeof(**ppTypeAttr);
5752 if (This->typekind == TKIND_ALIAS && This->tdescAlias)
5753 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5755 *ppTypeAttr = heap_alloc(size);
5756 if (!*ppTypeAttr)
5757 return E_OUTOFMEMORY;
5759 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5760 (*ppTypeAttr)->lcid = This->lcid;
5761 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5762 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5763 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5764 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5765 (*ppTypeAttr)->typekind = This->typekind;
5766 (*ppTypeAttr)->cFuncs = This->cFuncs;
5767 (*ppTypeAttr)->cVars = This->cVars;
5768 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5769 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5770 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5771 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5772 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5773 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5774 (*ppTypeAttr)->idldescType = This->idldescType;
5776 if (This->tdescAlias)
5777 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5778 This->tdescAlias, *ppTypeAttr + 1);
5779 else{
5780 (*ppTypeAttr)->tdescAlias.vt = VT_EMPTY;
5781 (*ppTypeAttr)->tdescAlias.u.lptdesc = NULL;
5784 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5785 /* This should include all the inherited funcs */
5786 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5787 /* This is always the size of IDispatch's vtbl */
5788 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5789 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5791 return S_OK;
5794 /* ITypeInfo::GetTypeComp
5796 * Retrieves the ITypeComp interface for the type description, which enables a
5797 * client compiler to bind to the type description's members.
5800 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5801 ITypeComp * *ppTComp)
5803 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5805 TRACE("(%p)->(%p)\n", This, ppTComp);
5807 *ppTComp = &This->ITypeComp_iface;
5808 ITypeComp_AddRef(*ppTComp);
5809 return S_OK;
5812 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5814 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5815 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5816 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5817 return size;
5820 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5822 *dest = *src;
5823 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5824 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5826 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5827 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5828 *buffer += sizeof(PARAMDESCEX);
5829 *pparamdescex_dest = *pparamdescex_src;
5830 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5831 VariantInit(&pparamdescex_dest->varDefaultValue);
5832 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5833 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5835 else
5836 dest->u.paramdesc.pparamdescex = NULL;
5837 return S_OK;
5840 static HRESULT TLB_SanitizeBSTR(BSTR str)
5842 UINT len = SysStringLen(str), i;
5843 for (i = 0; i < len; ++i)
5844 if (str[i] > 0x7f)
5845 str[i] = '?';
5846 return S_OK;
5849 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5851 if (V_VT(var) == VT_INT)
5852 return VariantChangeType(var, var, 0, VT_I4);
5853 else if (V_VT(var) == VT_UINT)
5854 return VariantChangeType(var, var, 0, VT_UI4);
5855 else if (V_VT(var) == VT_BSTR)
5856 return TLB_SanitizeBSTR(V_BSTR(var));
5858 return S_OK;
5861 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5863 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5864 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5867 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5869 FUNCDESC *dest;
5870 char *buffer;
5871 SIZE_T size = sizeof(*src);
5872 SHORT i;
5873 HRESULT hr;
5875 size += sizeof(*src->lprgscode) * src->cScodes;
5876 size += TLB_SizeElemDesc(&src->elemdescFunc);
5877 for (i = 0; i < src->cParams; i++)
5879 size += sizeof(ELEMDESC);
5880 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5883 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5884 if (!dest) return E_OUTOFMEMORY;
5886 *dest = *src;
5887 if (dispinterface) /* overwrite funckind */
5888 dest->funckind = FUNC_DISPATCH;
5889 buffer = (char *)(dest + 1);
5891 dest->oVft = dest->oVft & 0xFFFC;
5893 if (dest->cScodes) {
5894 dest->lprgscode = (SCODE *)buffer;
5895 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5896 buffer += sizeof(*src->lprgscode) * src->cScodes;
5897 } else
5898 dest->lprgscode = NULL;
5900 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5901 if (FAILED(hr))
5903 SysFreeString((BSTR)dest);
5904 return hr;
5907 if (dest->cParams) {
5908 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5909 buffer += sizeof(ELEMDESC) * src->cParams;
5910 for (i = 0; i < src->cParams; i++)
5912 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5913 if (FAILED(hr))
5914 break;
5916 if (FAILED(hr))
5918 /* undo the above actions */
5919 for (i = i - 1; i >= 0; i--)
5920 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5921 TLB_FreeElemDesc(&dest->elemdescFunc);
5922 SysFreeString((BSTR)dest);
5923 return hr;
5925 } else
5926 dest->lprgelemdescParam = NULL;
5928 /* special treatment for dispinterfaces: this makes functions appear
5929 * to return their [retval] value when it is really returning an
5930 * HRESULT */
5931 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5933 if (dest->cParams &&
5934 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5936 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5937 if (elemdesc->tdesc.vt != VT_PTR)
5939 ERR("elemdesc should have started with VT_PTR instead of:\n");
5940 if (ERR_ON(ole))
5941 dump_ELEMDESC(elemdesc);
5942 return E_UNEXPECTED;
5945 /* copy last parameter to the return value. we are using a flat
5946 * buffer so there is no danger of leaking memory in
5947 * elemdescFunc */
5948 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5950 /* remove the last parameter */
5951 dest->cParams--;
5953 else
5954 /* otherwise this function is made to appear to have no return
5955 * value */
5956 dest->elemdescFunc.tdesc.vt = VT_VOID;
5960 *dest_ptr = dest;
5961 return S_OK;
5964 static void TLB_FreeVarDesc(VARDESC *var_desc)
5966 TLB_FreeElemDesc(&var_desc->elemdescVar);
5967 if (var_desc->varkind == VAR_CONST)
5968 VariantClear(var_desc->u.lpvarValue);
5969 SysFreeString((BSTR)var_desc);
5972 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5974 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5976 if (index >= This->cFuncs)
5977 return TYPE_E_ELEMENTNOTFOUND;
5979 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5980 return S_OK;
5983 /* internal function to make the inherited interfaces' methods appear
5984 * part of the interface */
5985 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5986 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5988 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5989 HRESULT hr;
5990 UINT implemented_funcs = 0;
5992 if (funcs)
5993 *funcs = 0;
5994 else
5995 *hrefoffset = DISPATCH_HREF_OFFSET;
5997 if(This->impltypes)
5999 ITypeInfo *pSubTypeInfo;
6000 UINT sub_funcs;
6002 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6003 if (FAILED(hr))
6004 return hr;
6006 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
6007 index,
6008 ppFuncDesc,
6009 &sub_funcs, hrefoffset);
6010 implemented_funcs += sub_funcs;
6011 ITypeInfo_Release(pSubTypeInfo);
6012 if (SUCCEEDED(hr))
6013 return hr;
6014 *hrefoffset += DISPATCH_HREF_OFFSET;
6017 if (funcs)
6018 *funcs = implemented_funcs + This->cFuncs;
6019 else
6020 *hrefoffset = 0;
6022 if (index < implemented_funcs)
6023 return E_INVALIDARG;
6024 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
6025 ppFuncDesc);
6028 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
6030 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
6031 while (TRUE)
6033 switch (pTypeDesc->vt)
6035 case VT_USERDEFINED:
6036 pTypeDesc->u.hreftype += hrefoffset;
6037 return;
6038 case VT_PTR:
6039 case VT_SAFEARRAY:
6040 pTypeDesc = pTypeDesc->u.lptdesc;
6041 break;
6042 case VT_CARRAY:
6043 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
6044 break;
6045 default:
6046 return;
6051 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
6053 SHORT i;
6054 for (i = 0; i < pFuncDesc->cParams; i++)
6055 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
6056 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
6059 /* ITypeInfo::GetFuncDesc
6061 * Retrieves the FUNCDESC structure that contains information about a
6062 * specified function.
6065 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
6066 LPFUNCDESC *ppFuncDesc)
6068 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6069 const FUNCDESC *internal_funcdesc;
6070 HRESULT hr;
6071 UINT hrefoffset = 0;
6073 TRACE("(%p) index %d\n", This, index);
6075 if (!ppFuncDesc)
6076 return E_INVALIDARG;
6078 if (This->needs_layout)
6079 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6081 if (This->typekind == TKIND_DISPATCH)
6082 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6083 &internal_funcdesc, NULL,
6084 &hrefoffset);
6085 else
6086 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6087 &internal_funcdesc);
6088 if (FAILED(hr))
6090 WARN("description for function %d not found\n", index);
6091 return hr;
6094 hr = TLB_AllocAndInitFuncDesc(
6095 internal_funcdesc,
6096 ppFuncDesc,
6097 This->typekind == TKIND_DISPATCH);
6099 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
6100 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6102 TRACE("-- 0x%08x\n", hr);
6103 return hr;
6106 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6108 VARDESC *dest;
6109 char *buffer;
6110 SIZE_T size = sizeof(*src);
6111 HRESULT hr;
6113 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6114 if (src->varkind == VAR_CONST)
6115 size += sizeof(VARIANT);
6116 size += TLB_SizeElemDesc(&src->elemdescVar);
6118 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6119 if (!dest) return E_OUTOFMEMORY;
6121 *dest = *src;
6122 buffer = (char *)(dest + 1);
6123 if (src->lpstrSchema)
6125 int len;
6126 dest->lpstrSchema = (LPOLESTR)buffer;
6127 len = strlenW(src->lpstrSchema);
6128 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6129 buffer += (len + 1) * sizeof(WCHAR);
6132 if (src->varkind == VAR_CONST)
6134 HRESULT hr;
6136 dest->u.lpvarValue = (VARIANT *)buffer;
6137 *dest->u.lpvarValue = *src->u.lpvarValue;
6138 buffer += sizeof(VARIANT);
6139 VariantInit(dest->u.lpvarValue);
6140 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6141 if (FAILED(hr))
6143 SysFreeString((BSTR)dest);
6144 return hr;
6147 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6148 if (FAILED(hr))
6150 if (src->varkind == VAR_CONST)
6151 VariantClear(dest->u.lpvarValue);
6152 SysFreeString((BSTR)dest);
6153 return hr;
6155 *dest_ptr = dest;
6156 return S_OK;
6159 /* ITypeInfo::GetVarDesc
6161 * Retrieves a VARDESC structure that describes the specified variable.
6164 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6165 LPVARDESC *ppVarDesc)
6167 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6168 const TLBVarDesc *pVDesc = &This->vardescs[index];
6170 TRACE("(%p) index %d\n", This, index);
6172 if(index >= This->cVars)
6173 return TYPE_E_ELEMENTNOTFOUND;
6175 if (This->needs_layout)
6176 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6178 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6181 /* ITypeInfo_GetNames
6183 * Retrieves the variable with the specified member ID (or the name of the
6184 * property or method and its parameters) that correspond to the specified
6185 * function ID.
6187 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6188 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6190 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6191 const TLBFuncDesc *pFDesc;
6192 const TLBVarDesc *pVDesc;
6193 int i;
6194 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6196 if(!rgBstrNames)
6197 return E_INVALIDARG;
6199 *pcNames = 0;
6201 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
6202 if(pFDesc)
6204 if(!cMaxNames || !pFDesc->Name)
6205 return S_OK;
6207 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6208 ++(*pcNames);
6210 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6211 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6212 return S_OK;
6213 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6214 ++(*pcNames);
6216 return S_OK;
6219 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
6220 if(pVDesc)
6222 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6223 *pcNames=1;
6225 else
6227 if(This->impltypes &&
6228 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
6229 /* recursive search */
6230 ITypeInfo *pTInfo;
6231 HRESULT result;
6232 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6233 if(SUCCEEDED(result))
6235 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6236 ITypeInfo_Release(pTInfo);
6237 return result;
6239 WARN("Could not search inherited interface!\n");
6241 else
6243 WARN("no names found\n");
6245 *pcNames=0;
6246 return TYPE_E_ELEMENTNOTFOUND;
6248 return S_OK;
6252 /* ITypeInfo::GetRefTypeOfImplType
6254 * If a type description describes a COM class, it retrieves the type
6255 * description of the implemented interface types. For an interface,
6256 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6257 * if any exist.
6260 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6261 ITypeInfo2 *iface,
6262 UINT index,
6263 HREFTYPE *pRefType)
6265 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6266 HRESULT hr = S_OK;
6268 TRACE("(%p) index %d\n", This, index);
6269 if (TRACE_ON(ole)) dump_TypeInfo(This);
6271 if(index==(UINT)-1)
6273 /* only valid on dual interfaces;
6274 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6277 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6279 *pRefType = -2;
6281 else
6283 hr = TYPE_E_ELEMENTNOTFOUND;
6286 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6288 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6289 *pRefType = This->pTypeLib->dispatch_href;
6291 else
6293 if(index >= This->cImplTypes)
6294 hr = TYPE_E_ELEMENTNOTFOUND;
6295 else{
6296 *pRefType = This->impltypes[index].hRef;
6297 if(This->typekind == TKIND_INTERFACE)
6298 *pRefType |= 0x2;
6302 if(TRACE_ON(ole))
6304 if(SUCCEEDED(hr))
6305 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6306 else
6307 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6310 return hr;
6313 /* ITypeInfo::GetImplTypeFlags
6315 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6316 * or base interface in a type description.
6318 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6319 UINT index, INT *pImplTypeFlags)
6321 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6323 TRACE("(%p) index %d\n", This, index);
6325 if(!pImplTypeFlags)
6326 return E_INVALIDARG;
6328 if(This->typekind == TKIND_DISPATCH && index == 0){
6329 *pImplTypeFlags = 0;
6330 return S_OK;
6333 if(index >= This->cImplTypes)
6334 return TYPE_E_ELEMENTNOTFOUND;
6336 *pImplTypeFlags = This->impltypes[index].implflags;
6338 return S_OK;
6341 /* GetIDsOfNames
6342 * Maps between member names and member IDs, and parameter names and
6343 * parameter IDs.
6345 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6346 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6348 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6349 const TLBVarDesc *pVDesc;
6350 HRESULT ret=S_OK;
6351 UINT i, fdc;
6353 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6354 cNames);
6356 /* init out parameters in case of failure */
6357 for (i = 0; i < cNames; i++)
6358 pMemId[i] = MEMBERID_NIL;
6360 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6361 int j;
6362 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6363 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6364 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6365 for(i=1; i < cNames; i++){
6366 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6367 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6368 break;
6369 if( j<pFDesc->funcdesc.cParams)
6370 pMemId[i]=j;
6371 else
6372 ret=DISP_E_UNKNOWNNAME;
6374 TRACE("-- 0x%08x\n", ret);
6375 return ret;
6378 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6379 if(pVDesc){
6380 if(cNames)
6381 *pMemId = pVDesc->vardesc.memid;
6382 return ret;
6384 /* not found, see if it can be found in an inherited interface */
6385 if(This->impltypes) {
6386 /* recursive search */
6387 ITypeInfo *pTInfo;
6388 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6389 if(SUCCEEDED(ret)){
6390 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6391 ITypeInfo_Release(pTInfo);
6392 return ret;
6394 WARN("Could not search inherited interface!\n");
6395 } else
6396 WARN("no names found\n");
6397 return DISP_E_UNKNOWNNAME;
6401 #ifdef __i386__
6403 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6404 __ASM_GLOBAL_FUNC( call_method,
6405 "pushl %ebp\n\t"
6406 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6407 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6408 "movl %esp,%ebp\n\t"
6409 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6410 "pushl %esi\n\t"
6411 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6412 "pushl %edi\n\t"
6413 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6414 "movl 12(%ebp),%edx\n\t"
6415 "movl %esp,%edi\n\t"
6416 "shll $2,%edx\n\t"
6417 "jz 1f\n\t"
6418 "subl %edx,%edi\n\t"
6419 "andl $~15,%edi\n\t"
6420 "movl %edi,%esp\n\t"
6421 "movl 12(%ebp),%ecx\n\t"
6422 "movl 16(%ebp),%esi\n\t"
6423 "cld\n\t"
6424 "rep; movsl\n"
6425 "1:\tcall *8(%ebp)\n\t"
6426 "subl %esp,%edi\n\t"
6427 "movl 20(%ebp),%ecx\n\t"
6428 "movl %edi,(%ecx)\n\t"
6429 "leal -8(%ebp),%esp\n\t"
6430 "popl %edi\n\t"
6431 __ASM_CFI(".cfi_same_value %edi\n\t")
6432 "popl %esi\n\t"
6433 __ASM_CFI(".cfi_same_value %esi\n\t")
6434 "popl %ebp\n\t"
6435 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6436 __ASM_CFI(".cfi_same_value %ebp\n\t")
6437 "ret" )
6439 /* same function but returning floating point */
6440 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6442 /* ITypeInfo::Invoke
6444 * Invokes a method, or accesses a property of an object, that implements the
6445 * interface described by the type description.
6447 DWORD
6448 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6449 DWORD res;
6450 int stack_offset;
6452 if (TRACE_ON(ole)) {
6453 int i;
6454 TRACE("Calling %p(",func);
6455 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6456 if (nrargs > 30) TRACE("...");
6457 TRACE(")\n");
6460 switch (callconv) {
6461 case CC_STDCALL:
6462 case CC_CDECL:
6463 res = call_method( func, nrargs, args, &stack_offset );
6464 break;
6465 default:
6466 FIXME("unsupported calling convention %d\n",callconv);
6467 res = -1;
6468 break;
6470 TRACE("returns %08x\n",res);
6471 return res;
6474 #elif defined(__x86_64__)
6476 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6477 __ASM_GLOBAL_FUNC( call_method,
6478 "pushq %rbp\n\t"
6479 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6480 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6481 "movq %rsp,%rbp\n\t"
6482 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6483 "pushq %rsi\n\t"
6484 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6485 "pushq %rdi\n\t"
6486 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6487 "movq %rcx,%rax\n\t"
6488 "movq $4,%rcx\n\t"
6489 "cmp %rcx,%rdx\n\t"
6490 "cmovgq %rdx,%rcx\n\t"
6491 "leaq 0(,%rcx,8),%rdx\n\t"
6492 "subq %rdx,%rsp\n\t"
6493 "andq $~15,%rsp\n\t"
6494 "movq %rsp,%rdi\n\t"
6495 "movq %r8,%rsi\n\t"
6496 "rep; movsq\n\t"
6497 "movq 0(%rsp),%rcx\n\t"
6498 "movq 8(%rsp),%rdx\n\t"
6499 "movq 16(%rsp),%r8\n\t"
6500 "movq 24(%rsp),%r9\n\t"
6501 "movq %rcx,%xmm0\n\t"
6502 "movq %rdx,%xmm1\n\t"
6503 "movq %r8,%xmm2\n\t"
6504 "movq %r9,%xmm3\n\t"
6505 "callq *%rax\n\t"
6506 "leaq -16(%rbp),%rsp\n\t"
6507 "popq %rdi\n\t"
6508 __ASM_CFI(".cfi_same_value %rdi\n\t")
6509 "popq %rsi\n\t"
6510 __ASM_CFI(".cfi_same_value %rsi\n\t")
6511 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6512 "popq %rbp\n\t"
6513 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6514 __ASM_CFI(".cfi_same_value %rbp\n\t")
6515 "ret")
6517 /* same function but returning floating point */
6518 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6520 #endif /* __x86_64__ */
6522 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6524 HRESULT hr = S_OK;
6525 ITypeInfo *tinfo2 = NULL;
6526 TYPEATTR *tattr = NULL;
6528 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6529 if (hr)
6531 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6532 "hr = 0x%08x\n",
6533 tdesc->u.hreftype, hr);
6534 return hr;
6536 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6537 if (hr)
6539 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6540 ITypeInfo_Release(tinfo2);
6541 return hr;
6544 switch (tattr->typekind)
6546 case TKIND_ENUM:
6547 *vt |= VT_I4;
6548 break;
6550 case TKIND_ALIAS:
6551 tdesc = &tattr->tdescAlias;
6552 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6553 break;
6555 case TKIND_INTERFACE:
6556 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6557 *vt |= VT_DISPATCH;
6558 else
6559 *vt |= VT_UNKNOWN;
6560 break;
6562 case TKIND_DISPATCH:
6563 *vt |= VT_DISPATCH;
6564 break;
6566 case TKIND_COCLASS:
6567 *vt |= VT_DISPATCH;
6568 break;
6570 case TKIND_RECORD:
6571 FIXME("TKIND_RECORD unhandled.\n");
6572 hr = E_NOTIMPL;
6573 break;
6575 case TKIND_UNION:
6576 FIXME("TKIND_UNION unhandled.\n");
6577 hr = E_NOTIMPL;
6578 break;
6580 default:
6581 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6582 hr = E_NOTIMPL;
6583 break;
6585 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6586 ITypeInfo_Release(tinfo2);
6587 return hr;
6590 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6592 HRESULT hr = S_OK;
6594 /* enforce only one level of pointer indirection */
6595 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6597 tdesc = tdesc->u.lptdesc;
6599 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6600 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6601 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6602 if ((tdesc->vt == VT_USERDEFINED) ||
6603 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6605 VARTYPE vt_userdefined = 0;
6606 const TYPEDESC *tdesc_userdefined = tdesc;
6607 if (tdesc->vt == VT_PTR)
6609 vt_userdefined = VT_BYREF;
6610 tdesc_userdefined = tdesc->u.lptdesc;
6612 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6613 if ((hr == S_OK) &&
6614 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6615 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6617 *vt |= vt_userdefined;
6618 return S_OK;
6621 *vt = VT_BYREF;
6624 switch (tdesc->vt)
6626 case VT_HRESULT:
6627 *vt |= VT_ERROR;
6628 break;
6629 case VT_USERDEFINED:
6630 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6631 break;
6632 case VT_VOID:
6633 case VT_CARRAY:
6634 case VT_PTR:
6635 case VT_LPSTR:
6636 case VT_LPWSTR:
6637 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6638 hr = DISP_E_BADVARTYPE;
6639 break;
6640 case VT_SAFEARRAY:
6641 *vt |= VT_ARRAY;
6642 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6643 break;
6644 case VT_INT:
6645 *vt |= VT_I4;
6646 break;
6647 case VT_UINT:
6648 *vt |= VT_UI4;
6649 break;
6650 default:
6651 *vt |= tdesc->vt;
6652 break;
6654 return hr;
6657 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6659 ITypeInfo *tinfo2;
6660 TYPEATTR *tattr;
6661 HRESULT hres;
6663 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6664 if(FAILED(hres))
6665 return hres;
6667 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6668 if(FAILED(hres)) {
6669 ITypeInfo_Release(tinfo2);
6670 return hres;
6673 switch(tattr->typekind) {
6674 case TKIND_ALIAS:
6675 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6676 break;
6678 case TKIND_INTERFACE:
6679 case TKIND_DISPATCH:
6680 *guid = tattr->guid;
6681 break;
6683 default:
6684 ERR("Unexpected typekind %d\n", tattr->typekind);
6685 hres = E_UNEXPECTED;
6688 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6689 ITypeInfo_Release(tinfo2);
6690 return hres;
6693 /***********************************************************************
6694 * DispCallFunc (OLEAUT32.@)
6696 * Invokes a function of the specified calling convention, passing the
6697 * specified arguments and returns the result.
6699 * PARAMS
6700 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6701 * oVft [I] The offset in the vtable. See notes.
6702 * cc [I] Calling convention of the function to call.
6703 * vtReturn [I] The return type of the function.
6704 * cActuals [I] Number of parameters.
6705 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6706 * prgpvarg [I] The arguments to pass.
6707 * pvargResult [O] The return value of the function. Can be NULL.
6709 * RETURNS
6710 * Success: S_OK.
6711 * Failure: HRESULT code.
6713 * NOTES
6714 * The HRESULT return value of this function is not affected by the return
6715 * value of the user supplied function, which is returned in pvargResult.
6717 * If pvInstance is NULL then a non-object function is to be called and oVft
6718 * is the address of the function to call.
6720 * The cc parameter can be one of the following values:
6721 *|CC_FASTCALL
6722 *|CC_CDECL
6723 *|CC_PASCAL
6724 *|CC_STDCALL
6725 *|CC_FPFASTCALL
6726 *|CC_SYSCALL
6727 *|CC_MPWCDECL
6728 *|CC_MPWPASCAL
6731 HRESULT WINAPI
6732 DispCallFunc(
6733 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6734 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6736 #ifdef __i386__
6737 int argspos, stack_offset;
6738 void *func;
6739 UINT i;
6740 DWORD *args;
6742 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6743 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6744 pvargResult, V_VT(pvargResult));
6746 if (cc != CC_STDCALL && cc != CC_CDECL)
6748 FIXME("unsupported calling convention %d\n",cc);
6749 return E_INVALIDARG;
6752 /* maximum size for an argument is sizeof(VARIANT) */
6753 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6755 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6756 argspos = 1;
6757 if (pvInstance)
6759 const FARPROC *vtable = *(FARPROC **)pvInstance;
6760 func = vtable[oVft/sizeof(void *)];
6761 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6763 else func = (void *)oVft;
6765 for (i = 0; i < cActuals; i++)
6767 VARIANT *arg = prgpvarg[i];
6769 switch (prgvt[i])
6771 case VT_EMPTY:
6772 break;
6773 case VT_I8:
6774 case VT_UI8:
6775 case VT_R8:
6776 case VT_DATE:
6777 case VT_CY:
6778 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6779 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6780 break;
6781 case VT_DECIMAL:
6782 case VT_VARIANT:
6783 memcpy( &args[argspos], arg, sizeof(*arg) );
6784 argspos += sizeof(*arg) / sizeof(DWORD);
6785 break;
6786 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6787 args[argspos++] = V_BOOL(arg);
6788 break;
6789 default:
6790 args[argspos++] = V_UI4(arg);
6791 break;
6793 TRACE("arg %u: type %d\n",i,prgvt[i]);
6794 dump_Variant(arg);
6797 switch (vtReturn)
6799 case VT_EMPTY:
6800 call_method( func, argspos - 1, args + 1, &stack_offset );
6801 break;
6802 case VT_R4:
6803 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6804 break;
6805 case VT_R8:
6806 case VT_DATE:
6807 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6808 break;
6809 case VT_DECIMAL:
6810 case VT_VARIANT:
6811 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6812 call_method( func, argspos, args, &stack_offset );
6813 break;
6814 case VT_I8:
6815 case VT_UI8:
6816 case VT_CY:
6817 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6818 break;
6819 case VT_HRESULT:
6820 WARN("invalid return type %u\n", vtReturn);
6821 heap_free( args );
6822 return E_INVALIDARG;
6823 default:
6824 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6825 break;
6827 heap_free( args );
6828 if (stack_offset && cc == CC_STDCALL)
6830 WARN( "stack pointer off by %d\n", stack_offset );
6831 return DISP_E_BADCALLEE;
6833 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6834 TRACE("retval: "); dump_Variant(pvargResult);
6835 return S_OK;
6837 #elif defined(__x86_64__)
6838 int argspos;
6839 UINT i;
6840 DWORD_PTR *args;
6841 void *func;
6843 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6844 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6845 pvargResult, V_VT(pvargResult));
6847 if (cc != CC_STDCALL && cc != CC_CDECL)
6849 FIXME("unsupported calling convention %d\n",cc);
6850 return E_INVALIDARG;
6853 /* maximum size for an argument is sizeof(DWORD_PTR) */
6854 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6856 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6857 argspos = 1;
6858 if (pvInstance)
6860 const FARPROC *vtable = *(FARPROC **)pvInstance;
6861 func = vtable[oVft/sizeof(void *)];
6862 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6864 else func = (void *)oVft;
6866 for (i = 0; i < cActuals; i++)
6868 VARIANT *arg = prgpvarg[i];
6870 switch (prgvt[i])
6872 case VT_DECIMAL:
6873 case VT_VARIANT:
6874 args[argspos++] = (ULONG_PTR)arg;
6875 break;
6876 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6877 args[argspos++] = V_BOOL(arg);
6878 break;
6879 default:
6880 args[argspos++] = V_UI8(arg);
6881 break;
6883 TRACE("arg %u: type %d\n",i,prgvt[i]);
6884 dump_Variant(arg);
6887 switch (vtReturn)
6889 case VT_R4:
6890 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6891 break;
6892 case VT_R8:
6893 case VT_DATE:
6894 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6895 break;
6896 case VT_DECIMAL:
6897 case VT_VARIANT:
6898 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6899 call_method( func, argspos, args );
6900 break;
6901 case VT_HRESULT:
6902 WARN("invalid return type %u\n", vtReturn);
6903 heap_free( args );
6904 return E_INVALIDARG;
6905 default:
6906 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6907 break;
6909 heap_free( args );
6910 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6911 TRACE("retval: "); dump_Variant(pvargResult);
6912 return S_OK;
6914 #else
6915 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6916 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6917 return E_NOTIMPL;
6918 #endif
6921 static inline BOOL func_restricted( const FUNCDESC *desc )
6923 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6926 #define INVBUF_ELEMENT_SIZE \
6927 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6928 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6929 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6930 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6931 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6932 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6933 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6934 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6936 static HRESULT WINAPI ITypeInfo_fnInvoke(
6937 ITypeInfo2 *iface,
6938 VOID *pIUnk,
6939 MEMBERID memid,
6940 UINT16 wFlags,
6941 DISPPARAMS *pDispParams,
6942 VARIANT *pVarResult,
6943 EXCEPINFO *pExcepInfo,
6944 UINT *pArgErr)
6946 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6947 int i;
6948 unsigned int var_index;
6949 TYPEKIND type_kind;
6950 HRESULT hres;
6951 const TLBFuncDesc *pFuncInfo;
6952 UINT fdc;
6954 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6955 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6958 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6959 return DISP_E_MEMBERNOTFOUND;
6961 if (!pDispParams)
6963 ERR("NULL pDispParams not allowed\n");
6964 return E_INVALIDARG;
6967 dump_DispParms(pDispParams);
6969 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6971 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6972 pDispParams->cNamedArgs, pDispParams->cArgs);
6973 return E_INVALIDARG;
6976 /* we do this instead of using GetFuncDesc since it will return a fake
6977 * FUNCDESC for dispinterfaces and we want the real function description */
6978 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6979 pFuncInfo = &This->funcdescs[fdc];
6980 if ((memid == pFuncInfo->funcdesc.memid) &&
6981 (wFlags & pFuncInfo->funcdesc.invkind) &&
6982 !func_restricted( &pFuncInfo->funcdesc ))
6983 break;
6986 if (fdc < This->cFuncs) {
6987 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6989 if (TRACE_ON(ole))
6991 TRACE("invoking:\n");
6992 dump_TLBFuncDescOne(pFuncInfo);
6995 switch (func_desc->funckind) {
6996 case FUNC_PUREVIRTUAL:
6997 case FUNC_VIRTUAL: {
6998 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6999 VARIANT varresult;
7000 VARIANT retval; /* pointer for storing byref retvals in */
7001 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7002 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7003 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7004 UINT cNamedArgs = pDispParams->cNamedArgs;
7005 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7006 UINT vargs_converted=0;
7008 hres = S_OK;
7010 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7012 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7014 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7015 hres = DISP_E_PARAMNOTFOUND;
7016 goto func_fail;
7020 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7022 ERR("functions with the vararg attribute do not support named arguments\n");
7023 hres = DISP_E_NONAMEDARGS;
7024 goto func_fail;
7027 for (i = 0; i < func_desc->cParams; i++)
7029 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7030 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7031 if (FAILED(hres))
7032 goto func_fail;
7035 TRACE("changing args\n");
7036 for (i = 0; i < func_desc->cParams; i++)
7038 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7039 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7040 VARIANTARG *src_arg;
7042 if (wParamFlags & PARAMFLAG_FLCID)
7044 VARIANTARG *arg;
7045 arg = prgpvarg[i] = &rgvarg[i];
7046 V_VT(arg) = VT_I4;
7047 V_I4(arg) = This->pTypeLib->lcid;
7048 continue;
7051 src_arg = NULL;
7053 if (cNamedArgs)
7055 USHORT j;
7056 for (j = 0; j < cNamedArgs; j++)
7057 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7059 src_arg = &pDispParams->rgvarg[j];
7060 break;
7064 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7066 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7067 vargs_converted++;
7070 if (wParamFlags & PARAMFLAG_FRETVAL)
7072 /* under most conditions the caller is not allowed to
7073 * pass in a dispparam arg in the index of what would be
7074 * the retval parameter. however, there is an exception
7075 * where the extra parameter is used in an extra
7076 * IDispatch::Invoke below */
7077 if ((i < pDispParams->cArgs) &&
7078 ((func_desc->cParams != 1) || !pVarResult ||
7079 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7081 hres = DISP_E_BADPARAMCOUNT;
7082 break;
7085 /* note: this check is placed so that if the caller passes
7086 * in a VARIANTARG for the retval we just ignore it, like
7087 * native does */
7088 if (i == func_desc->cParams - 1)
7090 VARIANTARG *arg;
7091 arg = prgpvarg[i] = &rgvarg[i];
7092 memset(arg, 0, sizeof(*arg));
7093 V_VT(arg) = rgvt[i];
7094 memset(&retval, 0, sizeof(retval));
7095 V_BYREF(arg) = &retval;
7097 else
7099 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7100 hres = E_UNEXPECTED;
7101 break;
7104 else if (src_arg)
7106 dump_Variant(src_arg);
7108 if(rgvt[i]!=V_VT(src_arg))
7110 if (rgvt[i] == VT_VARIANT)
7111 hres = VariantCopy(&rgvarg[i], src_arg);
7112 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7114 if (rgvt[i] == V_VT(src_arg))
7115 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7116 else
7118 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7119 if (wParamFlags & PARAMFLAG_FIN)
7120 hres = VariantCopy(&missing_arg[i], src_arg);
7121 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7123 V_VT(&rgvarg[i]) = rgvt[i];
7125 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
7127 SAFEARRAY *a;
7128 SAFEARRAYBOUND bound;
7129 VARIANT *v;
7130 LONG j;
7131 bound.lLbound = 0;
7132 bound.cElements = pDispParams->cArgs-i;
7133 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7135 ERR("SafeArrayCreate failed\n");
7136 break;
7138 hres = SafeArrayAccessData(a, (LPVOID)&v);
7139 if (hres != S_OK)
7141 ERR("SafeArrayAccessData failed with %x\n", hres);
7142 SafeArrayDestroy(a);
7143 break;
7145 for (j = 0; j < bound.cElements; j++)
7146 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7147 hres = SafeArrayUnaccessData(a);
7148 if (hres != S_OK)
7150 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7151 SafeArrayDestroy(a);
7152 break;
7154 V_ARRAY(&rgvarg[i]) = a;
7155 V_VT(&rgvarg[i]) = rgvt[i];
7157 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7159 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7160 if (wParamFlags & PARAMFLAG_FIN)
7161 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7162 else
7163 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7164 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7165 V_VT(&rgvarg[i]) = rgvt[i];
7167 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7169 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7170 V_VT(&rgvarg[i]) = rgvt[i];
7172 else
7174 /* FIXME: this doesn't work for VT_BYREF arguments if
7175 * they are not the same type as in the paramdesc */
7176 V_VT(&rgvarg[i]) = V_VT(src_arg);
7177 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7178 V_VT(&rgvarg[i]) = rgvt[i];
7181 if (FAILED(hres))
7183 ERR("failed to convert param %d to %s%s from %s%s\n", i,
7184 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
7185 debugstr_VT(src_arg), debugstr_VF(src_arg));
7186 break;
7188 prgpvarg[i] = &rgvarg[i];
7190 else
7192 prgpvarg[i] = src_arg;
7195 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7196 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7197 && V_UNKNOWN(prgpvarg[i])) {
7198 IUnknown *userdefined_iface;
7199 GUID guid;
7201 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7202 if(FAILED(hres))
7203 break;
7205 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7206 if(FAILED(hres)) {
7207 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7208 break;
7211 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7212 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7215 else if (wParamFlags & PARAMFLAG_FOPT)
7217 VARIANTARG *arg;
7218 arg = prgpvarg[i] = &rgvarg[i];
7219 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7221 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7222 if (FAILED(hres))
7223 break;
7225 else
7227 VARIANTARG *missing_arg;
7228 /* if the function wants a pointer to a variant then
7229 * set that up, otherwise just pass the VT_ERROR in
7230 * the argument by value */
7231 if (rgvt[i] & VT_BYREF)
7233 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7234 V_VT(arg) = VT_VARIANT | VT_BYREF;
7235 V_VARIANTREF(arg) = missing_arg;
7237 else
7238 missing_arg = arg;
7239 V_VT(missing_arg) = VT_ERROR;
7240 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7243 else
7245 hres = DISP_E_BADPARAMCOUNT;
7246 break;
7249 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7251 /* VT_VOID is a special case for return types, so it is not
7252 * handled in the general function */
7253 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7254 V_VT(&varresult) = VT_EMPTY;
7255 else
7257 V_VT(&varresult) = 0;
7258 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7259 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7262 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7263 V_VT(&varresult), func_desc->cParams, rgvt,
7264 prgpvarg, &varresult);
7266 vargs_converted = 0;
7268 for (i = 0; i < func_desc->cParams; i++)
7270 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7271 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7273 if (wParamFlags & PARAMFLAG_FLCID)
7274 continue;
7275 else if (wParamFlags & PARAMFLAG_FRETVAL)
7277 if (TRACE_ON(ole))
7279 TRACE("[retval] value: ");
7280 dump_Variant(prgpvarg[i]);
7283 if (pVarResult)
7285 VariantInit(pVarResult);
7286 /* deref return value */
7287 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7290 VARIANT_ClearInd(prgpvarg[i]);
7292 else if (vargs_converted < pDispParams->cArgs)
7294 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7295 if (wParamFlags & PARAMFLAG_FOUT)
7297 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7299 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7301 if (FAILED(hres))
7303 ERR("failed to convert param %d to vt %d\n", i,
7304 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7305 break;
7309 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7310 func_desc->cParamsOpt < 0 &&
7311 i == func_desc->cParams-1)
7313 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7314 LONG j, ubound;
7315 VARIANT *v;
7316 hres = SafeArrayGetUBound(a, 1, &ubound);
7317 if (hres != S_OK)
7319 ERR("SafeArrayGetUBound failed with %x\n", hres);
7320 break;
7322 hres = SafeArrayAccessData(a, (LPVOID)&v);
7323 if (hres != S_OK)
7325 ERR("SafeArrayAccessData failed with %x\n", hres);
7326 break;
7328 for (j = 0; j <= ubound; j++)
7329 VariantClear(&v[j]);
7330 hres = SafeArrayUnaccessData(a);
7331 if (hres != S_OK)
7333 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7334 break;
7337 VariantClear(&rgvarg[i]);
7338 vargs_converted++;
7340 else if (wParamFlags & PARAMFLAG_FOPT)
7342 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7343 VariantClear(&rgvarg[i]);
7346 VariantClear(&missing_arg[i]);
7349 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7351 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7352 hres = DISP_E_EXCEPTION;
7353 if (pExcepInfo)
7355 IErrorInfo *pErrorInfo;
7356 pExcepInfo->scode = V_ERROR(&varresult);
7357 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7359 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7360 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7361 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7362 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7364 IErrorInfo_Release(pErrorInfo);
7368 if (V_VT(&varresult) != VT_ERROR)
7370 TRACE("varresult value: ");
7371 dump_Variant(&varresult);
7373 if (pVarResult)
7375 VariantClear(pVarResult);
7376 *pVarResult = varresult;
7378 else
7379 VariantClear(&varresult);
7382 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7383 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7384 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7385 (pDispParams->cArgs != 0))
7387 if (V_VT(pVarResult) == VT_DISPATCH)
7389 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7390 /* Note: not VariantClear; we still need the dispatch
7391 * pointer to be valid */
7392 VariantInit(pVarResult);
7393 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7394 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7395 pDispParams, pVarResult, pExcepInfo, pArgErr);
7396 IDispatch_Release(pDispatch);
7398 else
7400 VariantClear(pVarResult);
7401 hres = DISP_E_NOTACOLLECTION;
7405 func_fail:
7406 heap_free(buffer);
7407 break;
7409 case FUNC_DISPATCH: {
7410 IDispatch *disp;
7412 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7413 if (SUCCEEDED(hres)) {
7414 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7415 hres = IDispatch_Invoke(
7416 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7417 pVarResult,pExcepInfo,pArgErr
7419 if (FAILED(hres))
7420 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7421 IDispatch_Release(disp);
7422 } else
7423 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7424 break;
7426 default:
7427 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7428 hres = E_FAIL;
7429 break;
7432 TRACE("-- 0x%08x\n", hres);
7433 return hres;
7435 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7436 VARDESC *var_desc;
7438 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7439 if(FAILED(hres)) return hres;
7441 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7442 dump_VARDESC(var_desc);
7443 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7444 return E_NOTIMPL;
7447 /* not found, look for it in inherited interfaces */
7448 ITypeInfo2_GetTypeKind(iface, &type_kind);
7449 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7450 if(This->impltypes) {
7451 /* recursive search */
7452 ITypeInfo *pTInfo;
7453 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7454 if(SUCCEEDED(hres)){
7455 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7456 ITypeInfo_Release(pTInfo);
7457 return hres;
7459 WARN("Could not search inherited interface!\n");
7462 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7463 return DISP_E_MEMBERNOTFOUND;
7466 /* ITypeInfo::GetDocumentation
7468 * Retrieves the documentation string, the complete Help file name and path,
7469 * and the context ID for the Help topic for a specified type description.
7471 * (Can be tested by the Visual Basic Editor in Word for instance.)
7473 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7474 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7475 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7477 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7478 const TLBFuncDesc *pFDesc;
7479 const TLBVarDesc *pVDesc;
7480 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7481 " HelpContext(%p) HelpFile(%p)\n",
7482 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7483 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7484 if(pBstrName)
7485 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7486 if(pBstrDocString)
7487 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7488 if(pdwHelpContext)
7489 *pdwHelpContext=This->dwHelpContext;
7490 if(pBstrHelpFile)
7491 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7492 return S_OK;
7493 }else {/* for a member */
7494 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7495 if(pFDesc){
7496 if(pBstrName)
7497 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7498 if(pBstrDocString)
7499 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7500 if(pdwHelpContext)
7501 *pdwHelpContext=pFDesc->helpcontext;
7502 if(pBstrHelpFile)
7503 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7504 return S_OK;
7506 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7507 if(pVDesc){
7508 if(pBstrName)
7509 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7510 if(pBstrDocString)
7511 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7512 if(pdwHelpContext)
7513 *pdwHelpContext=pVDesc->HelpContext;
7514 if(pBstrHelpFile)
7515 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7516 return S_OK;
7520 if(This->impltypes &&
7521 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7522 /* recursive search */
7523 ITypeInfo *pTInfo;
7524 HRESULT result;
7525 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7526 if(SUCCEEDED(result)) {
7527 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7528 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7529 ITypeInfo_Release(pTInfo);
7530 return result;
7532 WARN("Could not search inherited interface!\n");
7535 WARN("member %d not found\n", memid);
7536 return TYPE_E_ELEMENTNOTFOUND;
7539 /* ITypeInfo::GetDllEntry
7541 * Retrieves a description or specification of an entry point for a function
7542 * in a DLL.
7544 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7545 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7546 WORD *pwOrdinal)
7548 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7549 const TLBFuncDesc *pFDesc;
7551 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7553 if (pBstrDllName) *pBstrDllName = NULL;
7554 if (pBstrName) *pBstrName = NULL;
7555 if (pwOrdinal) *pwOrdinal = 0;
7557 if (This->typekind != TKIND_MODULE)
7558 return TYPE_E_BADMODULEKIND;
7560 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7561 if(pFDesc){
7562 dump_TypeInfo(This);
7563 if (TRACE_ON(ole))
7564 dump_TLBFuncDescOne(pFDesc);
7566 if (pBstrDllName)
7567 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7569 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7570 if (pBstrName)
7571 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7572 if (pwOrdinal)
7573 *pwOrdinal = -1;
7574 return S_OK;
7576 if (pBstrName)
7577 *pBstrName = NULL;
7578 if (pwOrdinal)
7579 *pwOrdinal = LOWORD(pFDesc->Entry);
7580 return S_OK;
7582 return TYPE_E_ELEMENTNOTFOUND;
7585 /* internal function to make the inherited interfaces' methods appear
7586 * part of the interface */
7587 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7588 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7590 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7591 HRESULT hr;
7593 TRACE("%p, 0x%x\n", iface, *hRefType);
7595 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7597 ITypeInfo *pSubTypeInfo;
7599 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7600 if (FAILED(hr))
7601 return hr;
7603 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7604 hRefType, ppTInfo);
7605 ITypeInfo_Release(pSubTypeInfo);
7606 if (SUCCEEDED(hr))
7607 return hr;
7609 *hRefType -= DISPATCH_HREF_OFFSET;
7611 if (!(*hRefType & DISPATCH_HREF_MASK))
7612 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7613 else
7614 return E_FAIL;
7617 /* ITypeInfo::GetRefTypeInfo
7619 * If a type description references other type descriptions, it retrieves
7620 * the referenced type descriptions.
7622 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7623 ITypeInfo2 *iface,
7624 HREFTYPE hRefType,
7625 ITypeInfo **ppTInfo)
7627 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7628 HRESULT result = E_FAIL;
7630 if(!ppTInfo)
7631 return E_INVALIDARG;
7633 if ((INT)hRefType < 0) {
7634 ITypeInfoImpl *pTypeInfoImpl;
7636 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7637 !(This->typekind == TKIND_INTERFACE ||
7638 This->typekind == TKIND_DISPATCH))
7639 return TYPE_E_ELEMENTNOTFOUND;
7641 /* when we meet a DUAL typeinfo, we must create the alternate
7642 * version of it.
7644 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7646 *pTypeInfoImpl = *This;
7647 pTypeInfoImpl->ref = 0;
7648 list_init(&pTypeInfoImpl->custdata_list);
7650 if (This->typekind == TKIND_INTERFACE)
7651 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7652 else
7653 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7655 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7656 /* the AddRef implicitly adds a reference to the parent typelib, which
7657 * stops the copied data from being destroyed until the new typeinfo's
7658 * refcount goes to zero, but we need to signal to the new instance to
7659 * not free its data structures when it is destroyed */
7660 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7662 ITypeInfo_AddRef(*ppTInfo);
7664 result = S_OK;
7665 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7666 (This->typekind == TKIND_DISPATCH))
7668 HREFTYPE href_dispatch = hRefType;
7669 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7670 } else {
7671 TLBRefType *ref_type;
7672 ITypeLib *pTLib = NULL;
7673 UINT i;
7675 if(!(hRefType & 0x1)){
7676 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7678 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7680 result = S_OK;
7681 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7682 ITypeInfo_AddRef(*ppTInfo);
7683 goto end;
7688 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7690 if(ref_type->reference == (hRefType & (~0x3)))
7691 break;
7693 if(&ref_type->entry == &This->pTypeLib->ref_list)
7695 FIXME("Can't find pRefType for ref %x\n", hRefType);
7696 goto end;
7699 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7700 UINT Index;
7701 TRACE("internal reference\n");
7702 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7703 } else {
7704 if(ref_type->pImpTLInfo->pImpTypeLib) {
7705 TRACE("typeinfo in imported typelib that is already loaded\n");
7706 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7707 ITypeLib_AddRef(pTLib);
7708 result = S_OK;
7709 } else {
7710 BSTR libnam;
7712 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7714 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7715 ref_type->pImpTLInfo->wVersionMajor,
7716 ref_type->pImpTLInfo->wVersionMinor,
7717 This->pTypeLib->syskind,
7718 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7719 if(FAILED(result))
7720 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7722 result = LoadTypeLib(libnam, &pTLib);
7723 SysFreeString(libnam);
7725 if(SUCCEEDED(result)) {
7726 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7727 ITypeLib_AddRef(pTLib);
7731 if(SUCCEEDED(result)) {
7732 if(ref_type->index == TLB_REF_USE_GUID)
7733 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7734 else
7735 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7737 if (pTLib != NULL)
7738 ITypeLib_Release(pTLib);
7741 end:
7742 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7743 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7744 return result;
7747 /* ITypeInfo::AddressOfMember
7749 * Retrieves the addresses of static functions or variables, such as those
7750 * defined in a DLL.
7752 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7753 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7755 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7756 HRESULT hr;
7757 BSTR dll, entry;
7758 WORD ordinal;
7759 HMODULE module;
7761 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7763 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7764 if (FAILED(hr))
7765 return hr;
7767 module = LoadLibraryW(dll);
7768 if (!module)
7770 ERR("couldn't load %s\n", debugstr_w(dll));
7771 SysFreeString(dll);
7772 SysFreeString(entry);
7773 return STG_E_FILENOTFOUND;
7775 /* FIXME: store library somewhere where we can free it */
7777 if (entry)
7779 LPSTR entryA;
7780 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7781 entryA = heap_alloc(len);
7782 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7784 *ppv = GetProcAddress(module, entryA);
7785 if (!*ppv)
7786 ERR("function not found %s\n", debugstr_a(entryA));
7788 heap_free(entryA);
7790 else
7792 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7793 if (!*ppv)
7794 ERR("function not found %d\n", ordinal);
7797 SysFreeString(dll);
7798 SysFreeString(entry);
7800 if (!*ppv)
7801 return TYPE_E_DLLFUNCTIONNOTFOUND;
7803 return S_OK;
7806 /* ITypeInfo::CreateInstance
7808 * Creates a new instance of a type that describes a component object class
7809 * (coclass).
7811 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7812 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7814 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7815 HRESULT hr;
7816 TYPEATTR *pTA;
7818 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7820 *ppvObj = NULL;
7822 if(pOuterUnk)
7824 WARN("Not able to aggregate\n");
7825 return CLASS_E_NOAGGREGATION;
7828 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7829 if(FAILED(hr)) return hr;
7831 if(pTA->typekind != TKIND_COCLASS)
7833 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7834 hr = E_INVALIDARG;
7835 goto end;
7838 hr = S_FALSE;
7839 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7841 IUnknown *pUnk;
7842 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7843 TRACE("GetActiveObject rets %08x\n", hr);
7844 if(hr == S_OK)
7846 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7847 IUnknown_Release(pUnk);
7851 if(hr != S_OK)
7852 hr = CoCreateInstance(&pTA->guid, NULL,
7853 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7854 riid, ppvObj);
7856 end:
7857 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7858 return hr;
7861 /* ITypeInfo::GetMops
7863 * Retrieves marshalling information.
7865 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7866 BSTR *pBstrMops)
7868 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7869 FIXME("(%p %d) stub!\n", This, memid);
7870 *pBstrMops = NULL;
7871 return S_OK;
7874 /* ITypeInfo::GetContainingTypeLib
7876 * Retrieves the containing type library and the index of the type description
7877 * within that type library.
7879 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7880 ITypeLib * *ppTLib, UINT *pIndex)
7882 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7884 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7885 if (pIndex) {
7886 *pIndex=This->index;
7887 TRACE("returning pIndex=%d\n", *pIndex);
7890 if (ppTLib) {
7891 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7892 ITypeLib_AddRef(*ppTLib);
7893 TRACE("returning ppTLib=%p\n", *ppTLib);
7896 return S_OK;
7899 /* ITypeInfo::ReleaseTypeAttr
7901 * Releases a TYPEATTR previously returned by Get
7904 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7905 TYPEATTR* pTypeAttr)
7907 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7908 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7909 heap_free(pTypeAttr);
7912 /* ITypeInfo::ReleaseFuncDesc
7914 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7916 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7917 ITypeInfo2 *iface,
7918 FUNCDESC *pFuncDesc)
7920 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7921 SHORT i;
7923 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7925 for (i = 0; i < pFuncDesc->cParams; i++)
7926 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7927 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7929 SysFreeString((BSTR)pFuncDesc);
7932 /* ITypeInfo::ReleaseVarDesc
7934 * Releases a VARDESC previously returned by GetVarDesc.
7936 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7937 VARDESC *pVarDesc)
7939 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7940 TRACE("(%p)->(%p)\n", This, pVarDesc);
7942 TLB_FreeVarDesc(pVarDesc);
7945 /* ITypeInfo2::GetTypeKind
7947 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7950 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7951 TYPEKIND *pTypeKind)
7953 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7954 *pTypeKind=This->typekind;
7955 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7956 return S_OK;
7959 /* ITypeInfo2::GetTypeFlags
7961 * Returns the type flags without any allocations. This returns a DWORD type
7962 * flag, which expands the type flags without growing the TYPEATTR (type
7963 * attribute).
7966 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7968 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7969 *pTypeFlags=This->wTypeFlags;
7970 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7971 return S_OK;
7974 /* ITypeInfo2::GetFuncIndexOfMemId
7975 * Binds to a specific member based on a known DISPID, where the member name
7976 * is not known (for example, when binding to a default member).
7979 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7980 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7982 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7983 UINT fdc;
7984 HRESULT result;
7986 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7987 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7988 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7989 break;
7991 if(fdc < This->cFuncs) {
7992 *pFuncIndex = fdc;
7993 result = S_OK;
7994 } else
7995 result = TYPE_E_ELEMENTNOTFOUND;
7997 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7998 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7999 return result;
8002 /* TypeInfo2::GetVarIndexOfMemId
8004 * Binds to a specific member based on a known DISPID, where the member name
8005 * is not known (for example, when binding to a default member).
8008 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8009 MEMBERID memid, UINT *pVarIndex)
8011 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8012 TLBVarDesc *pVarInfo;
8014 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8016 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8017 if(!pVarInfo)
8018 return TYPE_E_ELEMENTNOTFOUND;
8020 *pVarIndex = (pVarInfo - This->vardescs);
8022 return S_OK;
8025 /* ITypeInfo2::GetCustData
8027 * Gets the custom data
8029 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8030 ITypeInfo2 * iface,
8031 REFGUID guid,
8032 VARIANT *pVarVal)
8034 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8035 TLBCustData *pCData;
8037 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8039 if(!guid || !pVarVal)
8040 return E_INVALIDARG;
8042 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8044 VariantInit( pVarVal);
8045 if (pCData)
8046 VariantCopy( pVarVal, &pCData->data);
8047 else
8048 VariantClear( pVarVal );
8049 return S_OK;
8052 /* ITypeInfo2::GetFuncCustData
8054 * Gets the custom data
8056 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8057 ITypeInfo2 * iface,
8058 UINT index,
8059 REFGUID guid,
8060 VARIANT *pVarVal)
8062 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8063 TLBCustData *pCData;
8064 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8066 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8068 if(index >= This->cFuncs)
8069 return TYPE_E_ELEMENTNOTFOUND;
8071 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8072 if(!pCData)
8073 return TYPE_E_ELEMENTNOTFOUND;
8075 VariantInit(pVarVal);
8076 VariantCopy(pVarVal, &pCData->data);
8078 return S_OK;
8081 /* ITypeInfo2::GetParamCustData
8083 * Gets the custom data
8085 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8086 ITypeInfo2 * iface,
8087 UINT indexFunc,
8088 UINT indexParam,
8089 REFGUID guid,
8090 VARIANT *pVarVal)
8092 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8093 TLBCustData *pCData;
8094 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8096 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8097 debugstr_guid(guid), pVarVal);
8099 if(indexFunc >= This->cFuncs)
8100 return TYPE_E_ELEMENTNOTFOUND;
8102 if(indexParam >= pFDesc->funcdesc.cParams)
8103 return TYPE_E_ELEMENTNOTFOUND;
8105 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8106 if(!pCData)
8107 return TYPE_E_ELEMENTNOTFOUND;
8109 VariantInit(pVarVal);
8110 VariantCopy(pVarVal, &pCData->data);
8112 return S_OK;
8115 /* ITypeInfo2::GetVarCustData
8117 * Gets the custom data
8119 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8120 ITypeInfo2 * iface,
8121 UINT index,
8122 REFGUID guid,
8123 VARIANT *pVarVal)
8125 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8126 TLBCustData *pCData;
8127 TLBVarDesc *pVDesc = &This->vardescs[index];
8129 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8131 if(index >= This->cVars)
8132 return TYPE_E_ELEMENTNOTFOUND;
8134 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8135 if(!pCData)
8136 return TYPE_E_ELEMENTNOTFOUND;
8138 VariantInit(pVarVal);
8139 VariantCopy(pVarVal, &pCData->data);
8141 return S_OK;
8144 /* ITypeInfo2::GetImplCustData
8146 * Gets the custom data
8148 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8149 ITypeInfo2 * iface,
8150 UINT index,
8151 REFGUID guid,
8152 VARIANT *pVarVal)
8154 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8155 TLBCustData *pCData;
8156 TLBImplType *pRDesc = &This->impltypes[index];
8158 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8160 if(index >= This->cImplTypes)
8161 return TYPE_E_ELEMENTNOTFOUND;
8163 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8164 if(!pCData)
8165 return TYPE_E_ELEMENTNOTFOUND;
8167 VariantInit(pVarVal);
8168 VariantCopy(pVarVal, &pCData->data);
8170 return S_OK;
8173 /* ITypeInfo2::GetDocumentation2
8175 * Retrieves the documentation string, the complete Help file name and path,
8176 * the localization context to use, and the context ID for the library Help
8177 * topic in the Help file.
8180 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8181 ITypeInfo2 * iface,
8182 MEMBERID memid,
8183 LCID lcid,
8184 BSTR *pbstrHelpString,
8185 DWORD *pdwHelpStringContext,
8186 BSTR *pbstrHelpStringDll)
8188 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8189 const TLBFuncDesc *pFDesc;
8190 const TLBVarDesc *pVDesc;
8191 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8192 "HelpStringContext(%p) HelpStringDll(%p)\n",
8193 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8194 pbstrHelpStringDll );
8195 /* the help string should be obtained from the helpstringdll,
8196 * using the _DLLGetDocumentation function, based on the supplied
8197 * lcid. Nice to do sometime...
8199 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8200 if(pbstrHelpString)
8201 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8202 if(pdwHelpStringContext)
8203 *pdwHelpStringContext=This->dwHelpStringContext;
8204 if(pbstrHelpStringDll)
8205 *pbstrHelpStringDll=
8206 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8207 return S_OK;
8208 }else {/* for a member */
8209 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
8210 if(pFDesc){
8211 if(pbstrHelpString)
8212 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8213 if(pdwHelpStringContext)
8214 *pdwHelpStringContext=pFDesc->HelpStringContext;
8215 if(pbstrHelpStringDll)
8216 *pbstrHelpStringDll=
8217 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8218 return S_OK;
8220 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8221 if(pVDesc){
8222 if(pbstrHelpString)
8223 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8224 if(pdwHelpStringContext)
8225 *pdwHelpStringContext=pVDesc->HelpStringContext;
8226 if(pbstrHelpStringDll)
8227 *pbstrHelpStringDll=
8228 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8229 return S_OK;
8232 return TYPE_E_ELEMENTNOTFOUND;
8235 /* ITypeInfo2::GetAllCustData
8237 * Gets all custom data items for the Type info.
8240 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8241 ITypeInfo2 * iface,
8242 CUSTDATA *pCustData)
8244 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8246 TRACE("%p %p\n", This, pCustData);
8248 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8251 /* ITypeInfo2::GetAllFuncCustData
8253 * Gets all custom data items for the specified Function
8256 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8257 ITypeInfo2 * iface,
8258 UINT index,
8259 CUSTDATA *pCustData)
8261 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8262 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8264 TRACE("%p %u %p\n", This, index, pCustData);
8266 if(index >= This->cFuncs)
8267 return TYPE_E_ELEMENTNOTFOUND;
8269 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8272 /* ITypeInfo2::GetAllParamCustData
8274 * Gets all custom data items for the Functions
8277 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8278 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8280 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8281 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8283 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8285 if(indexFunc >= This->cFuncs)
8286 return TYPE_E_ELEMENTNOTFOUND;
8288 if(indexParam >= pFDesc->funcdesc.cParams)
8289 return TYPE_E_ELEMENTNOTFOUND;
8291 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8294 /* ITypeInfo2::GetAllVarCustData
8296 * Gets all custom data items for the specified Variable
8299 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8300 UINT index, CUSTDATA *pCustData)
8302 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8303 TLBVarDesc * pVDesc = &This->vardescs[index];
8305 TRACE("%p %u %p\n", This, index, pCustData);
8307 if(index >= This->cVars)
8308 return TYPE_E_ELEMENTNOTFOUND;
8310 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8313 /* ITypeInfo2::GetAllImplCustData
8315 * Gets all custom data items for the specified implementation type
8318 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8319 ITypeInfo2 * iface,
8320 UINT index,
8321 CUSTDATA *pCustData)
8323 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8324 TLBImplType *pRDesc = &This->impltypes[index];
8326 TRACE("%p %u %p\n", This, index, pCustData);
8328 if(index >= This->cImplTypes)
8329 return TYPE_E_ELEMENTNOTFOUND;
8331 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8334 static const ITypeInfo2Vtbl tinfvt =
8337 ITypeInfo_fnQueryInterface,
8338 ITypeInfo_fnAddRef,
8339 ITypeInfo_fnRelease,
8341 ITypeInfo_fnGetTypeAttr,
8342 ITypeInfo_fnGetTypeComp,
8343 ITypeInfo_fnGetFuncDesc,
8344 ITypeInfo_fnGetVarDesc,
8345 ITypeInfo_fnGetNames,
8346 ITypeInfo_fnGetRefTypeOfImplType,
8347 ITypeInfo_fnGetImplTypeFlags,
8348 ITypeInfo_fnGetIDsOfNames,
8349 ITypeInfo_fnInvoke,
8350 ITypeInfo_fnGetDocumentation,
8351 ITypeInfo_fnGetDllEntry,
8352 ITypeInfo_fnGetRefTypeInfo,
8353 ITypeInfo_fnAddressOfMember,
8354 ITypeInfo_fnCreateInstance,
8355 ITypeInfo_fnGetMops,
8356 ITypeInfo_fnGetContainingTypeLib,
8357 ITypeInfo_fnReleaseTypeAttr,
8358 ITypeInfo_fnReleaseFuncDesc,
8359 ITypeInfo_fnReleaseVarDesc,
8361 ITypeInfo2_fnGetTypeKind,
8362 ITypeInfo2_fnGetTypeFlags,
8363 ITypeInfo2_fnGetFuncIndexOfMemId,
8364 ITypeInfo2_fnGetVarIndexOfMemId,
8365 ITypeInfo2_fnGetCustData,
8366 ITypeInfo2_fnGetFuncCustData,
8367 ITypeInfo2_fnGetParamCustData,
8368 ITypeInfo2_fnGetVarCustData,
8369 ITypeInfo2_fnGetImplTypeCustData,
8370 ITypeInfo2_fnGetDocumentation2,
8371 ITypeInfo2_fnGetAllCustData,
8372 ITypeInfo2_fnGetAllFuncCustData,
8373 ITypeInfo2_fnGetAllParamCustData,
8374 ITypeInfo2_fnGetAllVarCustData,
8375 ITypeInfo2_fnGetAllImplTypeCustData,
8378 /******************************************************************************
8379 * CreateDispTypeInfo [OLEAUT32.31]
8381 * Build type information for an object so it can be called through an
8382 * IDispatch interface.
8384 * RETURNS
8385 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8386 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8388 * NOTES
8389 * This call allows an objects methods to be accessed through IDispatch, by
8390 * building an ITypeInfo object that IDispatch can use to call through.
8392 HRESULT WINAPI CreateDispTypeInfo(
8393 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8394 LCID lcid, /* [I] Locale Id */
8395 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8397 ITypeInfoImpl *pTIClass, *pTIIface;
8398 ITypeLibImpl *pTypeLibImpl;
8399 unsigned int param, func;
8400 TLBFuncDesc *pFuncDesc;
8401 TLBRefType *ref;
8403 TRACE("\n");
8404 pTypeLibImpl = TypeLibImpl_Constructor();
8405 if (!pTypeLibImpl) return E_FAIL;
8407 pTypeLibImpl->TypeInfoCount = 2;
8408 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8410 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8411 pTIIface->pTypeLib = pTypeLibImpl;
8412 pTIIface->index = 0;
8413 pTIIface->Name = NULL;
8414 pTIIface->dwHelpContext = -1;
8415 pTIIface->guid = NULL;
8416 pTIIface->lcid = lcid;
8417 pTIIface->typekind = TKIND_INTERFACE;
8418 pTIIface->wMajorVerNum = 0;
8419 pTIIface->wMinorVerNum = 0;
8420 pTIIface->cbAlignment = 2;
8421 pTIIface->cbSizeInstance = -1;
8422 pTIIface->cbSizeVft = -1;
8423 pTIIface->cFuncs = 0;
8424 pTIIface->cImplTypes = 0;
8425 pTIIface->cVars = 0;
8426 pTIIface->wTypeFlags = 0;
8427 pTIIface->hreftype = 0;
8429 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8430 pFuncDesc = pTIIface->funcdescs;
8431 for(func = 0; func < pidata->cMembers; func++) {
8432 METHODDATA *md = pidata->pmethdata + func;
8433 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8434 pFuncDesc->funcdesc.memid = md->dispid;
8435 pFuncDesc->funcdesc.lprgscode = NULL;
8436 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8437 pFuncDesc->funcdesc.invkind = md->wFlags;
8438 pFuncDesc->funcdesc.callconv = md->cc;
8439 pFuncDesc->funcdesc.cParams = md->cArgs;
8440 pFuncDesc->funcdesc.cParamsOpt = 0;
8441 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8442 pFuncDesc->funcdesc.cScodes = 0;
8443 pFuncDesc->funcdesc.wFuncFlags = 0;
8444 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8445 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8446 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8447 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8448 md->cArgs * sizeof(ELEMDESC));
8449 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8450 for(param = 0; param < md->cArgs; param++) {
8451 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8452 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8454 pFuncDesc->helpcontext = 0;
8455 pFuncDesc->HelpStringContext = 0;
8456 pFuncDesc->HelpString = NULL;
8457 pFuncDesc->Entry = NULL;
8458 list_init(&pFuncDesc->custdata_list);
8459 pTIIface->cFuncs++;
8460 ++pFuncDesc;
8463 dump_TypeInfo(pTIIface);
8465 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8466 pTIClass->pTypeLib = pTypeLibImpl;
8467 pTIClass->index = 1;
8468 pTIClass->Name = NULL;
8469 pTIClass->dwHelpContext = -1;
8470 pTIClass->guid = NULL;
8471 pTIClass->lcid = lcid;
8472 pTIClass->typekind = TKIND_COCLASS;
8473 pTIClass->wMajorVerNum = 0;
8474 pTIClass->wMinorVerNum = 0;
8475 pTIClass->cbAlignment = 2;
8476 pTIClass->cbSizeInstance = -1;
8477 pTIClass->cbSizeVft = -1;
8478 pTIClass->cFuncs = 0;
8479 pTIClass->cImplTypes = 1;
8480 pTIClass->cVars = 0;
8481 pTIClass->wTypeFlags = 0;
8482 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8484 pTIClass->impltypes = TLBImplType_Alloc(1);
8486 ref = heap_alloc_zero(sizeof(*ref));
8487 ref->pImpTLInfo = TLB_REF_INTERNAL;
8488 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8490 dump_TypeInfo(pTIClass);
8492 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8494 ITypeInfo_AddRef(*pptinfo);
8495 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8497 return S_OK;
8501 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8503 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8505 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8508 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8510 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8512 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8515 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8517 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8519 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8522 static HRESULT WINAPI ITypeComp_fnBind(
8523 ITypeComp * iface,
8524 OLECHAR * szName,
8525 ULONG lHash,
8526 WORD wFlags,
8527 ITypeInfo ** ppTInfo,
8528 DESCKIND * pDescKind,
8529 BINDPTR * pBindPtr)
8531 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8532 const TLBFuncDesc *pFDesc;
8533 const TLBVarDesc *pVDesc;
8534 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8535 UINT fdc;
8537 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8539 *pDescKind = DESCKIND_NONE;
8540 pBindPtr->lpfuncdesc = NULL;
8541 *ppTInfo = NULL;
8543 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8544 pFDesc = &This->funcdescs[fdc];
8545 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8546 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8547 break;
8548 else
8549 /* name found, but wrong flags */
8550 hr = TYPE_E_TYPEMISMATCH;
8554 if (fdc < This->cFuncs)
8556 HRESULT hr = TLB_AllocAndInitFuncDesc(
8557 &pFDesc->funcdesc,
8558 &pBindPtr->lpfuncdesc,
8559 This->typekind == TKIND_DISPATCH);
8560 if (FAILED(hr))
8561 return hr;
8562 *pDescKind = DESCKIND_FUNCDESC;
8563 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8564 ITypeInfo_AddRef(*ppTInfo);
8565 return S_OK;
8566 } else {
8567 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8568 if(pVDesc){
8569 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8570 if (FAILED(hr))
8571 return hr;
8572 *pDescKind = DESCKIND_VARDESC;
8573 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8574 ITypeInfo_AddRef(*ppTInfo);
8575 return S_OK;
8579 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8580 /* recursive search */
8581 ITypeInfo *pTInfo;
8582 ITypeComp *pTComp;
8583 HRESULT hr;
8584 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8585 if (SUCCEEDED(hr))
8587 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8588 ITypeInfo_Release(pTInfo);
8590 if (SUCCEEDED(hr))
8592 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8593 ITypeComp_Release(pTComp);
8594 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8595 This->typekind == TKIND_DISPATCH)
8597 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8598 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8599 SysFreeString((BSTR)tmp);
8601 return hr;
8603 WARN("Could not search inherited interface!\n");
8605 if (hr == DISP_E_MEMBERNOTFOUND)
8606 hr = S_OK;
8607 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8608 return hr;
8611 static HRESULT WINAPI ITypeComp_fnBindType(
8612 ITypeComp * iface,
8613 OLECHAR * szName,
8614 ULONG lHash,
8615 ITypeInfo ** ppTInfo,
8616 ITypeComp ** ppTComp)
8618 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8620 /* strange behaviour (does nothing) but like the
8621 * original */
8623 if (!ppTInfo || !ppTComp)
8624 return E_POINTER;
8626 *ppTInfo = NULL;
8627 *ppTComp = NULL;
8629 return S_OK;
8632 static const ITypeCompVtbl tcompvt =
8635 ITypeComp_fnQueryInterface,
8636 ITypeComp_fnAddRef,
8637 ITypeComp_fnRelease,
8639 ITypeComp_fnBind,
8640 ITypeComp_fnBindType
8643 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8644 ICreateTypeLib2** ppctlib)
8646 ITypeLibImpl *This;
8647 HRESULT hres;
8649 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8651 if (!szFile) return E_INVALIDARG;
8653 This = TypeLibImpl_Constructor();
8654 if (!This)
8655 return E_OUTOFMEMORY;
8657 This->lcid = GetSystemDefaultLCID();
8658 This->syskind = syskind;
8659 This->ptr_size = get_ptr_size(syskind);
8661 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8662 if (!This->path) {
8663 ITypeLib2_Release(&This->ITypeLib2_iface);
8664 return E_OUTOFMEMORY;
8666 lstrcpyW(This->path, szFile);
8668 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8669 ITypeLib2_Release(&This->ITypeLib2_iface);
8670 return hres;
8673 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8674 REFIID riid, void **object)
8676 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8678 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8681 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8683 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8685 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8688 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8690 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8692 return ITypeLib2_Release(&This->ITypeLib2_iface);
8695 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8696 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8698 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8699 ITypeInfoImpl *info;
8700 HRESULT hres;
8702 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8704 if (!ctinfo || !name)
8705 return E_INVALIDARG;
8707 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8708 if (info)
8709 return TYPE_E_NAMECONFLICT;
8711 if (This->typeinfos)
8712 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8713 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8714 else
8715 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8717 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8719 info->pTypeLib = This;
8720 info->Name = TLB_append_str(&This->name_list, name);
8721 info->index = This->TypeInfoCount;
8722 info->typekind = kind;
8723 info->cbAlignment = 4;
8725 switch(info->typekind) {
8726 case TKIND_ENUM:
8727 case TKIND_INTERFACE:
8728 case TKIND_DISPATCH:
8729 case TKIND_COCLASS:
8730 info->cbSizeInstance = This->ptr_size;
8731 break;
8732 case TKIND_RECORD:
8733 case TKIND_UNION:
8734 info->cbSizeInstance = 0;
8735 break;
8736 case TKIND_MODULE:
8737 info->cbSizeInstance = 2;
8738 break;
8739 case TKIND_ALIAS:
8740 info->cbSizeInstance = -0x75;
8741 break;
8742 default:
8743 FIXME("unrecognized typekind %d\n", info->typekind);
8744 info->cbSizeInstance = 0xdeadbeef;
8745 break;
8748 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8749 &IID_ICreateTypeInfo, (void **)ctinfo);
8750 if (FAILED(hres)) {
8751 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8752 return hres;
8755 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8757 ++This->TypeInfoCount;
8759 return S_OK;
8762 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8763 LPOLESTR name)
8765 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8767 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8769 if (!name)
8770 return E_INVALIDARG;
8772 This->Name = TLB_append_str(&This->name_list, name);
8774 return S_OK;
8777 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8778 WORD majorVerNum, WORD minorVerNum)
8780 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8782 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8784 This->ver_major = majorVerNum;
8785 This->ver_minor = minorVerNum;
8787 return S_OK;
8790 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8791 REFGUID guid)
8793 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8795 TRACE("%p %s\n", This, debugstr_guid(guid));
8797 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8799 return S_OK;
8802 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8803 LPOLESTR doc)
8805 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8807 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8809 if (!doc)
8810 return E_INVALIDARG;
8812 This->DocString = TLB_append_str(&This->string_list, doc);
8814 return S_OK;
8817 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8818 LPOLESTR helpFileName)
8820 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8822 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8824 if (!helpFileName)
8825 return E_INVALIDARG;
8827 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8829 return S_OK;
8832 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8833 DWORD helpContext)
8835 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8837 TRACE("%p %d\n", This, helpContext);
8839 This->dwHelpContext = helpContext;
8841 return S_OK;
8844 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8845 LCID lcid)
8847 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8849 TRACE("%p %x\n", This, lcid);
8851 This->set_lcid = lcid;
8853 return S_OK;
8856 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8857 UINT libFlags)
8859 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8861 TRACE("%p %x\n", This, libFlags);
8863 This->libflags = libFlags;
8865 return S_OK;
8868 typedef struct tagWMSFT_SegContents {
8869 DWORD len;
8870 void *data;
8871 } WMSFT_SegContents;
8873 typedef struct tagWMSFT_TLBFile {
8874 MSFT_Header header;
8875 WMSFT_SegContents typeinfo_seg;
8876 WMSFT_SegContents impfile_seg;
8877 WMSFT_SegContents impinfo_seg;
8878 WMSFT_SegContents ref_seg;
8879 WMSFT_SegContents guidhash_seg;
8880 WMSFT_SegContents guid_seg;
8881 WMSFT_SegContents namehash_seg;
8882 WMSFT_SegContents name_seg;
8883 WMSFT_SegContents string_seg;
8884 WMSFT_SegContents typdesc_seg;
8885 WMSFT_SegContents arraydesc_seg;
8886 WMSFT_SegContents custdata_seg;
8887 WMSFT_SegContents cdguids_seg;
8888 MSFT_SegDir segdir;
8889 WMSFT_SegContents aux_seg;
8890 } WMSFT_TLBFile;
8892 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8893 WMSFT_TLBFile *file)
8895 TLBString *str;
8896 UINT last_offs;
8897 char *data;
8899 file->string_seg.len = 0;
8900 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8901 int size;
8903 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8904 if (size == 0)
8905 return E_UNEXPECTED;
8907 size += sizeof(INT16);
8908 if (size % 4)
8909 size = (size + 4) & ~0x3;
8910 if (size < 8)
8911 size = 8;
8913 file->string_seg.len += size;
8915 /* temporarily use str->offset to store the length of the aligned,
8916 * converted string */
8917 str->offset = size;
8920 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8922 last_offs = 0;
8923 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8924 int size;
8926 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8927 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8928 if (size == 0) {
8929 heap_free(file->string_seg.data);
8930 return E_UNEXPECTED;
8933 *((INT16*)data) = size;
8935 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8937 size = str->offset;
8938 data += size;
8939 str->offset = last_offs;
8940 last_offs += size;
8943 return S_OK;
8946 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8947 WMSFT_TLBFile *file)
8949 TLBString *str;
8950 UINT last_offs;
8951 char *data;
8952 MSFT_NameIntro *last_intro = NULL;
8954 file->header.nametablecount = 0;
8955 file->header.nametablechars = 0;
8957 file->name_seg.len = 0;
8958 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8959 int size;
8961 size = strlenW(str->str);
8962 file->header.nametablechars += size;
8963 file->header.nametablecount++;
8965 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8966 if (size == 0)
8967 return E_UNEXPECTED;
8969 size += sizeof(MSFT_NameIntro);
8970 if (size % 4)
8971 size = (size + 4) & ~0x3;
8972 if (size < 8)
8973 size = 8;
8975 file->name_seg.len += size;
8977 /* temporarily use str->offset to store the length of the aligned,
8978 * converted string */
8979 str->offset = size;
8982 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8983 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8985 last_offs = 0;
8986 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8987 int size, hash;
8988 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8990 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8991 data + sizeof(MSFT_NameIntro),
8992 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8993 if (size == 0) {
8994 heap_free(file->name_seg.data);
8995 return E_UNEXPECTED;
8997 data[sizeof(MSFT_NameIntro) + size] = '\0';
8999 intro->hreftype = -1; /* TODO? */
9000 intro->namelen = size & 0xFF;
9001 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9002 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9003 intro->namelen |= hash << 16;
9004 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9005 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9007 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9008 str->offset - size - sizeof(MSFT_NameIntro));
9010 /* update str->offset to actual value to use in other
9011 * compilation functions that require positions within
9012 * the string table */
9013 last_intro = intro;
9014 size = str->offset;
9015 data += size;
9016 str->offset = last_offs;
9017 last_offs += size;
9020 if(last_intro)
9021 last_intro->hreftype = 0; /* last one is 0? */
9023 return S_OK;
9026 static inline int hash_guid(GUID *guid)
9028 int i, hash = 0;
9030 for (i = 0; i < 8; i ++)
9031 hash ^= ((const short *)guid)[i];
9033 return hash & 0x1f;
9036 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9038 TLBGuid *guid;
9039 MSFT_GuidEntry *entry;
9040 DWORD offs;
9041 int hash_key, *guidhashtab;
9043 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9044 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9046 entry = file->guid_seg.data;
9047 offs = 0;
9048 guidhashtab = file->guidhash_seg.data;
9049 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9050 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9051 entry->hreftype = guid->hreftype;
9053 hash_key = hash_guid(&guid->guid);
9054 entry->next_hash = guidhashtab[hash_key];
9055 guidhashtab[hash_key] = offs;
9057 guid->offset = offs;
9058 offs += sizeof(MSFT_GuidEntry);
9059 ++entry;
9062 return S_OK;
9065 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9067 VARIANT v = *value;
9068 VARTYPE arg_type = V_VT(value);
9069 int mask = 0;
9070 HRESULT hres;
9071 DWORD ret = file->custdata_seg.len;
9073 if(arg_type == VT_INT)
9074 arg_type = VT_I4;
9075 if(arg_type == VT_UINT)
9076 arg_type = VT_UI4;
9078 v = *value;
9079 if(V_VT(value) != arg_type) {
9080 hres = VariantChangeType(&v, value, 0, arg_type);
9081 if(FAILED(hres)){
9082 ERR("VariantChangeType failed: %08x\n", hres);
9083 return -1;
9087 /* Check if default value can be stored in-place */
9088 switch(arg_type){
9089 case VT_I4:
9090 case VT_UI4:
9091 mask = 0x3ffffff;
9092 if(V_UI4(&v) > 0x3ffffff)
9093 break;
9094 /* fall through */
9095 case VT_I1:
9096 case VT_UI1:
9097 case VT_BOOL:
9098 if(!mask)
9099 mask = 0xff;
9100 /* fall through */
9101 case VT_I2:
9102 case VT_UI2:
9103 if(!mask)
9104 mask = 0xffff;
9105 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9108 /* have to allocate space in custdata_seg */
9109 switch(arg_type) {
9110 case VT_I4:
9111 case VT_R4:
9112 case VT_UI4:
9113 case VT_INT:
9114 case VT_UINT:
9115 case VT_HRESULT:
9116 case VT_PTR: {
9117 /* Construct the data to be allocated */
9118 int *data;
9120 if(file->custdata_seg.data){
9121 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9122 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9123 file->custdata_seg.len += sizeof(int) * 2;
9124 }else{
9125 file->custdata_seg.len = sizeof(int) * 2;
9126 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9129 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9130 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9132 /* TODO: Check if the encoded data is already present in custdata_seg */
9134 return ret;
9137 case VT_BSTR: {
9138 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9139 char *data;
9141 if(file->custdata_seg.data){
9142 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9143 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9144 file->custdata_seg.len += len;
9145 }else{
9146 file->custdata_seg.len = len;
9147 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9150 *((unsigned short *)data) = V_VT(value);
9151 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9152 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9153 if(V_BSTR(&v)[i] <= 0x7f)
9154 data[i+6] = V_BSTR(&v)[i];
9155 else
9156 data[i+6] = '?';
9158 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9159 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9160 data[i] = 0x57;
9162 /* TODO: Check if the encoded data is already present in custdata_seg */
9164 return ret;
9166 default:
9167 FIXME("Argument type not yet handled\n");
9168 return -1;
9172 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9174 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9176 DWORD offs = file->arraydesc_seg.len;
9177 DWORD *encoded;
9178 USHORT i;
9180 /* TODO: we should check for duplicates, but that's harder because each
9181 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9182 * at the library-level) */
9184 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9185 if(!file->arraydesc_seg.data)
9186 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9187 else
9188 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9189 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
9191 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9192 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9193 for(i = 0; i < desc->cDims; ++i){
9194 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9195 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9198 return offs;
9201 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9203 DWORD junk;
9204 INT16 junk2;
9205 DWORD offs = 0;
9206 DWORD encoded[2];
9207 VARTYPE vt, subtype;
9208 char *data;
9210 if(!desc)
9211 return -1;
9213 if(!out_mix)
9214 out_mix = &junk;
9215 if(!out_size)
9216 out_size = &junk2;
9218 vt = desc->vt & VT_TYPEMASK;
9220 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9221 DWORD mix;
9222 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9223 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9224 *out_mix = 0x7FFF;
9225 *out_size += 2 * sizeof(DWORD);
9226 }else if(vt == VT_CARRAY){
9227 encoded[0] = desc->vt | (0x7FFE << 16);
9228 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9229 *out_mix = 0x7FFE;
9230 }else if(vt == VT_USERDEFINED){
9231 encoded[0] = desc->vt | (0x7FFF << 16);
9232 encoded[1] = desc->u.hreftype;
9233 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9234 }else{
9235 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9237 switch(vt){
9238 case VT_INT:
9239 subtype = VT_I4;
9240 break;
9241 case VT_UINT:
9242 subtype = VT_UI4;
9243 break;
9244 case VT_VOID:
9245 subtype = VT_EMPTY;
9246 break;
9247 default:
9248 subtype = vt;
9249 break;
9252 *out_mix = subtype;
9253 return 0x80000000 | (subtype << 16) | desc->vt;
9256 data = file->typdesc_seg.data;
9257 while(offs < file->typdesc_seg.len){
9258 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9259 return offs;
9260 offs += sizeof(encoded);
9263 file->typdesc_seg.len += sizeof(encoded);
9264 if(!file->typdesc_seg.data)
9265 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9266 else
9267 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9269 memcpy(&data[offs], encoded, sizeof(encoded));
9271 return offs;
9274 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9276 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9277 DWORD ret = cdguids_seg->len, offs;
9278 MSFT_CDGuid *cdguid = cdguids_seg->data;
9279 TLBCustData *cd;
9281 if(list_empty(custdata_list))
9282 return -1;
9284 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9285 if(!cdguids_seg->data){
9286 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9287 }else
9288 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9290 offs = ret + sizeof(MSFT_CDGuid);
9291 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9292 cdguid->GuidOffset = cd->guid->offset;
9293 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9294 cdguid->next = offs;
9295 offs += sizeof(MSFT_CDGuid);
9296 ++cdguid;
9299 --cdguid;
9300 cdguid->next = -1;
9302 return ret;
9305 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9306 WMSFT_TLBFile *file)
9308 WMSFT_SegContents *aux_seg = &file->aux_seg;
9309 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9310 MSFT_VarRecord *varrecord;
9311 MSFT_FuncRecord *funcrecord;
9312 MEMBERID *memid;
9313 DWORD *name, *offsets, offs;
9315 for(i = 0; i < info->cFuncs; ++i){
9316 TLBFuncDesc *desc = &info->funcdescs[i];
9318 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9320 /* optional fields */
9321 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9322 if(!list_empty(&desc->custdata_list))
9323 recorded_size += 7 * sizeof(INT);
9324 else if(desc->HelpStringContext != 0)
9325 recorded_size += 6 * sizeof(INT);
9326 /* res9? resA? */
9327 else if(desc->Entry)
9328 recorded_size += 3 * sizeof(INT);
9329 else if(desc->HelpString)
9330 recorded_size += 2 * sizeof(INT);
9331 else if(desc->helpcontext)
9332 recorded_size += sizeof(INT);
9334 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9336 for(j = 0; j < desc->funcdesc.cParams; ++j){
9337 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9338 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9339 break;
9343 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9346 for(i = 0; i < info->cVars; ++i){
9347 TLBVarDesc *desc = &info->vardescs[i];
9349 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9351 /* optional fields */
9352 if(desc->HelpStringContext != 0)
9353 recorded_size += 5 * sizeof(INT);
9354 else if(!list_empty(&desc->custdata_list))
9355 recorded_size += 4 * sizeof(INT);
9356 /* res9? */
9357 else if(desc->HelpString)
9358 recorded_size += 2 * sizeof(INT);
9359 else if(desc->HelpContext != 0)
9360 recorded_size += sizeof(INT);
9362 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9365 if(!recorded_size && !extra_size)
9366 return ret;
9368 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9370 aux_seg->len += recorded_size + extra_size;
9372 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9374 if(aux_seg->data)
9375 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9376 else
9377 aux_seg->data = heap_alloc(aux_seg->len);
9379 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9381 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9382 offs = 0;
9384 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9385 for(i = 0; i < info->cFuncs; ++i){
9386 TLBFuncDesc *desc = &info->funcdescs[i];
9387 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9389 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9390 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9391 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9392 funcrecord->VtableOffset = desc->funcdesc.oVft;
9394 /* FKCCIC:
9395 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9396 * ^^^funckind
9397 * ^^^ ^invkind
9398 * ^has_cust_data
9399 * ^^^^callconv
9400 * ^has_param_defaults
9401 * ^oEntry_is_intresource
9403 funcrecord->FKCCIC =
9404 desc->funcdesc.funckind |
9405 (desc->funcdesc.invkind << 3) |
9406 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9407 (desc->funcdesc.callconv << 8);
9409 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9410 funcrecord->FKCCIC |= 0x2000;
9412 for(j = 0; j < desc->funcdesc.cParams; ++j){
9413 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9414 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9415 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9418 if(paramdefault_size > 0)
9419 funcrecord->FKCCIC |= 0x1000;
9421 funcrecord->nrargs = desc->funcdesc.cParams;
9422 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9424 /* optional fields */
9425 /* res9? resA? */
9426 if(!list_empty(&desc->custdata_list)){
9427 size += 7 * sizeof(INT);
9428 funcrecord->HelpContext = desc->helpcontext;
9429 if(desc->HelpString)
9430 funcrecord->oHelpString = desc->HelpString->offset;
9431 else
9432 funcrecord->oHelpString = -1;
9433 if(!desc->Entry)
9434 funcrecord->oEntry = -1;
9435 else if(IS_INTRESOURCE(desc->Entry))
9436 funcrecord->oEntry = LOWORD(desc->Entry);
9437 else
9438 funcrecord->oEntry = desc->Entry->offset;
9439 funcrecord->res9 = -1;
9440 funcrecord->resA = -1;
9441 funcrecord->HelpStringContext = desc->HelpStringContext;
9442 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9443 }else if(desc->HelpStringContext != 0){
9444 size += 6 * sizeof(INT);
9445 funcrecord->HelpContext = desc->helpcontext;
9446 if(desc->HelpString)
9447 funcrecord->oHelpString = desc->HelpString->offset;
9448 else
9449 funcrecord->oHelpString = -1;
9450 if(!desc->Entry)
9451 funcrecord->oEntry = -1;
9452 else if(IS_INTRESOURCE(desc->Entry))
9453 funcrecord->oEntry = LOWORD(desc->Entry);
9454 else
9455 funcrecord->oEntry = desc->Entry->offset;
9456 funcrecord->res9 = -1;
9457 funcrecord->resA = -1;
9458 funcrecord->HelpStringContext = desc->HelpStringContext;
9459 }else if(desc->Entry){
9460 size += 3 * sizeof(INT);
9461 funcrecord->HelpContext = desc->helpcontext;
9462 if(desc->HelpString)
9463 funcrecord->oHelpString = desc->HelpString->offset;
9464 else
9465 funcrecord->oHelpString = -1;
9466 if(!desc->Entry)
9467 funcrecord->oEntry = -1;
9468 else if(IS_INTRESOURCE(desc->Entry))
9469 funcrecord->oEntry = LOWORD(desc->Entry);
9470 else
9471 funcrecord->oEntry = desc->Entry->offset;
9472 }else if(desc->HelpString){
9473 size += 2 * sizeof(INT);
9474 funcrecord->HelpContext = desc->helpcontext;
9475 funcrecord->oHelpString = desc->HelpString->offset;
9476 }else if(desc->helpcontext){
9477 size += sizeof(INT);
9478 funcrecord->HelpContext = desc->helpcontext;
9481 paramdefault = (DWORD*)((char *)funcrecord + size);
9482 size += paramdefault_size;
9484 for(j = 0; j < desc->funcdesc.cParams; ++j){
9485 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9487 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9488 if(desc->pParamDesc[j].Name)
9489 info->oName = desc->pParamDesc[j].Name->offset;
9490 else
9491 info->oName = -1;
9492 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9494 if(paramdefault_size){
9495 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9496 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9497 else if(paramdefault_size)
9498 *paramdefault = -1;
9499 ++paramdefault;
9502 size += sizeof(MSFT_ParameterInfo);
9505 funcrecord->Info = size | (i << 16); /* is it just the index? */
9507 *offsets = offs;
9508 offs += size;
9509 ++offsets;
9511 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9514 varrecord = (MSFT_VarRecord*)funcrecord;
9515 for(i = 0; i < info->cVars; ++i){
9516 TLBVarDesc *desc = &info->vardescs[i];
9517 DWORD size = 5 * sizeof(INT);
9519 varrecord->vardescsize = sizeof(desc->vardesc);
9520 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9521 varrecord->Flags = desc->vardesc.wVarFlags;
9522 varrecord->VarKind = desc->vardesc.varkind;
9524 if(desc->vardesc.varkind == VAR_CONST){
9525 varrecord->vardescsize += sizeof(VARIANT);
9526 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9527 }else
9528 varrecord->OffsValue = desc->vardesc.u.oInst;
9530 /* res9? */
9531 if(desc->HelpStringContext != 0){
9532 size += 5 * sizeof(INT);
9533 varrecord->HelpContext = desc->HelpContext;
9534 if(desc->HelpString)
9535 varrecord->HelpString = desc->HelpString->offset;
9536 else
9537 varrecord->HelpString = -1;
9538 varrecord->res9 = -1;
9539 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9540 varrecord->HelpStringContext = desc->HelpStringContext;
9541 }else if(!list_empty(&desc->custdata_list)){
9542 size += 4 * sizeof(INT);
9543 varrecord->HelpContext = desc->HelpContext;
9544 if(desc->HelpString)
9545 varrecord->HelpString = desc->HelpString->offset;
9546 else
9547 varrecord->HelpString = -1;
9548 varrecord->res9 = -1;
9549 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9550 }else if(desc->HelpString){
9551 size += 2 * sizeof(INT);
9552 varrecord->HelpContext = desc->HelpContext;
9553 if(desc->HelpString)
9554 varrecord->HelpString = desc->HelpString->offset;
9555 else
9556 varrecord->HelpString = -1;
9557 }else if(desc->HelpContext != 0){
9558 size += sizeof(INT);
9559 varrecord->HelpContext = desc->HelpContext;
9562 varrecord->Info = size | (i << 16);
9564 *offsets = offs;
9565 offs += size;
9566 ++offsets;
9568 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9571 memid = (MEMBERID*)varrecord;
9572 for(i = 0; i < info->cFuncs; ++i){
9573 TLBFuncDesc *desc = &info->funcdescs[i];
9574 *memid = desc->funcdesc.memid;
9575 ++memid;
9577 for(i = 0; i < info->cVars; ++i){
9578 TLBVarDesc *desc = &info->vardescs[i];
9579 *memid = desc->vardesc.memid;
9580 ++memid;
9583 name = (UINT*)memid;
9584 for(i = 0; i < info->cFuncs; ++i){
9585 TLBFuncDesc *desc = &info->funcdescs[i];
9586 if(desc->Name)
9587 *name = desc->Name->offset;
9588 else
9589 *name = -1;
9590 ++name;
9592 for(i = 0; i < info->cVars; ++i){
9593 TLBVarDesc *desc = &info->vardescs[i];
9594 if(desc->Name)
9595 *name = desc->Name->offset;
9596 else
9597 *name = -1;
9598 ++name;
9601 return ret;
9604 typedef struct tagWMSFT_RefChunk {
9605 DWORD href;
9606 DWORD res04;
9607 DWORD res08;
9608 DWORD next;
9609 } WMSFT_RefChunk;
9611 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9613 DWORD offs = file->ref_seg.len, i;
9614 WMSFT_RefChunk *chunk;
9616 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9617 if(!file->ref_seg.data)
9618 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9619 else
9620 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9622 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9624 for(i = 0; i < info->cImplTypes; ++i){
9625 chunk->href = info->impltypes[i].hRef;
9626 chunk->res04 = info->impltypes[i].implflags;
9627 chunk->res08 = -1;
9628 if(i < info->cImplTypes - 1)
9629 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9630 else
9631 chunk->next = -1;
9632 ++chunk;
9635 return offs;
9638 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9640 DWORD size;
9642 size = sizeof(MSFT_TypeInfoBase);
9644 if(data){
9645 MSFT_TypeInfoBase *base = (void*)data;
9646 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9647 base->typekind = TKIND_DISPATCH;
9648 else
9649 base->typekind = info->typekind;
9650 base->typekind |= index << 16; /* TODO: There are some other flags here */
9651 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9652 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9653 base->res2 = 0;
9654 base->res3 = 0;
9655 base->res4 = 3;
9656 base->res5 = 0;
9657 base->cElement = (info->cVars << 16) | info->cFuncs;
9658 base->res7 = 0;
9659 base->res8 = 0;
9660 base->res9 = 0;
9661 base->resA = 0;
9662 if(info->guid)
9663 base->posguid = info->guid->offset;
9664 else
9665 base->posguid = -1;
9666 base->flags = info->wTypeFlags;
9667 if(info->Name) {
9668 base->NameOffset = info->Name->offset;
9670 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9671 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9672 }else {
9673 base->NameOffset = -1;
9675 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9676 if(info->DocString)
9677 base->docstringoffs = info->DocString->offset;
9678 else
9679 base->docstringoffs = -1;
9680 base->helpstringcontext = info->dwHelpStringContext;
9681 base->helpcontext = info->dwHelpContext;
9682 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9683 base->cImplTypes = info->cImplTypes;
9684 base->cbSizeVft = info->cbSizeVft;
9685 base->size = info->cbSizeInstance;
9686 if(info->typekind == TKIND_COCLASS){
9687 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9688 }else if(info->typekind == TKIND_ALIAS){
9689 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9690 }else if(info->typekind == TKIND_MODULE){
9691 if(info->DllName)
9692 base->datatype1 = info->DllName->offset;
9693 else
9694 base->datatype1 = -1;
9695 }else{
9696 if(info->cImplTypes > 0)
9697 base->datatype1 = info->impltypes[0].hRef;
9698 else
9699 base->datatype1 = -1;
9701 base->datatype2 = index; /* FIXME: i think there's more here */
9702 base->res18 = 0;
9703 base->res19 = -1;
9706 return size;
9709 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9711 UINT i;
9713 file->typeinfo_seg.len = 0;
9714 for(i = 0; i < This->TypeInfoCount; ++i){
9715 ITypeInfoImpl *info = This->typeinfos[i];
9716 *junk = file->typeinfo_seg.len;
9717 ++junk;
9718 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9721 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9722 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9724 file->aux_seg.len = 0;
9725 file->aux_seg.data = NULL;
9727 file->typeinfo_seg.len = 0;
9728 for(i = 0; i < This->TypeInfoCount; ++i){
9729 ITypeInfoImpl *info = This->typeinfos[i];
9730 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9731 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9735 typedef struct tagWMSFT_ImpFile {
9736 INT guid_offs;
9737 LCID lcid;
9738 DWORD version;
9739 } WMSFT_ImpFile;
9741 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9743 TLBImpLib *implib;
9744 WMSFT_ImpFile *impfile;
9745 char *data;
9746 DWORD last_offs = 0;
9748 file->impfile_seg.len = 0;
9749 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9750 int size = 0;
9752 if(implib->name){
9753 WCHAR *path = strrchrW(implib->name, '\\');
9754 if(path)
9755 ++path;
9756 else
9757 path = implib->name;
9758 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9759 if (size == 0)
9760 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9763 size += sizeof(INT16);
9764 if (size % 4)
9765 size = (size + 4) & ~0x3;
9766 if (size < 8)
9767 size = 8;
9769 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9772 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9774 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9775 int strlen = 0, size;
9777 impfile = (WMSFT_ImpFile*)data;
9778 impfile->guid_offs = implib->guid->offset;
9779 impfile->lcid = implib->lcid;
9780 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9782 data += sizeof(WMSFT_ImpFile);
9784 if(implib->name){
9785 WCHAR *path= strrchrW(implib->name, '\\');
9786 if(path)
9787 ++path;
9788 else
9789 path = implib->name;
9790 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9791 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9792 if (strlen == 0)
9793 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9796 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9798 size = strlen + sizeof(INT16);
9799 if (size % 4)
9800 size = (size + 4) & ~0x3;
9801 if (size < 8)
9802 size = 8;
9803 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9805 data += size;
9806 implib->offset = last_offs;
9807 last_offs += size + sizeof(WMSFT_ImpFile);
9811 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9813 MSFT_ImpInfo *info;
9814 TLBRefType *ref_type;
9815 UINT i = 0;
9817 WMSFT_compile_impfile(This, file);
9819 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9820 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9822 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9823 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9824 if(ref_type->index == TLB_REF_USE_GUID){
9825 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9826 info->oGuid = ref_type->guid->offset;
9827 }else
9828 info->oGuid = ref_type->index;
9829 info->oImpFile = ref_type->pImpTLInfo->offset;
9830 ++i;
9831 ++info;
9835 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9837 file->guidhash_seg.len = 0x80;
9838 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9839 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9842 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9844 file->namehash_seg.len = 0x200;
9845 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9846 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9849 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9851 if(contents && contents->len){
9852 segdir->offset = *running_offset;
9853 segdir->length = contents->len;
9854 *running_offset += segdir->length;
9855 }else{
9856 segdir->offset = -1;
9857 segdir->length = 0;
9860 /* TODO: do these ever change? */
9861 segdir->res08 = -1;
9862 segdir->res0c = 0xf;
9865 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9867 DWORD written;
9868 if(segment)
9869 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9872 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9873 DWORD file_len)
9875 DWORD i;
9876 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9878 for(i = 0; i < This->TypeInfoCount; ++i){
9879 base->memoffset += file_len;
9880 ++base;
9883 return S_OK;
9886 static void WMSFT_free_file(WMSFT_TLBFile *file)
9888 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9889 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9890 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9891 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9892 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9893 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9894 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9895 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9896 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9897 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9898 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9899 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9900 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9901 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9904 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9906 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9907 WMSFT_TLBFile file;
9908 DWORD written, junk_size, junk_offs, running_offset;
9909 BOOL br;
9910 HANDLE outfile;
9911 HRESULT hres;
9912 DWORD *junk;
9913 UINT i;
9915 TRACE("%p\n", This);
9917 for(i = 0; i < This->TypeInfoCount; ++i)
9918 if(This->typeinfos[i]->needs_layout)
9919 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9921 memset(&file, 0, sizeof(file));
9923 file.header.magic1 = 0x5446534D;
9924 file.header.magic2 = 0x00010002;
9925 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9926 file.header.lcid2 = This->set_lcid;
9927 file.header.varflags = 0x40 | This->syskind;
9928 if (This->HelpFile)
9929 file.header.varflags |= 0x10;
9930 if (This->HelpStringDll)
9931 file.header.varflags |= HELPDLLFLAG;
9932 file.header.version = (This->ver_minor << 16) | This->ver_major;
9933 file.header.flags = This->libflags;
9934 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9935 file.header.helpcontext = This->dwHelpContext;
9936 file.header.res44 = 0x20;
9937 file.header.res48 = 0x80;
9938 file.header.dispatchpos = This->dispatch_href;
9940 WMSFT_compile_namehash(This, &file);
9941 /* do name and string compilation to get offsets for other compilations */
9942 hres = WMSFT_compile_names(This, &file);
9943 if (FAILED(hres)){
9944 WMSFT_free_file(&file);
9945 return hres;
9948 hres = WMSFT_compile_strings(This, &file);
9949 if (FAILED(hres)){
9950 WMSFT_free_file(&file);
9951 return hres;
9954 WMSFT_compile_guidhash(This, &file);
9955 hres = WMSFT_compile_guids(This, &file);
9956 if (FAILED(hres)){
9957 WMSFT_free_file(&file);
9958 return hres;
9961 if(This->HelpFile)
9962 file.header.helpfile = This->HelpFile->offset;
9963 else
9964 file.header.helpfile = -1;
9966 if(This->DocString)
9967 file.header.helpstring = This->DocString->offset;
9968 else
9969 file.header.helpstring = -1;
9971 /* do some more segment compilation */
9972 file.header.nimpinfos = list_count(&This->ref_list);
9973 file.header.nrtypeinfos = This->TypeInfoCount;
9975 if(This->Name)
9976 file.header.NameOffset = This->Name->offset;
9977 else
9978 file.header.NameOffset = -1;
9980 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9982 if(This->guid)
9983 file.header.posguid = This->guid->offset;
9984 else
9985 file.header.posguid = -1;
9987 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9988 if(file.header.varflags & HELPDLLFLAG)
9989 junk_size += sizeof(DWORD);
9990 if(junk_size){
9991 junk = heap_alloc_zero(junk_size);
9992 if(file.header.varflags & HELPDLLFLAG){
9993 *junk = This->HelpStringDll->offset;
9994 junk_offs = 1;
9995 }else
9996 junk_offs = 0;
9997 }else{
9998 junk = NULL;
9999 junk_offs = 0;
10002 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10003 WMSFT_compile_impinfo(This, &file);
10005 running_offset = 0;
10007 TRACE("header at: 0x%x\n", running_offset);
10008 running_offset += sizeof(file.header);
10010 TRACE("junk at: 0x%x\n", running_offset);
10011 running_offset += junk_size;
10013 TRACE("segdir at: 0x%x\n", running_offset);
10014 running_offset += sizeof(file.segdir);
10016 TRACE("typeinfo at: 0x%x\n", running_offset);
10017 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10019 TRACE("guidhashtab at: 0x%x\n", running_offset);
10020 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10022 TRACE("guidtab at: 0x%x\n", running_offset);
10023 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10025 TRACE("reftab at: 0x%x\n", running_offset);
10026 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10028 TRACE("impinfo at: 0x%x\n", running_offset);
10029 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10031 TRACE("impfiles at: 0x%x\n", running_offset);
10032 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10034 TRACE("namehashtab at: 0x%x\n", running_offset);
10035 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10037 TRACE("nametab at: 0x%x\n", running_offset);
10038 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10040 TRACE("stringtab at: 0x%x\n", running_offset);
10041 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10043 TRACE("typdesc at: 0x%x\n", running_offset);
10044 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10046 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10047 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10049 TRACE("custdata at: 0x%x\n", running_offset);
10050 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10052 TRACE("cdguids at: 0x%x\n", running_offset);
10053 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10055 TRACE("res0e at: 0x%x\n", running_offset);
10056 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10058 TRACE("res0f at: 0x%x\n", running_offset);
10059 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10061 TRACE("aux_seg at: 0x%x\n", running_offset);
10063 WMSFT_fixup_typeinfos(This, &file, running_offset);
10065 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10066 FILE_ATTRIBUTE_NORMAL, 0);
10067 if (outfile == INVALID_HANDLE_VALUE){
10068 WMSFT_free_file(&file);
10069 heap_free(junk);
10070 return TYPE_E_IOERROR;
10073 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10074 if (!br) {
10075 WMSFT_free_file(&file);
10076 CloseHandle(outfile);
10077 heap_free(junk);
10078 return TYPE_E_IOERROR;
10081 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10082 heap_free(junk);
10083 if (!br) {
10084 WMSFT_free_file(&file);
10085 CloseHandle(outfile);
10086 return TYPE_E_IOERROR;
10089 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10090 if (!br) {
10091 WMSFT_free_file(&file);
10092 CloseHandle(outfile);
10093 return TYPE_E_IOERROR;
10096 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10097 WMSFT_write_segment(outfile, &file.guidhash_seg);
10098 WMSFT_write_segment(outfile, &file.guid_seg);
10099 WMSFT_write_segment(outfile, &file.ref_seg);
10100 WMSFT_write_segment(outfile, &file.impinfo_seg);
10101 WMSFT_write_segment(outfile, &file.impfile_seg);
10102 WMSFT_write_segment(outfile, &file.namehash_seg);
10103 WMSFT_write_segment(outfile, &file.name_seg);
10104 WMSFT_write_segment(outfile, &file.string_seg);
10105 WMSFT_write_segment(outfile, &file.typdesc_seg);
10106 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10107 WMSFT_write_segment(outfile, &file.custdata_seg);
10108 WMSFT_write_segment(outfile, &file.cdguids_seg);
10109 WMSFT_write_segment(outfile, &file.aux_seg);
10111 WMSFT_free_file(&file);
10113 CloseHandle(outfile);
10115 return S_OK;
10118 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10119 LPOLESTR name)
10121 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10122 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10123 return E_NOTIMPL;
10126 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10127 REFGUID guid, VARIANT *varVal)
10129 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10130 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
10131 return E_NOTIMPL;
10134 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10135 ULONG helpStringContext)
10137 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10138 FIXME("%p %u - stub\n", This, helpStringContext);
10139 return E_NOTIMPL;
10142 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10143 LPOLESTR filename)
10145 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10146 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10148 if (!filename)
10149 return E_INVALIDARG;
10151 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10153 return S_OK;
10156 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10157 ICreateTypeLib2_fnQueryInterface,
10158 ICreateTypeLib2_fnAddRef,
10159 ICreateTypeLib2_fnRelease,
10160 ICreateTypeLib2_fnCreateTypeInfo,
10161 ICreateTypeLib2_fnSetName,
10162 ICreateTypeLib2_fnSetVersion,
10163 ICreateTypeLib2_fnSetGuid,
10164 ICreateTypeLib2_fnSetDocString,
10165 ICreateTypeLib2_fnSetHelpFileName,
10166 ICreateTypeLib2_fnSetHelpContext,
10167 ICreateTypeLib2_fnSetLcid,
10168 ICreateTypeLib2_fnSetLibFlags,
10169 ICreateTypeLib2_fnSaveAllChanges,
10170 ICreateTypeLib2_fnDeleteTypeInfo,
10171 ICreateTypeLib2_fnSetCustData,
10172 ICreateTypeLib2_fnSetHelpStringContext,
10173 ICreateTypeLib2_fnSetHelpStringDll
10176 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10177 REFIID riid, void **object)
10179 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10181 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10184 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10186 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10188 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10191 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10193 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10195 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10198 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10199 REFGUID guid)
10201 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10203 TRACE("%p %s\n", This, debugstr_guid(guid));
10205 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10207 return S_OK;
10210 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10211 UINT typeFlags)
10213 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10214 WORD old_flags;
10215 HRESULT hres;
10217 TRACE("%p %x\n", This, typeFlags);
10219 if (typeFlags & TYPEFLAG_FDUAL) {
10220 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10221 ITypeLib *stdole;
10222 ITypeInfo *dispatch;
10223 HREFTYPE hreftype;
10224 HRESULT hres;
10226 hres = LoadTypeLib(stdole2tlb, &stdole);
10227 if(FAILED(hres))
10228 return hres;
10230 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10231 ITypeLib_Release(stdole);
10232 if(FAILED(hres))
10233 return hres;
10235 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10236 ITypeInfo_Release(dispatch);
10237 if(FAILED(hres))
10238 return hres;
10241 old_flags = This->wTypeFlags;
10242 This->wTypeFlags = typeFlags;
10244 hres = ICreateTypeInfo2_LayOut(iface);
10245 if (FAILED(hres)) {
10246 This->wTypeFlags = old_flags;
10247 return hres;
10250 return S_OK;
10253 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10254 LPOLESTR doc)
10256 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10258 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10260 if (!doc)
10261 return E_INVALIDARG;
10263 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10265 return S_OK;
10268 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10269 DWORD helpContext)
10271 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10273 TRACE("%p %d\n", This, helpContext);
10275 This->dwHelpContext = helpContext;
10277 return S_OK;
10280 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10281 WORD majorVerNum, WORD minorVerNum)
10283 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10285 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10287 This->wMajorVerNum = majorVerNum;
10288 This->wMinorVerNum = minorVerNum;
10290 return S_OK;
10293 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10294 ITypeInfo *typeInfo, HREFTYPE *refType)
10296 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10297 UINT index;
10298 ITypeLib *container;
10299 TLBRefType *ref_type;
10300 TLBImpLib *implib;
10301 TYPEATTR *typeattr;
10302 TLIBATTR *libattr;
10303 HRESULT hres;
10305 TRACE("%p %p %p\n", This, typeInfo, refType);
10307 if (!typeInfo || !refType)
10308 return E_INVALIDARG;
10310 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10311 if (FAILED(hres))
10312 return hres;
10314 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10315 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10317 ITypeLib_Release(container);
10319 *refType = target->hreftype;
10321 return S_OK;
10324 hres = ITypeLib_GetLibAttr(container, &libattr);
10325 if (FAILED(hres)) {
10326 ITypeLib_Release(container);
10327 return hres;
10330 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10331 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10332 implib->lcid == libattr->lcid &&
10333 implib->wVersionMajor == libattr->wMajorVerNum &&
10334 implib->wVersionMinor == libattr->wMinorVerNum)
10335 break;
10338 if(&implib->entry == &This->pTypeLib->implib_list){
10339 implib = heap_alloc_zero(sizeof(TLBImpLib));
10341 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10342 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10343 implib->name = SysAllocString(our_container->path);
10344 }else{
10345 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10346 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10347 if(FAILED(hres)){
10348 implib->name = NULL;
10349 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10353 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10354 implib->lcid = libattr->lcid;
10355 implib->wVersionMajor = libattr->wMajorVerNum;
10356 implib->wVersionMinor = libattr->wMinorVerNum;
10358 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10361 ITypeLib_ReleaseTLibAttr(container, libattr);
10362 ITypeLib_Release(container);
10364 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10365 if (FAILED(hres))
10366 return hres;
10368 index = 0;
10369 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10370 if(ref_type->index == TLB_REF_USE_GUID &&
10371 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10372 ref_type->tkind == typeattr->typekind)
10373 break;
10374 ++index;
10377 if(&ref_type->entry == &This->pTypeLib->ref_list){
10378 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10380 ref_type->tkind = typeattr->typekind;
10381 ref_type->pImpTLInfo = implib;
10382 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10384 ref_type->index = TLB_REF_USE_GUID;
10386 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10388 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10391 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10393 *refType = ref_type->reference | 0x1;
10395 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10396 This->pTypeLib->dispatch_href = *refType;
10398 return S_OK;
10401 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10402 UINT index, FUNCDESC *funcDesc)
10404 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10405 TLBFuncDesc tmp_func_desc, *func_desc;
10406 int buf_size, i;
10407 char *buffer;
10408 HRESULT hres;
10410 TRACE("%p %u %p\n", This, index, funcDesc);
10412 if (!funcDesc || funcDesc->oVft & 3)
10413 return E_INVALIDARG;
10415 switch (This->typekind) {
10416 case TKIND_MODULE:
10417 if (funcDesc->funckind != FUNC_STATIC)
10418 return TYPE_E_BADMODULEKIND;
10419 break;
10420 case TKIND_DISPATCH:
10421 if (funcDesc->funckind != FUNC_DISPATCH)
10422 return TYPE_E_BADMODULEKIND;
10423 break;
10424 default:
10425 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10426 return TYPE_E_BADMODULEKIND;
10429 if (index > This->cFuncs)
10430 return TYPE_E_ELEMENTNOTFOUND;
10432 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10433 !funcDesc->cParams)
10434 return TYPE_E_INCONSISTENTPROPFUNCS;
10436 #ifdef _WIN64
10437 if(This->pTypeLib->syskind == SYS_WIN64 &&
10438 funcDesc->oVft % 8 != 0)
10439 return E_INVALIDARG;
10440 #endif
10442 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10443 TLBFuncDesc_Constructor(&tmp_func_desc);
10445 tmp_func_desc.funcdesc = *funcDesc;
10447 if (tmp_func_desc.funcdesc.oVft != 0)
10448 tmp_func_desc.funcdesc.oVft |= 1;
10450 if (funcDesc->cScodes) {
10451 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10452 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10453 } else
10454 tmp_func_desc.funcdesc.lprgscode = NULL;
10456 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10457 for (i = 0; i < funcDesc->cParams; ++i) {
10458 buf_size += sizeof(ELEMDESC);
10459 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10461 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10462 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10464 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10465 if (FAILED(hres)) {
10466 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10467 heap_free(tmp_func_desc.funcdesc.lprgscode);
10468 return hres;
10471 for (i = 0; i < funcDesc->cParams; ++i) {
10472 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10473 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10474 if (FAILED(hres)) {
10475 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10476 heap_free(tmp_func_desc.funcdesc.lprgscode);
10477 return hres;
10479 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10480 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10481 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10482 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10483 if (FAILED(hres)) {
10484 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10485 heap_free(tmp_func_desc.funcdesc.lprgscode);
10486 return hres;
10491 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10493 if (This->funcdescs) {
10494 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10495 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10497 if (index < This->cFuncs) {
10498 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10499 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10500 func_desc = This->funcdescs + index;
10501 } else
10502 func_desc = This->funcdescs + This->cFuncs;
10504 /* move custdata lists to the new memory location */
10505 for(i = 0; i < This->cFuncs + 1; ++i){
10506 if(index != i){
10507 TLBFuncDesc *fd = &This->funcdescs[i];
10508 if(fd->custdata_list.prev == fd->custdata_list.next)
10509 list_init(&fd->custdata_list);
10510 else{
10511 fd->custdata_list.prev->next = &fd->custdata_list;
10512 fd->custdata_list.next->prev = &fd->custdata_list;
10516 } else
10517 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10519 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10520 list_init(&func_desc->custdata_list);
10522 ++This->cFuncs;
10524 This->needs_layout = TRUE;
10526 return S_OK;
10529 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10530 UINT index, HREFTYPE refType)
10532 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10533 TLBImplType *impl_type;
10534 HRESULT hres;
10536 TRACE("%p %u %d\n", This, index, refType);
10538 switch(This->typekind){
10539 case TKIND_COCLASS: {
10540 if (index == -1) {
10541 FIXME("Unhandled index: -1\n");
10542 return E_NOTIMPL;
10545 if(index != This->cImplTypes)
10546 return TYPE_E_ELEMENTNOTFOUND;
10548 break;
10550 case TKIND_INTERFACE:
10551 case TKIND_DISPATCH:
10552 if (index != 0 || This->cImplTypes)
10553 return TYPE_E_ELEMENTNOTFOUND;
10554 break;
10555 default:
10556 FIXME("Unimplemented typekind: %d\n", This->typekind);
10557 return E_NOTIMPL;
10560 if (This->impltypes){
10561 UINT i;
10563 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10564 sizeof(TLBImplType) * (This->cImplTypes + 1));
10566 if (index < This->cImplTypes) {
10567 memmove(This->impltypes + index + 1, This->impltypes + index,
10568 (This->cImplTypes - index) * sizeof(TLBImplType));
10569 impl_type = This->impltypes + index;
10570 } else
10571 impl_type = This->impltypes + This->cImplTypes;
10573 /* move custdata lists to the new memory location */
10574 for(i = 0; i < This->cImplTypes + 1; ++i){
10575 if(index != i){
10576 TLBImplType *it = &This->impltypes[i];
10577 if(it->custdata_list.prev == it->custdata_list.next)
10578 list_init(&it->custdata_list);
10579 else{
10580 it->custdata_list.prev->next = &it->custdata_list;
10581 it->custdata_list.next->prev = &it->custdata_list;
10585 } else
10586 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10588 memset(impl_type, 0, sizeof(TLBImplType));
10589 TLBImplType_Constructor(impl_type);
10590 impl_type->hRef = refType;
10592 ++This->cImplTypes;
10594 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10595 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10597 hres = ICreateTypeInfo2_LayOut(iface);
10598 if (FAILED(hres))
10599 return hres;
10601 return S_OK;
10604 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10605 UINT index, INT implTypeFlags)
10607 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10608 TLBImplType *impl_type = &This->impltypes[index];
10610 TRACE("%p %u %x\n", This, index, implTypeFlags);
10612 if (This->typekind != TKIND_COCLASS)
10613 return TYPE_E_BADMODULEKIND;
10615 if (index >= This->cImplTypes)
10616 return TYPE_E_ELEMENTNOTFOUND;
10618 impl_type->implflags = implTypeFlags;
10620 return S_OK;
10623 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10624 WORD alignment)
10626 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10628 TRACE("%p %d\n", This, alignment);
10630 This->cbAlignment = alignment;
10632 return S_OK;
10635 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10636 LPOLESTR schema)
10638 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10640 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10642 if (!schema)
10643 return E_INVALIDARG;
10645 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10647 This->lpstrSchema = This->Schema->str;
10649 return S_OK;
10652 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10653 UINT index, VARDESC *varDesc)
10655 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10656 TLBVarDesc *var_desc;
10658 TRACE("%p %u %p\n", This, index, varDesc);
10660 if (This->vardescs){
10661 UINT i;
10663 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10664 sizeof(TLBVarDesc) * (This->cVars + 1));
10666 if (index < This->cVars) {
10667 memmove(This->vardescs + index + 1, This->vardescs + index,
10668 (This->cVars - index) * sizeof(TLBVarDesc));
10669 var_desc = This->vardescs + index;
10670 } else
10671 var_desc = This->vardescs + This->cVars;
10673 /* move custdata lists to the new memory location */
10674 for(i = 0; i < This->cVars + 1; ++i){
10675 if(index != i){
10676 TLBVarDesc *var = &This->vardescs[i];
10677 if(var->custdata_list.prev == var->custdata_list.next)
10678 list_init(&var->custdata_list);
10679 else{
10680 var->custdata_list.prev->next = &var->custdata_list;
10681 var->custdata_list.next->prev = &var->custdata_list;
10685 } else
10686 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10688 TLBVarDesc_Constructor(var_desc);
10689 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10690 var_desc->vardesc = *var_desc->vardesc_create;
10692 ++This->cVars;
10694 This->needs_layout = TRUE;
10696 return S_OK;
10699 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10700 UINT index, LPOLESTR *names, UINT numNames)
10702 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10703 TLBFuncDesc *func_desc = &This->funcdescs[index];
10704 int i;
10706 TRACE("%p %u %p %u\n", This, index, names, numNames);
10708 if (!names)
10709 return E_INVALIDARG;
10711 if (index >= This->cFuncs || numNames == 0)
10712 return TYPE_E_ELEMENTNOTFOUND;
10714 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10715 if(numNames > func_desc->funcdesc.cParams)
10716 return TYPE_E_ELEMENTNOTFOUND;
10717 } else
10718 if(numNames > func_desc->funcdesc.cParams + 1)
10719 return TYPE_E_ELEMENTNOTFOUND;
10721 for(i = 0; i < This->cFuncs; ++i) {
10722 TLBFuncDesc *iter = &This->funcdescs[i];
10723 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10724 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10725 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10726 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10727 continue;
10728 return TYPE_E_AMBIGUOUSNAME;
10732 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10734 for (i = 1; i < numNames; ++i) {
10735 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10736 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10739 return S_OK;
10742 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10743 UINT index, LPOLESTR name)
10745 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10747 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10749 if(!name)
10750 return E_INVALIDARG;
10752 if(index >= This->cVars)
10753 return TYPE_E_ELEMENTNOTFOUND;
10755 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10756 return S_OK;
10759 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10760 TYPEDESC *tdescAlias)
10762 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10763 HRESULT hr;
10765 TRACE("%p %p\n", This, tdescAlias);
10767 if(!tdescAlias)
10768 return E_INVALIDARG;
10770 if(This->typekind != TKIND_ALIAS)
10771 return TYPE_E_BADMODULEKIND;
10773 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->cbSizeInstance, &This->cbAlignment);
10774 if(FAILED(hr))
10775 return hr;
10777 heap_free(This->tdescAlias);
10778 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10779 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10781 return S_OK;
10784 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10785 UINT index, LPOLESTR dllName, LPOLESTR procName)
10787 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10788 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10789 return E_NOTIMPL;
10792 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10793 UINT index, LPOLESTR docString)
10795 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10796 TLBFuncDesc *func_desc = &This->funcdescs[index];
10798 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10800 if(!docString)
10801 return E_INVALIDARG;
10803 if(index >= This->cFuncs)
10804 return TYPE_E_ELEMENTNOTFOUND;
10806 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10808 return S_OK;
10811 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10812 UINT index, LPOLESTR docString)
10814 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10815 TLBVarDesc *var_desc = &This->vardescs[index];
10817 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10819 if(!docString)
10820 return E_INVALIDARG;
10822 if(index >= This->cVars)
10823 return TYPE_E_ELEMENTNOTFOUND;
10825 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10827 return S_OK;
10830 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10831 UINT index, DWORD helpContext)
10833 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10834 TLBFuncDesc *func_desc = &This->funcdescs[index];
10836 TRACE("%p %u %d\n", This, index, helpContext);
10838 if(index >= This->cFuncs)
10839 return TYPE_E_ELEMENTNOTFOUND;
10841 func_desc->helpcontext = helpContext;
10843 return S_OK;
10846 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10847 UINT index, DWORD helpContext)
10849 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10850 TLBVarDesc *var_desc = &This->vardescs[index];
10852 TRACE("%p %u %d\n", This, index, helpContext);
10854 if(index >= This->cVars)
10855 return TYPE_E_ELEMENTNOTFOUND;
10857 var_desc->HelpContext = helpContext;
10859 return S_OK;
10862 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10863 UINT index, BSTR bstrMops)
10865 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10866 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10867 return E_NOTIMPL;
10870 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10871 IDLDESC *idlDesc)
10873 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10875 TRACE("%p %p\n", This, idlDesc);
10877 if (!idlDesc)
10878 return E_INVALIDARG;
10880 This->idldescType.dwReserved = idlDesc->dwReserved;
10881 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10883 return S_OK;
10886 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10888 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10889 ITypeInfo *tinfo;
10890 TLBFuncDesc *func_desc;
10891 UINT user_vft = 0, i, depth = 0;
10892 HRESULT hres = S_OK;
10894 TRACE("%p\n", This);
10896 This->needs_layout = FALSE;
10898 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10899 if (FAILED(hres))
10900 return hres;
10902 if (This->typekind == TKIND_INTERFACE) {
10903 ITypeInfo *inh;
10904 TYPEATTR *attr;
10905 HREFTYPE inh_href;
10907 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10909 if (SUCCEEDED(hres)) {
10910 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10912 if (SUCCEEDED(hres)) {
10913 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10914 if (FAILED(hres)) {
10915 ITypeInfo_Release(inh);
10916 ITypeInfo_Release(tinfo);
10917 return hres;
10919 This->cbSizeVft = attr->cbSizeVft;
10920 ITypeInfo_ReleaseTypeAttr(inh, attr);
10923 ++depth;
10924 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10925 if(SUCCEEDED(hres)){
10926 ITypeInfo *next;
10927 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10928 if(SUCCEEDED(hres)){
10929 ITypeInfo_Release(inh);
10930 inh = next;
10933 }while(SUCCEEDED(hres));
10934 hres = S_OK;
10936 ITypeInfo_Release(inh);
10937 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10938 This->cbSizeVft = 0;
10939 hres = S_OK;
10940 } else {
10941 ITypeInfo_Release(tinfo);
10942 return hres;
10944 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10945 This->cbSizeVft = 0;
10946 hres = S_OK;
10947 } else {
10948 ITypeInfo_Release(tinfo);
10949 return hres;
10951 } else if (This->typekind == TKIND_DISPATCH)
10952 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10953 else
10954 This->cbSizeVft = 0;
10956 func_desc = This->funcdescs;
10957 i = 0;
10958 while (i < This->cFuncs) {
10959 if (!(func_desc->funcdesc.oVft & 0x1))
10960 func_desc->funcdesc.oVft = This->cbSizeVft;
10962 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10963 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10965 This->cbSizeVft += This->pTypeLib->ptr_size;
10967 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10968 TLBFuncDesc *iter;
10969 UINT j = 0;
10970 BOOL reset = FALSE;
10972 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10974 iter = This->funcdescs;
10975 while (j < This->cFuncs) {
10976 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10977 if (!reset) {
10978 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10979 reset = TRUE;
10980 } else
10981 ++func_desc->funcdesc.memid;
10982 iter = This->funcdescs;
10983 j = 0;
10984 } else {
10985 ++iter;
10986 ++j;
10991 ++func_desc;
10992 ++i;
10995 if (user_vft > This->cbSizeVft)
10996 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10998 for(i = 0; i < This->cVars; ++i){
10999 TLBVarDesc *var_desc = &This->vardescs[i];
11000 if(var_desc->vardesc.memid == MEMBERID_NIL){
11001 UINT j = 0;
11002 BOOL reset = FALSE;
11003 TLBVarDesc *iter;
11005 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11007 iter = This->vardescs;
11008 while (j < This->cVars) {
11009 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11010 if (!reset) {
11011 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->cVars;
11012 reset = TRUE;
11013 } else
11014 ++var_desc->vardesc.memid;
11015 iter = This->vardescs;
11016 j = 0;
11017 } else {
11018 ++iter;
11019 ++j;
11025 ITypeInfo_Release(tinfo);
11026 return hres;
11029 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11030 UINT index)
11032 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11033 FIXME("%p %u - stub\n", This, index);
11034 return E_NOTIMPL;
11037 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11038 MEMBERID memid, INVOKEKIND invKind)
11040 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11041 FIXME("%p %x %d - stub\n", This, memid, invKind);
11042 return E_NOTIMPL;
11045 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11046 UINT index)
11048 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11049 FIXME("%p %u - stub\n", This, index);
11050 return E_NOTIMPL;
11053 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11054 MEMBERID memid)
11056 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11057 FIXME("%p %x - stub\n", This, memid);
11058 return E_NOTIMPL;
11061 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11062 UINT index)
11064 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11065 FIXME("%p %u - stub\n", This, index);
11066 return E_NOTIMPL;
11069 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11070 REFGUID guid, VARIANT *varVal)
11072 TLBGuid *tlbguid;
11074 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11076 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11078 if (!guid || !varVal)
11079 return E_INVALIDARG;
11081 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11083 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11086 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11087 UINT index, REFGUID guid, VARIANT *varVal)
11089 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11090 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11091 return E_NOTIMPL;
11094 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11095 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11097 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11098 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11099 return E_NOTIMPL;
11102 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11103 UINT index, REFGUID guid, VARIANT *varVal)
11105 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11106 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11107 return E_NOTIMPL;
11110 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11111 UINT index, REFGUID guid, VARIANT *varVal)
11113 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11114 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11115 return E_NOTIMPL;
11118 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11119 ULONG helpStringContext)
11121 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11123 TRACE("%p %u\n", This, helpStringContext);
11125 This->dwHelpStringContext = helpStringContext;
11127 return S_OK;
11130 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11131 UINT index, ULONG helpStringContext)
11133 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11134 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11135 return E_NOTIMPL;
11138 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11139 UINT index, ULONG helpStringContext)
11141 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11142 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11143 return E_NOTIMPL;
11146 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11148 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11149 FIXME("%p - stub\n", This);
11150 return E_NOTIMPL;
11153 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11154 LPOLESTR name)
11156 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11158 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11160 if (!name)
11161 return E_INVALIDARG;
11163 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11165 return S_OK;
11168 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11169 ICreateTypeInfo2_fnQueryInterface,
11170 ICreateTypeInfo2_fnAddRef,
11171 ICreateTypeInfo2_fnRelease,
11172 ICreateTypeInfo2_fnSetGuid,
11173 ICreateTypeInfo2_fnSetTypeFlags,
11174 ICreateTypeInfo2_fnSetDocString,
11175 ICreateTypeInfo2_fnSetHelpContext,
11176 ICreateTypeInfo2_fnSetVersion,
11177 ICreateTypeInfo2_fnAddRefTypeInfo,
11178 ICreateTypeInfo2_fnAddFuncDesc,
11179 ICreateTypeInfo2_fnAddImplType,
11180 ICreateTypeInfo2_fnSetImplTypeFlags,
11181 ICreateTypeInfo2_fnSetAlignment,
11182 ICreateTypeInfo2_fnSetSchema,
11183 ICreateTypeInfo2_fnAddVarDesc,
11184 ICreateTypeInfo2_fnSetFuncAndParamNames,
11185 ICreateTypeInfo2_fnSetVarName,
11186 ICreateTypeInfo2_fnSetTypeDescAlias,
11187 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11188 ICreateTypeInfo2_fnSetFuncDocString,
11189 ICreateTypeInfo2_fnSetVarDocString,
11190 ICreateTypeInfo2_fnSetFuncHelpContext,
11191 ICreateTypeInfo2_fnSetVarHelpContext,
11192 ICreateTypeInfo2_fnSetMops,
11193 ICreateTypeInfo2_fnSetTypeIdldesc,
11194 ICreateTypeInfo2_fnLayOut,
11195 ICreateTypeInfo2_fnDeleteFuncDesc,
11196 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11197 ICreateTypeInfo2_fnDeleteVarDesc,
11198 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11199 ICreateTypeInfo2_fnDeleteImplType,
11200 ICreateTypeInfo2_fnSetCustData,
11201 ICreateTypeInfo2_fnSetFuncCustData,
11202 ICreateTypeInfo2_fnSetParamCustData,
11203 ICreateTypeInfo2_fnSetVarCustData,
11204 ICreateTypeInfo2_fnSetImplTypeCustData,
11205 ICreateTypeInfo2_fnSetHelpStringContext,
11206 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11207 ICreateTypeInfo2_fnSetVarHelpStringContext,
11208 ICreateTypeInfo2_fnInvalidate,
11209 ICreateTypeInfo2_fnSetName
11212 /******************************************************************************
11213 * ClearCustData (OLEAUT32.171)
11215 * Clear a custom data type's data.
11217 * PARAMS
11218 * lpCust [I] The custom data type instance
11220 * RETURNS
11221 * Nothing.
11223 void WINAPI ClearCustData(CUSTDATA *lpCust)
11225 if (lpCust && lpCust->cCustData)
11227 if (lpCust->prgCustData)
11229 DWORD i;
11231 for (i = 0; i < lpCust->cCustData; i++)
11232 VariantClear(&lpCust->prgCustData[i].varValue);
11234 /* FIXME - Should be using a per-thread IMalloc */
11235 heap_free(lpCust->prgCustData);
11236 lpCust->prgCustData = NULL;
11238 lpCust->cCustData = 0;