oleaut32: Improve ITypeLib::FindName.
[wine.git] / dlls / oleaut32 / typelib.c
blobe5a99e8718b9299769bda0a20e36cc668b7c5215
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
45 * behaviour.
46 * -. lousy fatal error handling
50 #include "config.h"
51 #include "wine/port.h"
53 #include <stdlib.h>
54 #include <string.h>
55 #include <stdarg.h>
56 #include <stdio.h>
57 #include <ctype.h>
59 #define COBJMACROS
60 #define NONAMELESSUNION
61 #define NONAMELESSSTRUCT
63 #include "winerror.h"
64 #include "windef.h"
65 #include "winbase.h"
66 #include "winnls.h"
67 #include "winreg.h"
68 #include "winuser.h"
69 #include "winternl.h"
70 #include "lzexpand.h"
72 #include "wine/unicode.h"
73 #include "objbase.h"
74 #include "typelib.h"
75 #include "wine/debug.h"
76 #include "variant.h"
77 #include "wine/list.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(ole);
80 WINE_DECLARE_DEBUG_CHANNEL(typelib);
82 typedef struct
84 WORD offset;
85 WORD length;
86 WORD flags;
87 WORD id;
88 WORD handle;
89 WORD usage;
90 } NE_NAMEINFO;
92 typedef struct
94 WORD type_id; /* Type identifier */
95 WORD count; /* Number of resources of this type */
96 DWORD resloader; /* SetResourceHandler() */
98 * Name info array.
100 } NE_TYPEINFO;
102 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
103 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
104 static void TLB_FreeVarDesc(VARDESC*);
106 /****************************************************************************
107 * FromLExxx
109 * Takes p_iVal (which is in little endian) and returns it
110 * in the host machine's byte order.
112 #ifdef WORDS_BIGENDIAN
113 static WORD FromLEWord(WORD p_iVal)
115 return (((p_iVal & 0x00FF) << 8) |
116 ((p_iVal & 0xFF00) >> 8));
120 static DWORD FromLEDWord(DWORD p_iVal)
122 return (((p_iVal & 0x000000FF) << 24) |
123 ((p_iVal & 0x0000FF00) << 8) |
124 ((p_iVal & 0x00FF0000) >> 8) |
125 ((p_iVal & 0xFF000000) >> 24));
127 #else
128 #define FromLEWord(X) (X)
129 #define FromLEDWord(X) (X)
130 #endif
132 #define DISPATCH_HREF_OFFSET 0x01000000
133 #define DISPATCH_HREF_MASK 0xff000000
135 /****************************************************************************
136 * FromLExxx
138 * Fix byte order in any structure if necessary
140 #ifdef WORDS_BIGENDIAN
141 static void FromLEWords(void *p_Val, int p_iSize)
143 WORD *Val = p_Val;
145 p_iSize /= sizeof(WORD);
147 while (p_iSize) {
148 *Val = FromLEWord(*Val);
149 Val++;
150 p_iSize--;
155 static void FromLEDWords(void *p_Val, int p_iSize)
157 DWORD *Val = p_Val;
159 p_iSize /= sizeof(DWORD);
161 while (p_iSize) {
162 *Val = FromLEDWord(*Val);
163 Val++;
164 p_iSize--;
167 #else
168 #define FromLEWords(X,Y) /*nothing*/
169 #define FromLEDWords(X,Y) /*nothing*/
170 #endif
173 * Find a typelib key which matches a requested maj.min version.
175 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
177 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
178 WCHAR buffer[60];
179 char key_name[16];
180 DWORD len, i;
181 INT best_maj = -1, best_min = -1;
182 HKEY hkey;
184 memcpy( buffer, typelibW, sizeof(typelibW) );
185 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
187 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
188 return FALSE;
190 len = sizeof(key_name);
191 i = 0;
192 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
194 INT v_maj, v_min;
196 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
198 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
200 if (*wMaj == 0xffff && *wMin == 0xffff)
202 if (v_maj > best_maj) best_maj = v_maj;
203 if (v_min > best_min) best_min = v_min;
205 else if (*wMaj == v_maj)
207 best_maj = v_maj;
209 if (*wMin == v_min)
211 best_min = v_min;
212 break; /* exact match */
214 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
217 len = sizeof(key_name);
219 RegCloseKey( hkey );
221 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
223 if (*wMaj == 0xffff && *wMin == 0xffff)
225 if (best_maj >= 0 && best_min >= 0)
227 *wMaj = best_maj;
228 *wMin = best_min;
229 return TRUE;
233 if (*wMaj == best_maj && best_min >= 0)
235 *wMin = best_min;
236 return TRUE;
238 return FALSE;
241 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
242 /* buffer must be at least 60 characters long */
243 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
245 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
246 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
248 memcpy( buffer, TypelibW, sizeof(TypelibW) );
249 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
250 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
251 return buffer;
254 /* get the path of an interface key, in the form "Interface\\<guid>" */
255 /* buffer must be at least 50 characters long */
256 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
258 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
260 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
261 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
262 return buffer;
265 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
266 /* buffer must be at least 16 characters long */
267 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
269 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
270 static const WCHAR win16W[] = {'w','i','n','1','6',0};
271 static const WCHAR win32W[] = {'w','i','n','3','2',0};
272 static const WCHAR win64W[] = {'w','i','n','6','4',0};
274 sprintfW( buffer, LcidFormatW, lcid );
275 switch(syskind)
277 case SYS_WIN16: strcatW( buffer, win16W ); break;
278 case SYS_WIN32: strcatW( buffer, win32W ); break;
279 case SYS_WIN64: strcatW( buffer, win64W ); break;
280 default:
281 TRACE("Typelib is for unsupported syskind %i\n", syskind);
282 return NULL;
284 return buffer;
287 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
289 struct tlibredirect_data
291 ULONG size;
292 DWORD res;
293 ULONG name_len;
294 ULONG name_offset;
295 LANGID langid;
296 WORD flags;
297 ULONG help_len;
298 ULONG help_offset;
299 WORD major_version;
300 WORD minor_version;
303 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
304 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
305 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
307 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
308 LCID myLCID = lcid;
309 HKEY hkey;
310 WCHAR buffer[60];
311 WCHAR Path[MAX_PATH];
312 LONG res;
314 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
316 if (redir)
318 ACTCTX_SECTION_KEYED_DATA data;
320 data.cbSize = sizeof(data);
321 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
323 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
324 WCHAR *nameW;
325 DWORD len;
327 if (tlib->major_version != wMaj || tlib->minor_version < wMin)
328 return TYPE_E_LIBNOTREGISTERED;
330 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
331 len = SearchPathW( NULL, nameW, NULL, sizeof(Path)/sizeof(WCHAR), Path, NULL );
332 if (!len) return TYPE_E_LIBNOTREGISTERED;
334 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
335 *path = SysAllocString( Path );
336 return S_OK;
340 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
341 get_typelib_key( guid, wMaj, wMin, buffer );
343 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
344 if (res == ERROR_FILE_NOT_FOUND)
346 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
347 return TYPE_E_LIBNOTREGISTERED;
349 else if (res != ERROR_SUCCESS)
351 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
352 return TYPE_E_REGISTRYACCESS;
355 while (hr != S_OK)
357 LONG dwPathLen = sizeof(Path);
359 get_lcid_subkey( myLCID, syskind, buffer );
361 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
363 if (!lcid)
364 break;
365 else if (myLCID == lcid)
367 /* try with sub-langid */
368 myLCID = SUBLANGID(lcid);
370 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
372 /* try with system langid */
373 myLCID = 0;
375 else
377 break;
380 else
382 *path = SysAllocString( Path );
383 hr = S_OK;
386 RegCloseKey( hkey );
387 TRACE_(typelib)("-- 0x%08x\n", hr);
388 return hr;
391 /****************************************************************************
392 * QueryPathOfRegTypeLib [OLEAUT32.164]
394 * Gets the path to a registered type library.
396 * PARAMS
397 * guid [I] referenced guid
398 * wMaj [I] major version
399 * wMin [I] minor version
400 * lcid [I] locale id
401 * path [O] path of typelib
403 * RETURNS
404 * Success: S_OK.
405 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
406 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
407 * opened.
409 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
411 BOOL redir = TRUE;
412 #ifdef _WIN64
413 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
414 if(SUCCEEDED(hres))
415 return hres;
416 redir = FALSE;
417 #endif
418 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
421 /******************************************************************************
422 * CreateTypeLib [OLEAUT32.160] creates a typelib
424 * RETURNS
425 * Success: S_OK
426 * Failure: Status
428 HRESULT WINAPI CreateTypeLib(
429 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
431 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
432 return E_FAIL;
435 /******************************************************************************
436 * LoadTypeLib [OLEAUT32.161]
438 * Loads a type library
440 * PARAMS
441 * szFile [I] Name of file to load from.
442 * pptLib [O] Pointer that receives ITypeLib object on success.
444 * RETURNS
445 * Success: S_OK
446 * Failure: Status
448 * SEE
449 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
451 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
453 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
454 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
457 /******************************************************************************
458 * LoadTypeLibEx [OLEAUT32.183]
460 * Loads and optionally registers a type library
462 * RETURNS
463 * Success: S_OK
464 * Failure: Status
466 HRESULT WINAPI LoadTypeLibEx(
467 LPCOLESTR szFile, /* [in] Name of file to load from */
468 REGKIND regkind, /* [in] Specify kind of registration */
469 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
471 WCHAR szPath[MAX_PATH+1];
472 HRESULT res;
474 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
476 *pptLib = NULL;
478 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
480 if (SUCCEEDED(res))
481 switch(regkind)
483 case REGKIND_DEFAULT:
484 /* don't register typelibs supplied with full path. Experimentation confirms the following */
485 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
486 (szFile[0] && (szFile[1] == ':'))) break;
487 /* else fall-through */
489 case REGKIND_REGISTER:
490 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
492 ITypeLib_Release(*pptLib);
493 *pptLib = 0;
495 break;
496 case REGKIND_NONE:
497 break;
500 TRACE(" returns %08x\n",res);
501 return res;
504 /******************************************************************************
505 * LoadRegTypeLib [OLEAUT32.162]
507 * Loads a registered type library.
509 * PARAMS
510 * rguid [I] GUID of the registered type library.
511 * wVerMajor [I] major version.
512 * wVerMinor [I] minor version.
513 * lcid [I] locale ID.
514 * ppTLib [O] pointer that receives an ITypeLib object on success.
516 * RETURNS
517 * Success: S_OK.
518 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
519 * LoadTypeLib.
521 HRESULT WINAPI LoadRegTypeLib(
522 REFGUID rguid,
523 WORD wVerMajor,
524 WORD wVerMinor,
525 LCID lcid,
526 ITypeLib **ppTLib)
528 BSTR bstr=NULL;
529 HRESULT res;
531 *ppTLib = NULL;
533 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
535 if(SUCCEEDED(res))
537 res= LoadTypeLib(bstr, ppTLib);
538 SysFreeString(bstr);
540 if (*ppTLib)
542 TLIBATTR *attr;
544 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
545 if (res == S_OK && (attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor))
547 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
548 ITypeLib_Release(*ppTLib);
549 *ppTLib = NULL;
550 res = TYPE_E_LIBNOTREGISTERED;
555 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
557 return res;
561 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
562 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
563 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
564 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
565 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
566 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
568 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
570 WCHAR keyName[60];
571 HKEY key, subKey;
573 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
574 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
575 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
577 get_interface_key( &tattr->guid, keyName );
578 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
579 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
581 if (name)
582 RegSetValueExW(key, NULL, 0, REG_SZ,
583 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
585 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
586 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
587 RegSetValueExW(subKey, NULL, 0, REG_SZ,
588 (const BYTE *)PSOA, sizeof PSOA);
589 RegCloseKey(subKey);
592 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
593 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
594 RegSetValueExW(subKey, NULL, 0, REG_SZ,
595 (const BYTE *)PSOA, sizeof PSOA);
596 RegCloseKey(subKey);
599 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
600 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
602 WCHAR buffer[40];
603 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
604 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
606 StringFromGUID2(&libattr->guid, buffer, 40);
607 RegSetValueExW(subKey, NULL, 0, REG_SZ,
608 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
609 sprintfW(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
610 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
611 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
612 RegCloseKey(subKey);
615 RegCloseKey(key);
619 /******************************************************************************
620 * RegisterTypeLib [OLEAUT32.163]
621 * Adds information about a type library to the System Registry
622 * NOTES
623 * Docs: ITypeLib FAR * ptlib
624 * Docs: OLECHAR FAR* szFullPath
625 * Docs: OLECHAR FAR* szHelpDir
627 * RETURNS
628 * Success: S_OK
629 * Failure: Status
631 HRESULT WINAPI RegisterTypeLib(
632 ITypeLib * ptlib, /* [in] Pointer to the library*/
633 OLECHAR * szFullPath, /* [in] full Path of the library*/
634 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
635 may be NULL*/
637 HRESULT res;
638 TLIBATTR *attr;
639 WCHAR keyName[60];
640 WCHAR tmp[16];
641 HKEY key, subKey;
642 UINT types, tidx;
643 TYPEKIND kind;
644 DWORD disposition;
646 if (ptlib == NULL || szFullPath == NULL)
647 return E_INVALIDARG;
649 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
650 return E_FAIL;
652 #ifndef _WIN64
653 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
654 #endif
656 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
658 res = S_OK;
659 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
660 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
662 LPOLESTR doc;
664 /* Set the human-readable name of the typelib */
665 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
666 res = E_FAIL;
667 else if (doc)
669 if (RegSetValueExW(key, NULL, 0, REG_SZ,
670 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
671 res = E_FAIL;
673 SysFreeString(doc);
676 /* Make up the name of the typelib path subkey */
677 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
679 /* Create the typelib path subkey */
680 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
681 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
683 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
684 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
685 res = E_FAIL;
687 RegCloseKey(subKey);
689 else
690 res = E_FAIL;
692 /* Create the flags subkey */
693 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
694 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
696 /* FIXME: is %u correct? */
697 static const WCHAR formatW[] = {'%','u',0};
698 WCHAR buf[20];
699 sprintfW(buf, formatW, attr->wLibFlags);
700 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
701 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
702 res = E_FAIL;
704 RegCloseKey(subKey);
706 else
707 res = E_FAIL;
709 /* create the helpdir subkey */
710 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
711 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
713 BOOL freeHelpDir = FALSE;
714 OLECHAR* pIndexStr;
716 /* if we created a new key, and helpDir was null, set the helpdir
717 to the directory which contains the typelib. However,
718 if we just opened an existing key, we leave the helpdir alone */
719 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
720 szHelpDir = SysAllocString(szFullPath);
721 pIndexStr = strrchrW(szHelpDir, '\\');
722 if (pIndexStr) {
723 *pIndexStr = 0;
725 freeHelpDir = TRUE;
728 /* if we have an szHelpDir, set it! */
729 if (szHelpDir != NULL) {
730 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
731 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
732 res = E_FAIL;
736 /* tidy up */
737 if (freeHelpDir) SysFreeString(szHelpDir);
738 RegCloseKey(subKey);
740 } else {
741 res = E_FAIL;
744 RegCloseKey(key);
746 else
747 res = E_FAIL;
749 /* register OLE Automation-compatible interfaces for this typelib */
750 types = ITypeLib_GetTypeInfoCount(ptlib);
751 for (tidx=0; tidx<types; tidx++) {
752 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
753 LPOLESTR name = NULL;
754 ITypeInfo *tinfo = NULL;
756 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
758 switch (kind) {
759 case TKIND_INTERFACE:
760 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
761 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
762 break;
764 case TKIND_DISPATCH:
765 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
766 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
767 break;
769 default:
770 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
771 break;
774 if (tinfo) {
775 TYPEATTR *tattr = NULL;
776 ITypeInfo_GetTypeAttr(tinfo, &tattr);
778 if (tattr) {
779 TRACE_(typelib)("guid=%s, flags=%04x (",
780 debugstr_guid(&tattr->guid),
781 tattr->wTypeFlags);
783 if (TRACE_ON(typelib)) {
784 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
785 XX(FAPPOBJECT);
786 XX(FCANCREATE);
787 XX(FLICENSED);
788 XX(FPREDECLID);
789 XX(FHIDDEN);
790 XX(FCONTROL);
791 XX(FDUAL);
792 XX(FNONEXTENSIBLE);
793 XX(FOLEAUTOMATION);
794 XX(FRESTRICTED);
795 XX(FAGGREGATABLE);
796 XX(FREPLACEABLE);
797 XX(FDISPATCHABLE);
798 XX(FREVERSEBIND);
799 XX(FPROXY);
800 #undef XX
801 MESSAGE("\n");
804 /* Register all dispinterfaces (which includes dual interfaces) and
805 oleautomation interfaces */
806 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
807 kind == TKIND_DISPATCH)
809 BOOL is_wow64;
810 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
812 /* register interface<->typelib coupling */
813 TLB_register_interface(attr, name, tattr, 0);
815 /* register TLBs into the opposite registry view, too */
816 if(opposite == KEY_WOW64_32KEY ||
817 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
818 TLB_register_interface(attr, name, tattr, opposite);
821 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
824 ITypeInfo_Release(tinfo);
827 SysFreeString(name);
831 ITypeLib_ReleaseTLibAttr(ptlib, attr);
833 return res;
837 /******************************************************************************
838 * UnRegisterTypeLib [OLEAUT32.186]
839 * Removes information about a type library from the System Registry
840 * NOTES
842 * RETURNS
843 * Success: S_OK
844 * Failure: Status
846 HRESULT WINAPI UnRegisterTypeLib(
847 REFGUID libid, /* [in] Guid of the library */
848 WORD wVerMajor, /* [in] major version */
849 WORD wVerMinor, /* [in] minor version */
850 LCID lcid, /* [in] locale id */
851 SYSKIND syskind)
853 BSTR tlibPath = NULL;
854 DWORD tmpLength;
855 WCHAR keyName[60];
856 WCHAR subKeyName[50];
857 int result = S_OK;
858 DWORD i = 0;
859 BOOL deleteOtherStuff;
860 HKEY key = NULL;
861 HKEY subKey = NULL;
862 TYPEATTR* typeAttr = NULL;
863 TYPEKIND kind;
864 ITypeInfo* typeInfo = NULL;
865 ITypeLib* typeLib = NULL;
866 int numTypes;
868 TRACE("(IID: %s)\n",debugstr_guid(libid));
870 /* Create the path to the key */
871 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
873 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
875 TRACE("Unsupported syskind %i\n", syskind);
876 result = E_INVALIDARG;
877 goto end;
880 /* get the path to the typelib on disk */
881 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
882 result = E_INVALIDARG;
883 goto end;
886 /* Try and open the key to the type library. */
887 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
888 result = E_INVALIDARG;
889 goto end;
892 /* Try and load the type library */
893 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
894 result = TYPE_E_INVALIDSTATE;
895 goto end;
898 /* remove any types registered with this typelib */
899 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
900 for (i=0; i<numTypes; i++) {
901 /* get the kind of type */
902 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
903 goto enddeleteloop;
906 /* skip non-interfaces, and get type info for the type */
907 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
908 goto enddeleteloop;
910 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
911 goto enddeleteloop;
913 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
914 goto enddeleteloop;
917 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
918 kind == TKIND_DISPATCH)
920 /* the path to the type */
921 get_interface_key( &typeAttr->guid, subKeyName );
923 /* Delete its bits */
924 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
925 goto enddeleteloop;
927 RegDeleteKeyW(subKey, ProxyStubClsidW);
928 RegDeleteKeyW(subKey, ProxyStubClsid32W);
929 RegDeleteKeyW(subKey, TypeLibW);
930 RegCloseKey(subKey);
931 subKey = NULL;
932 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
935 enddeleteloop:
936 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
937 typeAttr = NULL;
938 if (typeInfo) ITypeInfo_Release(typeInfo);
939 typeInfo = NULL;
942 /* Now, delete the type library path subkey */
943 get_lcid_subkey( lcid, syskind, subKeyName );
944 RegDeleteKeyW(key, subKeyName);
945 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
946 RegDeleteKeyW(key, subKeyName);
948 /* check if there is anything besides the FLAGS/HELPDIR keys.
949 If there is, we don't delete them */
950 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
951 deleteOtherStuff = TRUE;
952 i = 0;
953 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
954 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
956 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
957 if (!strcmpW(subKeyName, FLAGSW)) continue;
958 if (!strcmpW(subKeyName, HELPDIRW)) continue;
959 deleteOtherStuff = FALSE;
960 break;
963 /* only delete the other parts of the key if we're absolutely sure */
964 if (deleteOtherStuff) {
965 RegDeleteKeyW(key, FLAGSW);
966 RegDeleteKeyW(key, HELPDIRW);
967 RegCloseKey(key);
968 key = NULL;
970 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
971 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
972 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
975 end:
976 SysFreeString(tlibPath);
977 if (typeLib) ITypeLib_Release(typeLib);
978 if (subKey) RegCloseKey(subKey);
979 if (key) RegCloseKey(key);
980 return result;
983 /******************************************************************************
984 * RegisterTypeLibForUser [OLEAUT32.442]
985 * Adds information about a type library to the user registry
986 * NOTES
987 * Docs: ITypeLib FAR * ptlib
988 * Docs: OLECHAR FAR* szFullPath
989 * Docs: OLECHAR FAR* szHelpDir
991 * RETURNS
992 * Success: S_OK
993 * Failure: Status
995 HRESULT WINAPI RegisterTypeLibForUser(
996 ITypeLib * ptlib, /* [in] Pointer to the library*/
997 OLECHAR * szFullPath, /* [in] full Path of the library*/
998 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
999 may be NULL*/
1001 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1002 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1003 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1006 /******************************************************************************
1007 * UnRegisterTypeLibForUser [OLEAUT32.443]
1008 * Removes information about a type library from the user registry
1010 * RETURNS
1011 * Success: S_OK
1012 * Failure: Status
1014 HRESULT WINAPI UnRegisterTypeLibForUser(
1015 REFGUID libid, /* [in] GUID of the library */
1016 WORD wVerMajor, /* [in] major version */
1017 WORD wVerMinor, /* [in] minor version */
1018 LCID lcid, /* [in] locale id */
1019 SYSKIND syskind)
1021 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1022 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1023 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1026 /*======================= ITypeLib implementation =======================*/
1028 typedef struct tagTLBGuid {
1029 GUID guid;
1030 INT hreftype;
1031 UINT offset;
1032 struct list entry;
1033 } TLBGuid;
1035 typedef struct tagTLBCustData
1037 TLBGuid *guid;
1038 VARIANT data;
1039 struct list entry;
1040 } TLBCustData;
1042 /* data structure for import typelibs */
1043 typedef struct tagTLBImpLib
1045 int offset; /* offset in the file (MSFT)
1046 offset in nametable (SLTG)
1047 just used to identify library while reading
1048 data from file */
1049 TLBGuid *guid; /* libid */
1050 BSTR name; /* name */
1052 LCID lcid; /* lcid of imported typelib */
1054 WORD wVersionMajor; /* major version number */
1055 WORD wVersionMinor; /* minor version number */
1057 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1058 NULL if not yet loaded */
1059 struct list entry;
1060 } TLBImpLib;
1062 typedef struct tagTLBString {
1063 BSTR str;
1064 UINT offset;
1065 struct list entry;
1066 } TLBString;
1068 /* internal ITypeLib data */
1069 typedef struct tagITypeLibImpl
1071 ITypeLib2 ITypeLib2_iface;
1072 ITypeComp ITypeComp_iface;
1073 ICreateTypeLib2 ICreateTypeLib2_iface;
1074 LONG ref;
1075 TLBGuid *guid;
1076 LCID lcid;
1077 SYSKIND syskind;
1078 int ptr_size;
1079 WORD ver_major;
1080 WORD ver_minor;
1081 WORD libflags;
1082 LCID set_lcid;
1084 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1085 * exported to the application as a UNICODE string.
1087 struct list string_list;
1088 struct list name_list;
1089 struct list guid_list;
1091 const TLBString *Name;
1092 const TLBString *DocString;
1093 const TLBString *HelpFile;
1094 const TLBString *HelpStringDll;
1095 DWORD dwHelpContext;
1096 int TypeInfoCount; /* nr of typeinfo's in librarry */
1097 struct tagITypeInfoImpl **typeinfos;
1098 struct list custdata_list;
1099 struct list implib_list;
1100 int ctTypeDesc; /* number of items in type desc array */
1101 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1102 library. Only used while reading MSFT
1103 typelibs */
1104 struct list ref_list; /* list of ref types in this typelib */
1105 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1108 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1109 struct list entry;
1110 WCHAR *path;
1111 INT index;
1112 } ITypeLibImpl;
1114 static const ITypeLib2Vtbl tlbvt;
1115 static const ITypeCompVtbl tlbtcvt;
1116 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1118 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1120 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1123 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1125 return impl_from_ITypeLib2((ITypeLib2*)iface);
1128 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1130 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1133 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1135 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1138 /* ITypeLib methods */
1139 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1140 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1142 /*======================= ITypeInfo implementation =======================*/
1144 /* data for referenced types */
1145 typedef struct tagTLBRefType
1147 INT index; /* Type index for internal ref or for external ref
1148 it the format is SLTG. -2 indicates to
1149 use guid */
1151 TYPEKIND tkind;
1152 TLBGuid *guid; /* guid of the referenced type */
1153 /* if index == TLB_REF_USE_GUID */
1155 HREFTYPE reference; /* The href of this ref */
1156 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1157 TLB_REF_INTERNAL for internal refs
1158 TLB_REF_NOT_FOUND for broken refs */
1160 struct list entry;
1161 } TLBRefType;
1163 #define TLB_REF_USE_GUID -2
1165 #define TLB_REF_INTERNAL (void*)-2
1166 #define TLB_REF_NOT_FOUND (void*)-1
1168 /* internal Parameter data */
1169 typedef struct tagTLBParDesc
1171 const TLBString *Name;
1172 struct list custdata_list;
1173 } TLBParDesc;
1175 /* internal Function data */
1176 typedef struct tagTLBFuncDesc
1178 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1179 const TLBString *Name; /* the name of this function */
1180 TLBParDesc *pParamDesc; /* array with param names and custom data */
1181 int helpcontext;
1182 int HelpStringContext;
1183 const TLBString *HelpString;
1184 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1185 struct list custdata_list;
1186 } TLBFuncDesc;
1188 /* internal Variable data */
1189 typedef struct tagTLBVarDesc
1191 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1192 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1193 const TLBString *Name; /* the name of this variable */
1194 int HelpContext;
1195 int HelpStringContext;
1196 const TLBString *HelpString;
1197 struct list custdata_list;
1198 } TLBVarDesc;
1200 /* internal implemented interface data */
1201 typedef struct tagTLBImplType
1203 HREFTYPE hRef; /* hRef of interface */
1204 int implflags; /* IMPLFLAG_*s */
1205 struct list custdata_list;
1206 } TLBImplType;
1208 /* internal TypeInfo data */
1209 typedef struct tagITypeInfoImpl
1211 ITypeInfo2 ITypeInfo2_iface;
1212 ITypeComp ITypeComp_iface;
1213 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1214 LONG ref;
1215 BOOL not_attached_to_typelib;
1216 BOOL needs_layout;
1218 TLBGuid *guid;
1219 LCID lcid;
1220 MEMBERID memidConstructor;
1221 MEMBERID memidDestructor;
1222 LPOLESTR lpstrSchema;
1223 ULONG cbSizeInstance;
1224 TYPEKIND typekind;
1225 WORD cFuncs;
1226 WORD cVars;
1227 WORD cImplTypes;
1228 WORD cbSizeVft;
1229 WORD cbAlignment;
1230 WORD wTypeFlags;
1231 WORD wMajorVerNum;
1232 WORD wMinorVerNum;
1233 TYPEDESC *tdescAlias;
1234 IDLDESC idldescType;
1236 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1237 int index; /* index in this typelib; */
1238 HREFTYPE hreftype; /* hreftype for app object binding */
1239 /* type libs seem to store the doc strings in ascii
1240 * so why should we do it in unicode?
1242 const TLBString *Name;
1243 const TLBString *DocString;
1244 const TLBString *DllName;
1245 const TLBString *Schema;
1246 DWORD dwHelpContext;
1247 DWORD dwHelpStringContext;
1249 /* functions */
1250 TLBFuncDesc *funcdescs;
1252 /* variables */
1253 TLBVarDesc *vardescs;
1255 /* Implemented Interfaces */
1256 TLBImplType *impltypes;
1258 struct list *pcustdata_list;
1259 struct list custdata_list;
1260 } ITypeInfoImpl;
1262 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1264 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1267 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1269 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1272 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1274 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1277 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1279 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1282 static const ITypeInfo2Vtbl tinfvt;
1283 static const ITypeCompVtbl tcompvt;
1284 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1286 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1287 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1289 typedef struct tagTLBContext
1291 unsigned int oStart; /* start of TLB in file */
1292 unsigned int pos; /* current pos */
1293 unsigned int length; /* total length */
1294 void *mapping; /* memory mapping */
1295 MSFT_SegDir * pTblDir;
1296 ITypeLibImpl* pLibInfo;
1297 } TLBContext;
1300 static inline BSTR TLB_get_bstr(const TLBString *str)
1302 return str != NULL ? str->str : NULL;
1305 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1307 if(!str)
1308 return 1;
1309 return memcmp(left, str->str, len);
1312 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1314 return guid != NULL ? &guid->guid : NULL;
1317 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1319 return guid != NULL ? &guid->guid : &GUID_NULL;
1322 static int get_ptr_size(SYSKIND syskind)
1324 switch(syskind){
1325 case SYS_WIN64:
1326 return 8;
1327 case SYS_WIN32:
1328 case SYS_MAC:
1329 case SYS_WIN16:
1330 return 4;
1332 WARN("Unhandled syskind: 0x%x\n", syskind);
1333 return 4;
1337 debug
1339 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1340 if (pTD->vt & VT_RESERVED)
1341 szVarType += strlen(strcpy(szVarType, "reserved | "));
1342 if (pTD->vt & VT_BYREF)
1343 szVarType += strlen(strcpy(szVarType, "ref to "));
1344 if (pTD->vt & VT_ARRAY)
1345 szVarType += strlen(strcpy(szVarType, "array of "));
1346 if (pTD->vt & VT_VECTOR)
1347 szVarType += strlen(strcpy(szVarType, "vector of "));
1348 switch(pTD->vt & VT_TYPEMASK) {
1349 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1350 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1351 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1352 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1353 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1354 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1355 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1356 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1357 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1358 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1359 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1360 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1361 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1362 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1363 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1364 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1365 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1366 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1367 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1368 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1369 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1370 pTD->u.hreftype); break;
1371 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1372 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1373 case VT_PTR: sprintf(szVarType, "ptr to ");
1374 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1375 break;
1376 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1377 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1378 break;
1379 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1380 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1381 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1382 break;
1384 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1388 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1389 char buf[200];
1390 USHORT flags = edesc->u.paramdesc.wParamFlags;
1391 dump_TypeDesc(&edesc->tdesc,buf);
1392 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1393 MESSAGE("\t\tu.paramdesc.wParamFlags");
1394 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1395 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1396 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1397 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1398 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1399 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1400 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1401 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1402 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1404 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1405 int i;
1406 MESSAGE("memid is %08x\n",funcdesc->memid);
1407 for (i=0;i<funcdesc->cParams;i++) {
1408 MESSAGE("Param %d:\n",i);
1409 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1411 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1412 switch (funcdesc->funckind) {
1413 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1414 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1415 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1416 case FUNC_STATIC: MESSAGE("static");break;
1417 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1418 default: MESSAGE("unknown");break;
1420 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1421 switch (funcdesc->invkind) {
1422 case INVOKE_FUNC: MESSAGE("func");break;
1423 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1424 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1425 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1427 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1428 switch (funcdesc->callconv) {
1429 case CC_CDECL: MESSAGE("cdecl");break;
1430 case CC_PASCAL: MESSAGE("pascal");break;
1431 case CC_STDCALL: MESSAGE("stdcall");break;
1432 case CC_SYSCALL: MESSAGE("syscall");break;
1433 default:break;
1435 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1436 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1437 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1439 MESSAGE("\telemdescFunc (return value type):\n");
1440 dump_ELEMDESC(&funcdesc->elemdescFunc);
1443 static const char * const typekind_desc[] =
1445 "TKIND_ENUM",
1446 "TKIND_RECORD",
1447 "TKIND_MODULE",
1448 "TKIND_INTERFACE",
1449 "TKIND_DISPATCH",
1450 "TKIND_COCLASS",
1451 "TKIND_ALIAS",
1452 "TKIND_UNION",
1453 "TKIND_MAX"
1456 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1458 int i;
1459 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1460 for (i=0;i<pfd->funcdesc.cParams;i++)
1461 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1464 dump_FUNCDESC(&(pfd->funcdesc));
1466 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1467 if(pfd->Entry == NULL)
1468 MESSAGE("\tentry: (null)\n");
1469 else if(pfd->Entry == (void*)-1)
1470 MESSAGE("\tentry: invalid\n");
1471 else if(IS_INTRESOURCE(pfd->Entry))
1472 MESSAGE("\tentry: %p\n", pfd->Entry);
1473 else
1474 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1476 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1478 while (n)
1480 dump_TLBFuncDescOne(pfd);
1481 ++pfd;
1482 --n;
1485 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1487 while (n)
1489 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1490 ++pvd;
1491 --n;
1495 static void dump_TLBImpLib(const TLBImpLib *import)
1497 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1498 debugstr_w(import->name));
1499 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1500 import->wVersionMinor, import->lcid, import->offset);
1503 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1505 TLBRefType *ref;
1507 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1509 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1510 if(ref->index == -1)
1511 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1512 else
1513 TRACE_(typelib)("type no: %d\n", ref->index);
1515 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1517 TRACE_(typelib)("in lib\n");
1518 dump_TLBImpLib(ref->pImpTLInfo);
1523 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1525 if(!impl)
1526 return;
1527 while (n) {
1528 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1529 impl->hRef, impl->implflags);
1530 ++impl;
1531 --n;
1535 static void dump_Variant(const VARIANT * pvar)
1537 SYSTEMTIME st;
1539 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1541 if (pvar)
1543 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1544 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1546 TRACE(",%p", V_BYREF(pvar));
1548 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1550 TRACE(",%p", V_ARRAY(pvar));
1552 else switch (V_TYPE(pvar))
1554 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1555 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1556 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1557 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1558 case VT_INT:
1559 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1560 case VT_UINT:
1561 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1562 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1563 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1564 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1565 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1566 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1567 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1568 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1569 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1570 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1571 V_CY(pvar).s.Lo); break;
1572 case VT_DATE:
1573 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1574 TRACE(",<invalid>");
1575 else
1576 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1577 st.wHour, st.wMinute, st.wSecond);
1578 break;
1579 case VT_ERROR:
1580 case VT_VOID:
1581 case VT_USERDEFINED:
1582 case VT_EMPTY:
1583 case VT_NULL: break;
1584 default: TRACE(",?"); break;
1587 TRACE("}\n");
1590 static void dump_DispParms(const DISPPARAMS * pdp)
1592 unsigned int index;
1594 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1596 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1598 TRACE("named args:\n");
1599 for (index = 0; index < pdp->cNamedArgs; index++)
1600 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1603 if (pdp->cArgs && pdp->rgvarg)
1605 TRACE("args:\n");
1606 for (index = 0; index < pdp->cArgs; index++)
1607 dump_Variant( &pdp->rgvarg[index] );
1611 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1613 TRACE("%p ref=%u\n", pty, pty->ref);
1614 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1615 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1616 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1617 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1618 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1619 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1620 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1621 if (TRACE_ON(ole))
1622 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1623 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1624 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1627 static void dump_VARDESC(const VARDESC *v)
1629 MESSAGE("memid %d\n",v->memid);
1630 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1631 MESSAGE("oInst %d\n",v->u.oInst);
1632 dump_ELEMDESC(&(v->elemdescVar));
1633 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1634 MESSAGE("varkind %d\n",v->varkind);
1637 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1639 /* VT_LPWSTR is largest type that, may appear in type description */
1640 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1641 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1642 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1643 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1644 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1645 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1646 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1647 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1650 static void TLB_abort(void)
1652 DebugBreak();
1655 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1657 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1658 if (!ret) ERR("cannot allocate memory\n");
1659 return ret;
1662 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1664 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1665 if (!ret) ERR("cannot allocate memory\n");
1666 return ret;
1669 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1671 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1674 void heap_free(void *ptr)
1676 HeapFree(GetProcessHeap(), 0, ptr);
1679 /* returns the size required for a deep copy of a typedesc into a
1680 * flat buffer */
1681 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1683 SIZE_T size = 0;
1685 if (alloc_initial_space)
1686 size += sizeof(TYPEDESC);
1688 switch (tdesc->vt)
1690 case VT_PTR:
1691 case VT_SAFEARRAY:
1692 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1693 break;
1694 case VT_CARRAY:
1695 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1696 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1697 break;
1699 return size;
1702 /* deep copy a typedesc into a flat buffer */
1703 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1705 if (!dest)
1707 dest = buffer;
1708 buffer = (char *)buffer + sizeof(TYPEDESC);
1711 *dest = *src;
1713 switch (src->vt)
1715 case VT_PTR:
1716 case VT_SAFEARRAY:
1717 dest->u.lptdesc = buffer;
1718 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1719 break;
1720 case VT_CARRAY:
1721 dest->u.lpadesc = buffer;
1722 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1723 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1724 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1725 break;
1727 return buffer;
1730 /* free custom data allocated by MSFT_CustData */
1731 static inline void TLB_FreeCustData(struct list *custdata_list)
1733 TLBCustData *cd, *cdn;
1734 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1736 list_remove(&cd->entry);
1737 VariantClear(&cd->data);
1738 heap_free(cd);
1742 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1744 DWORD len;
1745 BSTR ret;
1747 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1748 ret = SysAllocStringLen(NULL, len - 1);
1749 if (!ret) return ret;
1750 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1751 return ret;
1754 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1755 UINT n, MEMBERID memid)
1757 while(n){
1758 if(funcdescs->funcdesc.memid == memid)
1759 return funcdescs;
1760 ++funcdescs;
1761 --n;
1763 return NULL;
1766 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1767 UINT n, const OLECHAR *name)
1769 while(n){
1770 if(!lstrcmpiW(TLB_get_bstr(funcdescs->Name), name))
1771 return funcdescs;
1772 ++funcdescs;
1773 --n;
1775 return NULL;
1778 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1779 UINT n, MEMBERID memid)
1781 while(n){
1782 if(vardescs->vardesc.memid == memid)
1783 return vardescs;
1784 ++vardescs;
1785 --n;
1787 return NULL;
1790 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1791 UINT n, const OLECHAR *name)
1793 while(n){
1794 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1795 return vardescs;
1796 ++vardescs;
1797 --n;
1799 return NULL;
1802 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1804 TLBCustData *cust_data;
1805 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1806 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1807 return cust_data;
1808 return NULL;
1811 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1812 UINT n, const OLECHAR *name)
1814 while(n){
1815 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1816 return *typeinfos;
1817 ++typeinfos;
1818 --n;
1820 return NULL;
1823 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1825 list_init(&var_desc->custdata_list);
1828 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1830 TLBVarDesc *ret;
1832 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1833 if(!ret)
1834 return NULL;
1836 while(n){
1837 TLBVarDesc_Constructor(&ret[n-1]);
1838 --n;
1841 return ret;
1844 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1846 TLBParDesc *ret;
1848 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1849 if(!ret)
1850 return NULL;
1852 while(n){
1853 list_init(&ret[n-1].custdata_list);
1854 --n;
1857 return ret;
1860 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1862 list_init(&func_desc->custdata_list);
1865 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1867 TLBFuncDesc *ret;
1869 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1870 if(!ret)
1871 return NULL;
1873 while(n){
1874 TLBFuncDesc_Constructor(&ret[n-1]);
1875 --n;
1878 return ret;
1881 static void TLBImplType_Constructor(TLBImplType *impl)
1883 list_init(&impl->custdata_list);
1886 static TLBImplType *TLBImplType_Alloc(UINT n)
1888 TLBImplType *ret;
1890 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1891 if(!ret)
1892 return NULL;
1894 while(n){
1895 TLBImplType_Constructor(&ret[n-1]);
1896 --n;
1899 return ret;
1902 static TLBGuid *TLB_append_guid(struct list *guid_list,
1903 const GUID *new_guid, HREFTYPE hreftype)
1905 TLBGuid *guid;
1907 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1908 if (IsEqualGUID(&guid->guid, new_guid))
1909 return guid;
1912 guid = heap_alloc(sizeof(TLBGuid));
1913 if (!guid)
1914 return NULL;
1916 memcpy(&guid->guid, new_guid, sizeof(GUID));
1917 guid->hreftype = hreftype;
1919 list_add_tail(guid_list, &guid->entry);
1921 return guid;
1924 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1926 TLBCustData *cust_data;
1928 switch(V_VT(var)){
1929 case VT_I4:
1930 case VT_R4:
1931 case VT_UI4:
1932 case VT_INT:
1933 case VT_UINT:
1934 case VT_HRESULT:
1935 case VT_BSTR:
1936 break;
1937 default:
1938 return DISP_E_BADVARTYPE;
1941 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1943 if (!cust_data) {
1944 cust_data = heap_alloc(sizeof(TLBCustData));
1945 if (!cust_data)
1946 return E_OUTOFMEMORY;
1948 cust_data->guid = tlbguid;
1949 VariantInit(&cust_data->data);
1951 list_add_tail(custdata_list, &cust_data->entry);
1952 }else
1953 VariantClear(&cust_data->data);
1955 return VariantCopy(&cust_data->data, var);
1958 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1960 TLBString *str;
1962 if(!new_str)
1963 return NULL;
1965 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1966 if (strcmpW(str->str, new_str) == 0)
1967 return str;
1970 str = heap_alloc(sizeof(TLBString));
1971 if (!str)
1972 return NULL;
1974 str->str = SysAllocString(new_str);
1975 if (!str->str) {
1976 heap_free(str);
1977 return NULL;
1980 list_add_tail(string_list, &str->entry);
1982 return str;
1985 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1986 ULONG *size, WORD *align)
1988 ITypeInfo *other;
1989 TYPEATTR *attr;
1990 HRESULT hr;
1992 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1993 if(FAILED(hr))
1994 return hr;
1996 hr = ITypeInfo_GetTypeAttr(other, &attr);
1997 if(FAILED(hr)){
1998 ITypeInfo_Release(other);
1999 return hr;
2002 if(size)
2003 *size = attr->cbSizeInstance;
2004 if(align)
2005 *align = attr->cbAlignment;
2007 ITypeInfo_ReleaseTypeAttr(other, attr);
2008 ITypeInfo_Release(other);
2010 return S_OK;
2013 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
2014 TYPEDESC *tdesc, ULONG *size, WORD *align)
2016 ULONG i, sub, ptr_size;
2017 HRESULT hr;
2019 ptr_size = get_ptr_size(sys);
2021 switch(tdesc->vt){
2022 case VT_VOID:
2023 *size = 0;
2024 break;
2025 case VT_I1:
2026 case VT_UI1:
2027 *size = 1;
2028 break;
2029 case VT_I2:
2030 case VT_BOOL:
2031 case VT_UI2:
2032 *size = 2;
2033 break;
2034 case VT_I4:
2035 case VT_R4:
2036 case VT_ERROR:
2037 case VT_UI4:
2038 case VT_INT:
2039 case VT_UINT:
2040 case VT_HRESULT:
2041 *size = 4;
2042 break;
2043 case VT_R8:
2044 case VT_I8:
2045 case VT_UI8:
2046 *size = 8;
2047 break;
2048 case VT_BSTR:
2049 case VT_DISPATCH:
2050 case VT_UNKNOWN:
2051 case VT_PTR:
2052 case VT_SAFEARRAY:
2053 case VT_LPSTR:
2054 case VT_LPWSTR:
2055 *size = ptr_size;
2056 break;
2057 case VT_DATE:
2058 *size = sizeof(DATE);
2059 break;
2060 case VT_VARIANT:
2061 *size = sizeof(VARIANT);
2062 #ifdef _WIN64
2063 if(sys == SYS_WIN32)
2064 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2065 #endif
2066 break;
2067 case VT_DECIMAL:
2068 *size = sizeof(DECIMAL);
2069 break;
2070 case VT_CY:
2071 *size = sizeof(CY);
2072 break;
2073 case VT_CARRAY:
2074 *size = 0;
2075 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2076 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2077 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2078 if(FAILED(hr))
2079 return hr;
2080 *size *= sub;
2081 return S_OK;
2082 case VT_USERDEFINED:
2083 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2084 default:
2085 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2086 return E_FAIL;
2089 if(align){
2090 if(*size < 4)
2091 *align = *size;
2092 else
2093 *align = 4;
2096 return S_OK;
2099 /**********************************************************************
2101 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2103 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
2105 return pcx->pos;
2108 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2110 if (where != DO_NOT_SEEK)
2112 where += pcx->oStart;
2113 if (where > pcx->length)
2115 /* FIXME */
2116 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2117 TLB_abort();
2119 pcx->pos = where;
2123 /* read function */
2124 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2126 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2127 pcx->pos, count, pcx->oStart, pcx->length, where);
2129 MSFT_Seek(pcx, where);
2130 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2131 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2132 pcx->pos += count;
2133 return count;
2136 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2137 LONG where )
2139 DWORD ret;
2141 ret = MSFT_Read(buffer, count, pcx, where);
2142 FromLEDWords(buffer, ret);
2144 return ret;
2147 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2148 LONG where )
2150 DWORD ret;
2152 ret = MSFT_Read(buffer, count, pcx, where);
2153 FromLEWords(buffer, ret);
2155 return ret;
2158 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2160 TLBGuid *guid;
2161 MSFT_GuidEntry entry;
2162 int offs = 0;
2164 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2165 while (1) {
2166 if (offs >= pcx->pTblDir->pGuidTab.length)
2167 return S_OK;
2169 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2171 guid = heap_alloc(sizeof(TLBGuid));
2173 guid->offset = offs;
2174 guid->guid = entry.guid;
2175 guid->hreftype = entry.hreftype;
2177 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2179 offs += sizeof(MSFT_GuidEntry);
2183 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2185 TLBGuid *ret;
2187 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2188 if(ret->offset == offset){
2189 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2190 return ret;
2194 return NULL;
2197 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2199 MSFT_NameIntro niName;
2201 if (offset < 0)
2203 ERR_(typelib)("bad offset %d\n", offset);
2204 return -1;
2207 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2208 pcx->pTblDir->pNametab.offset+offset);
2210 return niName.hreftype;
2213 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2215 char *string;
2216 MSFT_NameIntro intro;
2217 INT16 len_piece;
2218 int offs = 0, lengthInChars;
2220 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2221 while (1) {
2222 TLBString *tlbstr;
2224 if (offs >= pcx->pTblDir->pNametab.length)
2225 return S_OK;
2227 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2228 intro.namelen &= 0xFF;
2229 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2230 if(len_piece % 4)
2231 len_piece = (len_piece + 4) & ~0x3;
2232 if(len_piece < 8)
2233 len_piece = 8;
2235 string = heap_alloc(len_piece + 1);
2236 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2237 string[intro.namelen] = '\0';
2239 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2240 string, -1, NULL, 0);
2241 if (!lengthInChars) {
2242 heap_free(string);
2243 return E_UNEXPECTED;
2246 tlbstr = heap_alloc(sizeof(TLBString));
2248 tlbstr->offset = offs;
2249 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2250 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2252 heap_free(string);
2254 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2256 offs += len_piece;
2260 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2262 TLBString *tlbstr;
2264 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2265 if (tlbstr->offset == offset) {
2266 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2267 return tlbstr;
2271 return NULL;
2274 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2276 TLBString *tlbstr;
2278 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2279 if (tlbstr->offset == offset) {
2280 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2281 return tlbstr;
2285 return NULL;
2289 * read a value and fill a VARIANT structure
2291 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2293 int size;
2295 TRACE_(typelib)("\n");
2297 if(offset <0) { /* data are packed in here */
2298 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2299 V_I4(pVar) = offset & 0x3ffffff;
2300 return;
2302 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2303 pcx->pTblDir->pCustData.offset + offset );
2304 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2305 switch (V_VT(pVar)){
2306 case VT_EMPTY: /* FIXME: is this right? */
2307 case VT_NULL: /* FIXME: is this right? */
2308 case VT_I2 : /* this should not happen */
2309 case VT_I4 :
2310 case VT_R4 :
2311 case VT_ERROR :
2312 case VT_BOOL :
2313 case VT_I1 :
2314 case VT_UI1 :
2315 case VT_UI2 :
2316 case VT_UI4 :
2317 case VT_INT :
2318 case VT_UINT :
2319 case VT_VOID : /* FIXME: is this right? */
2320 case VT_HRESULT :
2321 size=4; break;
2322 case VT_R8 :
2323 case VT_CY :
2324 case VT_DATE :
2325 case VT_I8 :
2326 case VT_UI8 :
2327 case VT_DECIMAL : /* FIXME: is this right? */
2328 case VT_FILETIME :
2329 size=8;break;
2330 /* pointer types with known behaviour */
2331 case VT_BSTR :{
2332 char * ptr;
2333 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2334 if(size == -1){
2335 V_BSTR(pVar) = NULL;
2336 }else{
2337 ptr = heap_alloc_zero(size);
2338 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2339 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2340 /* FIXME: do we need a AtoW conversion here? */
2341 V_UNION(pVar, bstrVal[size])='\0';
2342 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2343 heap_free(ptr);
2346 size=-4; break;
2347 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2348 case VT_DISPATCH :
2349 case VT_VARIANT :
2350 case VT_UNKNOWN :
2351 case VT_PTR :
2352 case VT_SAFEARRAY :
2353 case VT_CARRAY :
2354 case VT_USERDEFINED :
2355 case VT_LPSTR :
2356 case VT_LPWSTR :
2357 case VT_BLOB :
2358 case VT_STREAM :
2359 case VT_STORAGE :
2360 case VT_STREAMED_OBJECT :
2361 case VT_STORED_OBJECT :
2362 case VT_BLOB_OBJECT :
2363 case VT_CF :
2364 case VT_CLSID :
2365 default:
2366 size=0;
2367 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2368 V_VT(pVar));
2371 if(size>0) /* (big|small) endian correct? */
2372 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2373 return;
2376 * create a linked list with custom data
2378 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2380 MSFT_CDGuid entry;
2381 TLBCustData* pNew;
2382 int count=0;
2384 TRACE_(typelib)("\n");
2386 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2388 while(offset >=0){
2389 count++;
2390 pNew=heap_alloc_zero(sizeof(TLBCustData));
2391 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2392 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2393 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2394 list_add_head(custdata_list, &pNew->entry);
2395 offset = entry.next;
2397 return count;
2400 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2402 if(type <0)
2403 pTd->vt=type & VT_TYPEMASK;
2404 else
2405 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2407 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2410 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2412 return (invkind == INVOKE_PROPERTYGET ||
2413 invkind == INVOKE_PROPERTYPUT ||
2414 invkind == INVOKE_PROPERTYPUTREF);
2417 static void
2418 MSFT_DoFuncs(TLBContext* pcx,
2419 ITypeInfoImpl* pTI,
2420 int cFuncs,
2421 int cVars,
2422 int offset,
2423 TLBFuncDesc** pptfd)
2426 * member information is stored in a data structure at offset
2427 * indicated by the memoffset field of the typeinfo structure
2428 * There are several distinctive parts.
2429 * The first part starts with a field that holds the total length
2430 * of this (first) part excluding this field. Then follow the records,
2431 * for each member there is one record.
2433 * The first entry is always the length of the record (including this
2434 * length word).
2435 * The rest of the record depends on the type of the member. If there is
2436 * a field indicating the member type (function, variable, interface, etc)
2437 * I have not found it yet. At this time we depend on the information
2438 * in the type info and the usual order how things are stored.
2440 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2441 * for each member;
2443 * Third is an equal sized array with file offsets to the name entry
2444 * of each member.
2446 * The fourth and last (?) part is an array with offsets to the records
2447 * in the first part of this file segment.
2450 int infolen, nameoffset, reclength, i;
2451 int recoffset = offset + sizeof(INT);
2453 char *recbuf = heap_alloc(0xffff);
2454 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2455 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2457 TRACE_(typelib)("\n");
2459 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2461 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2462 ptfd = *pptfd;
2463 for ( i = 0; i < cFuncs ; i++ )
2465 int optional;
2467 /* name, eventually add to a hash table */
2468 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2469 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2471 /* read the function information record */
2472 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2474 reclength &= 0xffff;
2476 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2478 /* size without argument data */
2479 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2480 if (pFuncRec->FKCCIC & 0x1000)
2481 optional -= pFuncRec->nrargs * sizeof(INT);
2483 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2484 ptfd->helpcontext = pFuncRec->HelpContext;
2486 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2487 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2489 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2491 if (pFuncRec->FKCCIC & 0x2000 )
2493 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2494 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2495 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2497 else
2498 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2500 else
2501 ptfd->Entry = (TLBString*)-1;
2503 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2504 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2506 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2507 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2509 /* fill the FuncDesc Structure */
2510 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2511 offset + infolen + ( i + 1) * sizeof(INT));
2513 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2514 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2515 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2516 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2517 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2518 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2519 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2521 /* nameoffset is sometimes -1 on the second half of a propget/propput
2522 * pair of functions */
2523 if ((nameoffset == -1) && (i > 0) &&
2524 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2525 TLB_is_propgetput(ptfd->funcdesc.invkind))
2526 ptfd->Name = ptfd_prev->Name;
2527 else
2528 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2530 MSFT_GetTdesc(pcx,
2531 pFuncRec->DataType,
2532 &ptfd->funcdesc.elemdescFunc.tdesc);
2534 /* do the parameters/arguments */
2535 if(pFuncRec->nrargs)
2537 int j = 0;
2538 MSFT_ParameterInfo paraminfo;
2540 ptfd->funcdesc.lprgelemdescParam =
2541 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2543 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2545 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2546 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2548 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2550 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2552 MSFT_GetTdesc(pcx,
2553 paraminfo.DataType,
2554 &elemdesc->tdesc);
2556 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2558 /* name */
2559 if (paraminfo.oName != -1)
2560 ptfd->pParamDesc[j].Name =
2561 MSFT_ReadName( pcx, paraminfo.oName );
2562 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2564 /* default value */
2565 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2566 (pFuncRec->FKCCIC & 0x1000) )
2568 INT* pInt = (INT *)((char *)pFuncRec +
2569 reclength -
2570 (pFuncRec->nrargs * 4) * sizeof(INT) );
2572 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2574 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2575 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2577 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2578 pInt[j], pcx);
2580 else
2581 elemdesc->u.paramdesc.pparamdescex = NULL;
2583 /* custom info */
2584 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2585 j*sizeof(pFuncRec->oArgCustData[0])) &&
2586 pFuncRec->FKCCIC & 0x80 )
2588 MSFT_CustData(pcx,
2589 pFuncRec->oArgCustData[j],
2590 &ptfd->pParamDesc[j].custdata_list);
2593 /* SEEK value = jump to offset,
2594 * from there jump to the end of record,
2595 * go back by (j-1) arguments
2597 MSFT_ReadLEDWords( &paraminfo ,
2598 sizeof(MSFT_ParameterInfo), pcx,
2599 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2600 * sizeof(MSFT_ParameterInfo)));
2604 /* scode is not used: archaic win16 stuff FIXME: right? */
2605 ptfd->funcdesc.cScodes = 0 ;
2606 ptfd->funcdesc.lprgscode = NULL ;
2608 ptfd_prev = ptfd;
2609 ++ptfd;
2610 recoffset += reclength;
2612 heap_free(recbuf);
2615 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2616 int cVars, int offset, TLBVarDesc ** pptvd)
2618 int infolen, nameoffset, reclength;
2619 char recbuf[256];
2620 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2621 TLBVarDesc *ptvd;
2622 int i;
2623 int recoffset;
2625 TRACE_(typelib)("\n");
2627 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2628 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2629 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2630 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2631 recoffset += offset+sizeof(INT);
2632 for(i=0;i<cVars;i++, ++ptvd){
2633 /* name, eventually add to a hash table */
2634 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2635 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2636 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2637 /* read the variable information record */
2638 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2639 reclength &= 0xff;
2640 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2642 /* optional data */
2643 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2644 ptvd->HelpContext = pVarRec->HelpContext;
2646 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2647 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2649 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2650 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2652 /* fill the VarDesc Structure */
2653 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2654 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2655 ptvd->vardesc.varkind = pVarRec->VarKind;
2656 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2657 MSFT_GetTdesc(pcx, pVarRec->DataType,
2658 &ptvd->vardesc.elemdescVar.tdesc);
2659 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2660 if(pVarRec->VarKind == VAR_CONST ){
2661 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2662 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2663 pVarRec->OffsValue, pcx);
2664 } else
2665 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2666 recoffset += reclength;
2670 /* process Implemented Interfaces of a com class */
2671 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2672 int offset)
2674 int i;
2675 MSFT_RefRecord refrec;
2676 TLBImplType *pImpl;
2678 TRACE_(typelib)("\n");
2680 pTI->impltypes = TLBImplType_Alloc(count);
2681 pImpl = pTI->impltypes;
2682 for(i=0;i<count;i++){
2683 if(offset<0) break; /* paranoia */
2684 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2685 pImpl->hRef = refrec.reftype;
2686 pImpl->implflags=refrec.flags;
2687 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2688 offset=refrec.onext;
2689 ++pImpl;
2693 #ifdef _WIN64
2694 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2695 * and some structures, and fix the alignment */
2696 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2698 if(info->typekind == TKIND_ALIAS){
2699 switch(info->tdescAlias->vt){
2700 case VT_BSTR:
2701 case VT_DISPATCH:
2702 case VT_UNKNOWN:
2703 case VT_PTR:
2704 case VT_SAFEARRAY:
2705 case VT_LPSTR:
2706 case VT_LPWSTR:
2707 info->cbSizeInstance = sizeof(void*);
2708 info->cbAlignment = sizeof(void*);
2709 break;
2710 case VT_CARRAY:
2711 case VT_USERDEFINED:
2712 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->cbSizeInstance, &info->cbAlignment);
2713 break;
2714 case VT_VARIANT:
2715 info->cbSizeInstance = sizeof(VARIANT);
2716 info->cbAlignment = 8;
2717 default:
2718 if(info->cbSizeInstance < sizeof(void*))
2719 info->cbAlignment = info->cbSizeInstance;
2720 else
2721 info->cbAlignment = sizeof(void*);
2722 break;
2724 }else if(info->typekind == TKIND_INTERFACE ||
2725 info->typekind == TKIND_DISPATCH ||
2726 info->typekind == TKIND_COCLASS){
2727 info->cbSizeInstance = sizeof(void*);
2728 info->cbAlignment = sizeof(void*);
2731 #endif
2734 * process a typeinfo record
2736 static ITypeInfoImpl * MSFT_DoTypeInfo(
2737 TLBContext *pcx,
2738 int count,
2739 ITypeLibImpl * pLibInfo)
2741 MSFT_TypeInfoBase tiBase;
2742 ITypeInfoImpl *ptiRet;
2744 TRACE_(typelib)("count=%u\n", count);
2746 ptiRet = ITypeInfoImpl_Constructor();
2747 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2748 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2750 /* this is where we are coming from */
2751 ptiRet->pTypeLib = pLibInfo;
2752 ptiRet->index=count;
2754 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2755 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2756 ptiRet->lpstrSchema=NULL; /* reserved */
2757 ptiRet->cbSizeInstance=tiBase.size;
2758 ptiRet->typekind=tiBase.typekind & 0xF;
2759 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2760 ptiRet->cVars=HIWORD(tiBase.cElement);
2761 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2762 ptiRet->wTypeFlags=tiBase.flags;
2763 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2764 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2765 ptiRet->cImplTypes=tiBase.cImplTypes;
2766 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2767 if(ptiRet->typekind == TKIND_ALIAS){
2768 TYPEDESC tmp;
2769 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2770 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2771 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2774 /* FIXME: */
2775 /* IDLDESC idldescType; *//* never saw this one != zero */
2777 /* name, eventually add to a hash table */
2778 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2779 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2780 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2781 /* help info */
2782 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2783 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2784 ptiRet->dwHelpContext=tiBase.helpcontext;
2786 if (ptiRet->typekind == TKIND_MODULE)
2787 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2789 /* note: InfoType's Help file and HelpStringDll come from the containing
2790 * library. Further HelpString and Docstring appear to be the same thing :(
2792 /* functions */
2793 if(ptiRet->cFuncs >0 )
2794 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2795 ptiRet->cVars,
2796 tiBase.memoffset, &ptiRet->funcdescs);
2797 /* variables */
2798 if(ptiRet->cVars >0 )
2799 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2800 ptiRet->cVars,
2801 tiBase.memoffset, &ptiRet->vardescs);
2802 if(ptiRet->cImplTypes >0 ) {
2803 switch(ptiRet->typekind)
2805 case TKIND_COCLASS:
2806 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2807 tiBase.datatype1);
2808 break;
2809 case TKIND_DISPATCH:
2810 /* This is not -1 when the interface is a non-base dual interface or
2811 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2812 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2813 not this interface.
2816 if (tiBase.datatype1 != -1)
2818 ptiRet->impltypes = TLBImplType_Alloc(1);
2819 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2821 break;
2822 default:
2823 ptiRet->impltypes = TLBImplType_Alloc(1);
2824 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2825 break;
2828 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2830 TRACE_(typelib)("%s guid: %s kind:%s\n",
2831 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2832 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2833 typekind_desc[ptiRet->typekind]);
2834 if (TRACE_ON(typelib))
2835 dump_TypeInfo(ptiRet);
2837 return ptiRet;
2840 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2842 char *string;
2843 INT16 len_str, len_piece;
2844 int offs = 0, lengthInChars;
2846 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2847 while (1) {
2848 TLBString *tlbstr;
2850 if (offs >= pcx->pTblDir->pStringtab.length)
2851 return S_OK;
2853 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2854 len_piece = len_str + sizeof(INT16);
2855 if(len_piece % 4)
2856 len_piece = (len_piece + 4) & ~0x3;
2857 if(len_piece < 8)
2858 len_piece = 8;
2860 string = heap_alloc(len_piece + 1);
2861 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2862 string[len_str] = '\0';
2864 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2865 string, -1, NULL, 0);
2866 if (!lengthInChars) {
2867 heap_free(string);
2868 return E_UNEXPECTED;
2871 tlbstr = heap_alloc(sizeof(TLBString));
2873 tlbstr->offset = offs;
2874 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2875 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2877 heap_free(string);
2879 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2881 offs += len_piece;
2885 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2887 TLBRefType *ref;
2888 int offs = 0;
2890 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2891 while (offs < pcx->pTblDir->pImpInfo.length) {
2892 MSFT_ImpInfo impinfo;
2893 TLBImpLib *pImpLib;
2895 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2897 ref = heap_alloc_zero(sizeof(TLBRefType));
2898 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2900 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2901 if(pImpLib->offset==impinfo.oImpFile)
2902 break;
2904 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2905 ref->reference = offs;
2906 ref->pImpTLInfo = pImpLib;
2907 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2908 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2909 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2910 ref->index = TLB_REF_USE_GUID;
2911 } else
2912 ref->index = impinfo.oGuid;
2913 }else{
2914 ERR("Cannot find a reference\n");
2915 ref->reference = -1;
2916 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2919 offs += sizeof(impinfo);
2922 return S_OK;
2925 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2926 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2927 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2928 * tradeoff here.
2930 static struct list tlb_cache = LIST_INIT(tlb_cache);
2931 static CRITICAL_SECTION cache_section;
2932 static CRITICAL_SECTION_DEBUG cache_section_debug =
2934 0, 0, &cache_section,
2935 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2936 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2938 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2941 typedef struct TLB_PEFile
2943 IUnknown IUnknown_iface;
2944 LONG refs;
2945 HMODULE dll;
2946 HRSRC typelib_resource;
2947 HGLOBAL typelib_global;
2948 LPVOID typelib_base;
2949 } TLB_PEFile;
2951 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2953 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2956 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2958 if (IsEqualIID(riid, &IID_IUnknown))
2960 *ppv = iface;
2961 IUnknown_AddRef(iface);
2962 return S_OK;
2964 *ppv = NULL;
2965 return E_NOINTERFACE;
2968 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2970 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2971 return InterlockedIncrement(&This->refs);
2974 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2976 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2977 ULONG refs = InterlockedDecrement(&This->refs);
2978 if (!refs)
2980 if (This->typelib_global)
2981 FreeResource(This->typelib_global);
2982 if (This->dll)
2983 FreeLibrary(This->dll);
2984 heap_free(This);
2986 return refs;
2989 static const IUnknownVtbl TLB_PEFile_Vtable =
2991 TLB_PEFile_QueryInterface,
2992 TLB_PEFile_AddRef,
2993 TLB_PEFile_Release
2996 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2998 TLB_PEFile *This;
2999 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3001 This = heap_alloc(sizeof(TLB_PEFile));
3002 if (!This)
3003 return E_OUTOFMEMORY;
3005 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
3006 This->refs = 1;
3007 This->dll = NULL;
3008 This->typelib_resource = NULL;
3009 This->typelib_global = NULL;
3010 This->typelib_base = NULL;
3012 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
3013 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
3015 if (This->dll)
3017 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
3018 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
3019 if (This->typelib_resource)
3021 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
3022 if (This->typelib_global)
3024 This->typelib_base = LockResource(This->typelib_global);
3026 if (This->typelib_base)
3028 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
3029 *ppBase = This->typelib_base;
3030 *ppFile = &This->IUnknown_iface;
3031 return S_OK;
3036 TRACE("No TYPELIB resource found\n");
3037 hr = E_FAIL;
3040 TLB_PEFile_Release(&This->IUnknown_iface);
3041 return hr;
3044 typedef struct TLB_NEFile
3046 IUnknown IUnknown_iface;
3047 LONG refs;
3048 LPVOID typelib_base;
3049 } TLB_NEFile;
3051 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
3053 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
3056 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3058 if (IsEqualIID(riid, &IID_IUnknown))
3060 *ppv = iface;
3061 IUnknown_AddRef(iface);
3062 return S_OK;
3064 *ppv = NULL;
3065 return E_NOINTERFACE;
3068 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3070 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3071 return InterlockedIncrement(&This->refs);
3074 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3076 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3077 ULONG refs = InterlockedDecrement(&This->refs);
3078 if (!refs)
3080 heap_free(This->typelib_base);
3081 heap_free(This);
3083 return refs;
3086 static const IUnknownVtbl TLB_NEFile_Vtable =
3088 TLB_NEFile_QueryInterface,
3089 TLB_NEFile_AddRef,
3090 TLB_NEFile_Release
3093 /***********************************************************************
3094 * read_xx_header [internal]
3096 static int read_xx_header( HFILE lzfd )
3098 IMAGE_DOS_HEADER mzh;
3099 char magic[3];
3101 LZSeek( lzfd, 0, SEEK_SET );
3102 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3103 return 0;
3104 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3105 return 0;
3107 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3108 if ( 2 != LZRead( lzfd, magic, 2 ) )
3109 return 0;
3111 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3113 if ( magic[0] == 'N' && magic[1] == 'E' )
3114 return IMAGE_OS2_SIGNATURE;
3115 if ( magic[0] == 'P' && magic[1] == 'E' )
3116 return IMAGE_NT_SIGNATURE;
3118 magic[2] = '\0';
3119 WARN("Can't handle %s files.\n", magic );
3120 return 0;
3124 /***********************************************************************
3125 * find_ne_resource [internal]
3127 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3128 DWORD *resLen, DWORD *resOff )
3130 IMAGE_OS2_HEADER nehd;
3131 NE_TYPEINFO *typeInfo;
3132 NE_NAMEINFO *nameInfo;
3133 DWORD nehdoffset;
3134 LPBYTE resTab;
3135 DWORD resTabSize;
3136 int count;
3138 /* Read in NE header */
3139 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3140 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3142 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3143 if ( !resTabSize )
3145 TRACE("No resources in NE dll\n" );
3146 return FALSE;
3149 /* Read in resource table */
3150 resTab = heap_alloc( resTabSize );
3151 if ( !resTab ) return FALSE;
3153 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3154 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3156 heap_free( resTab );
3157 return FALSE;
3160 /* Find resource */
3161 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3163 if (!IS_INTRESOURCE(typeid)) /* named type */
3165 BYTE len = strlen( typeid );
3166 while (typeInfo->type_id)
3168 if (!(typeInfo->type_id & 0x8000))
3170 BYTE *p = resTab + typeInfo->type_id;
3171 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3173 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3174 typeInfo->count * sizeof(NE_NAMEINFO));
3177 else /* numeric type id */
3179 WORD id = LOWORD(typeid) | 0x8000;
3180 while (typeInfo->type_id)
3182 if (typeInfo->type_id == id) goto found_type;
3183 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3184 typeInfo->count * sizeof(NE_NAMEINFO));
3187 TRACE("No typeid entry found for %p\n", typeid );
3188 heap_free( resTab );
3189 return FALSE;
3191 found_type:
3192 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3194 if (!IS_INTRESOURCE(resid)) /* named resource */
3196 BYTE len = strlen( resid );
3197 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3199 BYTE *p = resTab + nameInfo->id;
3200 if (nameInfo->id & 0x8000) continue;
3201 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3204 else /* numeric resource id */
3206 WORD id = LOWORD(resid) | 0x8000;
3207 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3208 if (nameInfo->id == id) goto found_name;
3210 TRACE("No resid entry found for %p\n", typeid );
3211 heap_free( resTab );
3212 return FALSE;
3214 found_name:
3215 /* Return resource data */
3216 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3217 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3219 heap_free( resTab );
3220 return TRUE;
3223 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3225 HFILE lzfd = -1;
3226 OFSTRUCT ofs;
3227 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3228 TLB_NEFile *This;
3230 This = heap_alloc(sizeof(TLB_NEFile));
3231 if (!This) return E_OUTOFMEMORY;
3233 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3234 This->refs = 1;
3235 This->typelib_base = NULL;
3237 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3238 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3240 DWORD reslen, offset;
3241 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3243 This->typelib_base = heap_alloc(reslen);
3244 if( !This->typelib_base )
3245 hr = E_OUTOFMEMORY;
3246 else
3248 LZSeek( lzfd, offset, SEEK_SET );
3249 reslen = LZRead( lzfd, This->typelib_base, reslen );
3250 LZClose( lzfd );
3251 *ppBase = This->typelib_base;
3252 *pdwTLBLength = reslen;
3253 *ppFile = &This->IUnknown_iface;
3254 return S_OK;
3259 if( lzfd >= 0) LZClose( lzfd );
3260 TLB_NEFile_Release(&This->IUnknown_iface);
3261 return hr;
3264 typedef struct TLB_Mapping
3266 IUnknown IUnknown_iface;
3267 LONG refs;
3268 HANDLE file;
3269 HANDLE mapping;
3270 LPVOID typelib_base;
3271 } TLB_Mapping;
3273 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3275 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3278 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3280 if (IsEqualIID(riid, &IID_IUnknown))
3282 *ppv = iface;
3283 IUnknown_AddRef(iface);
3284 return S_OK;
3286 *ppv = NULL;
3287 return E_NOINTERFACE;
3290 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3292 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3293 return InterlockedIncrement(&This->refs);
3296 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3298 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3299 ULONG refs = InterlockedDecrement(&This->refs);
3300 if (!refs)
3302 if (This->typelib_base)
3303 UnmapViewOfFile(This->typelib_base);
3304 if (This->mapping)
3305 CloseHandle(This->mapping);
3306 if (This->file != INVALID_HANDLE_VALUE)
3307 CloseHandle(This->file);
3308 heap_free(This);
3310 return refs;
3313 static const IUnknownVtbl TLB_Mapping_Vtable =
3315 TLB_Mapping_QueryInterface,
3316 TLB_Mapping_AddRef,
3317 TLB_Mapping_Release
3320 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3322 TLB_Mapping *This;
3324 This = heap_alloc(sizeof(TLB_Mapping));
3325 if (!This)
3326 return E_OUTOFMEMORY;
3328 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3329 This->refs = 1;
3330 This->file = INVALID_HANDLE_VALUE;
3331 This->mapping = NULL;
3332 This->typelib_base = NULL;
3334 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3335 if (INVALID_HANDLE_VALUE != This->file)
3337 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3338 if (This->mapping)
3340 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3341 if(This->typelib_base)
3343 /* retrieve file size */
3344 *pdwTLBLength = GetFileSize(This->file, NULL);
3345 *ppBase = This->typelib_base;
3346 *ppFile = &This->IUnknown_iface;
3347 return S_OK;
3352 IUnknown_Release(&This->IUnknown_iface);
3353 return TYPE_E_CANTLOADLIBRARY;
3356 /****************************************************************************
3357 * TLB_ReadTypeLib
3359 * find the type of the typelib file and map the typelib resource into
3360 * the memory
3363 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3364 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3366 ITypeLibImpl *entry;
3367 HRESULT ret;
3368 INT index = 1;
3369 LPWSTR index_str, file = (LPWSTR)pszFileName;
3370 LPVOID pBase = NULL;
3371 DWORD dwTLBLength = 0;
3372 IUnknown *pFile = NULL;
3373 HANDLE h;
3375 *ppTypeLib = NULL;
3377 index_str = strrchrW(pszFileName, '\\');
3378 if(index_str && *++index_str != '\0')
3380 LPWSTR end_ptr;
3381 LONG idx = strtolW(index_str, &end_ptr, 10);
3382 if(*end_ptr == '\0')
3384 int str_len = index_str - pszFileName - 1;
3385 index = idx;
3386 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3387 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3388 file[str_len] = 0;
3392 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3394 if(strchrW(file, '\\'))
3396 lstrcpyW(pszPath, file);
3398 else
3400 int len = GetSystemDirectoryW(pszPath, cchPath);
3401 pszPath[len] = '\\';
3402 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3406 if(file != pszFileName) heap_free(file);
3408 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3409 if(h != INVALID_HANDLE_VALUE){
3410 FILE_NAME_INFORMATION *info;
3411 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3412 BOOL br;
3414 info = (FILE_NAME_INFORMATION*)data;
3415 /* GetFileInformationByHandleEx returns the path of the file without
3416 * WOW64 redirection */
3417 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3418 if(br){
3419 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3420 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3422 CloseHandle(h);
3425 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3427 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3428 EnterCriticalSection(&cache_section);
3429 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3431 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3433 TRACE("cache hit\n");
3434 *ppTypeLib = &entry->ITypeLib2_iface;
3435 ITypeLib2_AddRef(*ppTypeLib);
3436 LeaveCriticalSection(&cache_section);
3437 return S_OK;
3440 LeaveCriticalSection(&cache_section);
3442 /* now actually load and parse the typelib */
3444 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3445 if (ret == TYPE_E_CANTLOADLIBRARY)
3446 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3447 if (ret == TYPE_E_CANTLOADLIBRARY)
3448 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3449 if (SUCCEEDED(ret))
3451 if (dwTLBLength >= 4)
3453 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3454 if (dwSignature == MSFT_SIGNATURE)
3455 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3456 else if (dwSignature == SLTG_SIGNATURE)
3457 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3458 else
3460 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3461 ret = TYPE_E_CANTLOADLIBRARY;
3464 else
3465 ret = TYPE_E_CANTLOADLIBRARY;
3466 IUnknown_Release(pFile);
3469 if(*ppTypeLib) {
3470 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3472 TRACE("adding to cache\n");
3473 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3474 lstrcpyW(impl->path, pszPath);
3475 /* We should really canonicalise the path here. */
3476 impl->index = index;
3478 /* FIXME: check if it has added already in the meantime */
3479 EnterCriticalSection(&cache_section);
3480 list_add_head(&tlb_cache, &impl->entry);
3481 LeaveCriticalSection(&cache_section);
3482 ret = S_OK;
3484 else
3486 if(ret != E_FAIL)
3487 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3489 ret = TYPE_E_CANTLOADLIBRARY;
3493 return ret;
3496 /*================== ITypeLib(2) Methods ===================================*/
3498 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3500 ITypeLibImpl* pTypeLibImpl;
3502 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3503 if (!pTypeLibImpl) return NULL;
3505 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3506 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3507 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3508 pTypeLibImpl->ref = 1;
3510 list_init(&pTypeLibImpl->implib_list);
3511 list_init(&pTypeLibImpl->custdata_list);
3512 list_init(&pTypeLibImpl->name_list);
3513 list_init(&pTypeLibImpl->string_list);
3514 list_init(&pTypeLibImpl->guid_list);
3515 list_init(&pTypeLibImpl->ref_list);
3516 pTypeLibImpl->dispatch_href = -1;
3518 return pTypeLibImpl;
3521 /****************************************************************************
3522 * ITypeLib2_Constructor_MSFT
3524 * loading an MSFT typelib from an in-memory image
3526 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3528 TLBContext cx;
3529 LONG lPSegDir;
3530 MSFT_Header tlbHeader;
3531 MSFT_SegDir tlbSegDir;
3532 ITypeLibImpl * pTypeLibImpl;
3533 int i;
3535 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3537 pTypeLibImpl = TypeLibImpl_Constructor();
3538 if (!pTypeLibImpl) return NULL;
3540 /* get pointer to beginning of typelib data */
3541 cx.pos = 0;
3542 cx.oStart=0;
3543 cx.mapping = pLib;
3544 cx.pLibInfo = pTypeLibImpl;
3545 cx.length = dwTLBLength;
3547 /* read header */
3548 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3549 TRACE_(typelib)("header:\n");
3550 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3551 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3552 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3553 return NULL;
3555 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3557 /* there is a small amount of information here until the next important
3558 * part:
3559 * the segment directory . Try to calculate the amount of data */
3560 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3562 /* now read the segment directory */
3563 TRACE("read segment directory (at %d)\n",lPSegDir);
3564 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3565 cx.pTblDir = &tlbSegDir;
3567 /* just check two entries */
3568 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3570 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3571 heap_free(pTypeLibImpl);
3572 return NULL;
3575 MSFT_ReadAllNames(&cx);
3576 MSFT_ReadAllStrings(&cx);
3577 MSFT_ReadAllGuids(&cx);
3579 /* now fill our internal data */
3580 /* TLIBATTR fields */
3581 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3583 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3584 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3585 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3586 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3587 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3589 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3590 pTypeLibImpl->lcid = tlbHeader.lcid;
3592 /* name, eventually add to a hash table */
3593 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3595 /* help info */
3596 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3597 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3599 if( tlbHeader.varflags & HELPDLLFLAG)
3601 int offset;
3602 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3603 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3606 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3608 /* custom data */
3609 if(tlbHeader.CustomDataOffset >= 0)
3611 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3614 /* fill in type descriptions */
3615 if(tlbSegDir.pTypdescTab.length > 0)
3617 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3618 INT16 td[4];
3619 pTypeLibImpl->ctTypeDesc = cTD;
3620 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3621 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3622 for(i=0; i<cTD; )
3624 /* FIXME: add several sanity checks here */
3625 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3626 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3628 /* FIXME: check safearray */
3629 if(td[3] < 0)
3630 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3631 else
3632 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3634 else if(td[0] == VT_CARRAY)
3636 /* array descr table here */
3637 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3639 else if(td[0] == VT_USERDEFINED)
3641 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3643 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3646 /* second time around to fill the array subscript info */
3647 for(i=0;i<cTD;i++)
3649 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3650 if(tlbSegDir.pArrayDescriptions.offset>0)
3652 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3653 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3655 if(td[1]<0)
3656 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3657 else
3658 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3660 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3662 for(j = 0; j<td[2]; j++)
3664 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3665 sizeof(INT), &cx, DO_NOT_SEEK);
3666 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3667 sizeof(INT), &cx, DO_NOT_SEEK);
3670 else
3672 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3673 ERR("didn't find array description data\n");
3678 /* imported type libs */
3679 if(tlbSegDir.pImpFiles.offset>0)
3681 TLBImpLib *pImpLib;
3682 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3683 UINT16 size;
3685 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3687 char *name;
3689 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3690 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3691 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3693 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3694 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3695 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3696 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3698 size >>= 2;
3699 name = heap_alloc_zero(size+1);
3700 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3701 pImpLib->name = TLB_MultiByteToBSTR(name);
3702 heap_free(name);
3704 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3705 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3707 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3711 MSFT_ReadAllRefs(&cx);
3713 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3715 /* type infos */
3716 if(tlbHeader.nrtypeinfos >= 0 )
3718 ITypeInfoImpl **ppTI;
3720 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3722 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3724 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3726 ++ppTI;
3727 (pTypeLibImpl->TypeInfoCount)++;
3731 #ifdef _WIN64
3732 if(pTypeLibImpl->syskind == SYS_WIN32){
3733 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3734 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3736 #endif
3738 TRACE("(%p)\n", pTypeLibImpl);
3739 return &pTypeLibImpl->ITypeLib2_iface;
3743 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3745 char b[3];
3746 int i;
3747 short s;
3749 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3750 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3751 return FALSE;
3754 guid->Data4[0] = s >> 8;
3755 guid->Data4[1] = s & 0xff;
3757 b[2] = '\0';
3758 for(i = 0; i < 6; i++) {
3759 memcpy(b, str + 24 + 2 * i, 2);
3760 guid->Data4[i + 2] = strtol(b, NULL, 16);
3762 return TRUE;
3765 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3767 WORD bytelen;
3768 DWORD len;
3769 BSTR tmp_str;
3771 *pStr = NULL;
3772 bytelen = *(const WORD*)ptr;
3773 if(bytelen == 0xffff) return 2;
3775 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3776 tmp_str = SysAllocStringLen(NULL, len);
3777 if (tmp_str) {
3778 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3779 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3780 SysFreeString(tmp_str);
3782 return bytelen + 2;
3785 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3787 WORD bytelen;
3789 *str = NULL;
3790 bytelen = *(const WORD*)ptr;
3791 if(bytelen == 0xffff) return 2;
3792 *str = heap_alloc(bytelen + 1);
3793 memcpy(*str, ptr + 2, bytelen);
3794 (*str)[bytelen] = '\0';
3795 return bytelen + 2;
3798 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3800 BSTR tmp_str;
3801 TLBString *tlbstr;
3803 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3804 if (tlbstr->offset == offset)
3805 return tlbstr;
3808 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3809 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3810 SysFreeString(tmp_str);
3812 return tlbstr;
3815 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3817 char *ptr = pLibBlk;
3818 WORD w;
3820 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3821 FIXME("libblk magic = %04x\n", w);
3822 return 0;
3825 ptr += 6;
3826 if((w = *(WORD*)ptr) != 0xffff) {
3827 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3828 ptr += w;
3830 ptr += 2;
3832 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3834 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3836 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3837 ptr += 4;
3839 pTypeLibImpl->syskind = *(WORD*)ptr;
3840 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3841 ptr += 2;
3843 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3844 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3845 else
3846 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3847 ptr += 2;
3849 ptr += 4; /* skip res12 */
3851 pTypeLibImpl->libflags = *(WORD*)ptr;
3852 ptr += 2;
3854 pTypeLibImpl->ver_major = *(WORD*)ptr;
3855 ptr += 2;
3857 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3858 ptr += 2;
3860 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3861 ptr += sizeof(GUID);
3863 return ptr - (char*)pLibBlk;
3866 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3867 typedef struct
3869 unsigned int num;
3870 HREFTYPE refs[1];
3871 } sltg_ref_lookup_t;
3873 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3874 HREFTYPE *typelib_ref)
3876 if(table && typeinfo_ref < table->num)
3878 *typelib_ref = table->refs[typeinfo_ref];
3879 return S_OK;
3882 ERR_(typelib)("Unable to find reference\n");
3883 *typelib_ref = -1;
3884 return E_FAIL;
3887 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3889 BOOL done = FALSE;
3891 while(!done) {
3892 if((*pType & 0xe00) == 0xe00) {
3893 pTD->vt = VT_PTR;
3894 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3895 pTD = pTD->u.lptdesc;
3897 switch(*pType & 0x3f) {
3898 case VT_PTR:
3899 pTD->vt = VT_PTR;
3900 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3901 pTD = pTD->u.lptdesc;
3902 break;
3904 case VT_USERDEFINED:
3905 pTD->vt = VT_USERDEFINED;
3906 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3907 done = TRUE;
3908 break;
3910 case VT_CARRAY:
3912 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3913 array */
3915 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3917 pTD->vt = VT_CARRAY;
3918 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3919 pTD->u.lpadesc->cDims = pSA->cDims;
3920 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3921 pSA->cDims * sizeof(SAFEARRAYBOUND));
3923 pTD = &pTD->u.lpadesc->tdescElem;
3924 break;
3927 case VT_SAFEARRAY:
3929 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3930 useful? */
3932 pType++;
3933 pTD->vt = VT_SAFEARRAY;
3934 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3935 pTD = pTD->u.lptdesc;
3936 break;
3938 default:
3939 pTD->vt = *pType & 0x3f;
3940 done = TRUE;
3941 break;
3943 pType++;
3945 return pType;
3948 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3949 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3951 /* Handle [in/out] first */
3952 if((*pType & 0xc000) == 0xc000)
3953 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3954 else if(*pType & 0x8000)
3955 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3956 else if(*pType & 0x4000)
3957 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3958 else
3959 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3961 if(*pType & 0x2000)
3962 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3964 if(*pType & 0x80)
3965 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3967 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3971 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3972 char *pNameTable)
3974 unsigned int ref;
3975 char *name;
3976 TLBRefType *ref_type;
3977 sltg_ref_lookup_t *table;
3978 HREFTYPE typelib_ref;
3980 if(pRef->magic != SLTG_REF_MAGIC) {
3981 FIXME("Ref magic = %x\n", pRef->magic);
3982 return NULL;
3984 name = ( (char*)pRef->names + pRef->number);
3986 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3987 table->num = pRef->number >> 3;
3989 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3991 /* We don't want the first href to be 0 */
3992 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3994 for(ref = 0; ref < pRef->number >> 3; ref++) {
3995 char *refname;
3996 unsigned int lib_offs, type_num;
3998 ref_type = heap_alloc_zero(sizeof(TLBRefType));
4000 name += SLTG_ReadStringA(name, &refname);
4001 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
4002 FIXME_(typelib)("Can't sscanf ref\n");
4003 if(lib_offs != 0xffff) {
4004 TLBImpLib *import;
4006 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
4007 if(import->offset == lib_offs)
4008 break;
4010 if(&import->entry == &pTL->implib_list) {
4011 char fname[MAX_PATH+1];
4012 int len;
4013 GUID tmpguid;
4015 import = heap_alloc_zero(sizeof(*import));
4016 import->offset = lib_offs;
4017 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
4018 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
4019 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
4020 &import->wVersionMajor,
4021 &import->wVersionMinor,
4022 &import->lcid, fname) != 4) {
4023 FIXME_(typelib)("can't sscanf ref %s\n",
4024 pNameTable + lib_offs + 40);
4026 len = strlen(fname);
4027 if(fname[len-1] != '#')
4028 FIXME("fname = %s\n", fname);
4029 fname[len-1] = '\0';
4030 import->name = TLB_MultiByteToBSTR(fname);
4031 list_add_tail(&pTL->implib_list, &import->entry);
4033 ref_type->pImpTLInfo = import;
4035 /* Store a reference to IDispatch */
4036 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
4037 pTL->dispatch_href = typelib_ref;
4039 } else { /* internal ref */
4040 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
4042 ref_type->reference = typelib_ref;
4043 ref_type->index = type_num;
4045 heap_free(refname);
4046 list_add_tail(&pTL->ref_list, &ref_type->entry);
4048 table->refs[ref] = typelib_ref;
4049 typelib_ref += 4;
4051 if((BYTE)*name != SLTG_REF_MAGIC)
4052 FIXME_(typelib)("End of ref block magic = %x\n", *name);
4053 dump_TLBRefType(pTL);
4054 return table;
4057 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
4058 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
4060 SLTG_ImplInfo *info;
4061 TLBImplType *pImplType;
4062 /* I don't really get this structure, usually it's 0x16 bytes
4063 long, but iuser.tlb contains some that are 0x18 bytes long.
4064 That's ok because we can use the next ptr to jump to the next
4065 one. But how do we know the length of the last one? The WORD
4066 at offs 0x8 might be the clue. For now I'm just assuming that
4067 the last one is the regular 0x16 bytes. */
4069 info = (SLTG_ImplInfo*)pBlk;
4070 while(1){
4071 pTI->cImplTypes++;
4072 if(info->next == 0xffff)
4073 break;
4074 info = (SLTG_ImplInfo*)(pBlk + info->next);
4077 info = (SLTG_ImplInfo*)pBlk;
4078 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
4079 pImplType = pTI->impltypes;
4080 while(1) {
4081 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4082 pImplType->implflags = info->impltypeflags;
4083 ++pImplType;
4085 if(info->next == 0xffff)
4086 break;
4087 if(OneOnly)
4088 FIXME_(typelib)("Interface inheriting more than one interface\n");
4089 info = (SLTG_ImplInfo*)(pBlk + info->next);
4091 info++; /* see comment at top of function */
4092 return (char*)info;
4095 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4096 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4098 TLBVarDesc *pVarDesc;
4099 const TLBString *prevName = NULL;
4100 SLTG_Variable *pItem;
4101 unsigned short i;
4102 WORD *pType;
4104 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4106 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4107 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4109 pVarDesc->vardesc.memid = pItem->memid;
4111 if (pItem->magic != SLTG_VAR_MAGIC &&
4112 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4113 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4114 return;
4117 if (pItem->name == 0xfffe)
4118 pVarDesc->Name = prevName;
4119 else
4120 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4122 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4123 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4124 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4126 if(pItem->flags & 0x02)
4127 pType = &pItem->type;
4128 else
4129 pType = (WORD*)(pBlk + pItem->type);
4131 if (pItem->flags & ~0xda)
4132 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4134 SLTG_DoElem(pType, pBlk,
4135 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4137 if (TRACE_ON(typelib)) {
4138 char buf[300];
4139 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4140 TRACE_(typelib)("elemdescVar: %s\n", buf);
4143 if (pItem->flags & 0x40) {
4144 TRACE_(typelib)("VAR_DISPATCH\n");
4145 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4147 else if (pItem->flags & 0x10) {
4148 TRACE_(typelib)("VAR_CONST\n");
4149 pVarDesc->vardesc.varkind = VAR_CONST;
4150 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4151 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4152 if (pItem->flags & 0x08)
4153 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4154 else {
4155 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4157 case VT_LPSTR:
4158 case VT_LPWSTR:
4159 case VT_BSTR:
4161 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4162 BSTR str;
4163 TRACE_(typelib)("len = %u\n", len);
4164 if (len == 0xffff) {
4165 str = NULL;
4166 } else {
4167 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4168 str = SysAllocStringLen(NULL, alloc_len);
4169 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4171 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4172 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4173 break;
4175 case VT_I2:
4176 case VT_UI2:
4177 case VT_I4:
4178 case VT_UI4:
4179 case VT_INT:
4180 case VT_UINT:
4181 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4182 *(INT*)(pBlk + pItem->byte_offs);
4183 break;
4184 default:
4185 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4189 else {
4190 TRACE_(typelib)("VAR_PERINSTANCE\n");
4191 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4192 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4195 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4196 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4198 if (pItem->flags & 0x80)
4199 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4201 prevName = pVarDesc->Name;
4203 pTI->cVars = cVars;
4206 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4207 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4209 SLTG_Function *pFunc;
4210 unsigned short i;
4211 TLBFuncDesc *pFuncDesc;
4213 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4215 pFuncDesc = pTI->funcdescs;
4216 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4217 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4219 int param;
4220 WORD *pType, *pArg;
4222 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4223 case SLTG_FUNCTION_MAGIC:
4224 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4225 break;
4226 case SLTG_DISPATCH_FUNCTION_MAGIC:
4227 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4228 break;
4229 case SLTG_STATIC_FUNCTION_MAGIC:
4230 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4231 break;
4232 default:
4233 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4234 continue;
4236 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4238 pFuncDesc->funcdesc.memid = pFunc->dispid;
4239 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4240 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4241 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4242 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4243 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4245 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4246 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4248 if(pFunc->retnextopt & 0x80)
4249 pType = &pFunc->rettype;
4250 else
4251 pType = (WORD*)(pBlk + pFunc->rettype);
4253 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4255 pFuncDesc->funcdesc.lprgelemdescParam =
4256 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4257 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4259 pArg = (WORD*)(pBlk + pFunc->arg_off);
4261 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4262 char *paramName = pNameTable + *pArg;
4263 BOOL HaveOffs;
4264 /* If arg type follows then paramName points to the 2nd
4265 letter of the name, else the next WORD is an offset to
4266 the arg type and paramName points to the first letter.
4267 So let's take one char off paramName and see if we're
4268 pointing at an alpha-numeric char. However if *pArg is
4269 0xffff or 0xfffe then the param has no name, the former
4270 meaning that the next WORD is the type, the latter
4271 meaning that the next WORD is an offset to the type. */
4273 HaveOffs = FALSE;
4274 if(*pArg == 0xffff)
4275 paramName = NULL;
4276 else if(*pArg == 0xfffe) {
4277 paramName = NULL;
4278 HaveOffs = TRUE;
4280 else if(paramName[-1] && !isalnum(paramName[-1]))
4281 HaveOffs = TRUE;
4283 pArg++;
4285 if(HaveOffs) { /* the next word is an offset to type */
4286 pType = (WORD*)(pBlk + *pArg);
4287 SLTG_DoElem(pType, pBlk,
4288 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4289 pArg++;
4290 } else {
4291 if(paramName)
4292 paramName--;
4293 pArg = SLTG_DoElem(pArg, pBlk,
4294 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4297 /* Are we an optional param ? */
4298 if(pFuncDesc->funcdesc.cParams - param <=
4299 pFuncDesc->funcdesc.cParamsOpt)
4300 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4302 if(paramName) {
4303 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4304 paramName - pNameTable, pTI->pTypeLib);
4305 } else {
4306 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4310 pTI->cFuncs = cFuncs;
4313 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4314 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4315 SLTG_TypeInfoTail *pTITail)
4317 char *pFirstItem;
4318 sltg_ref_lookup_t *ref_lookup = NULL;
4320 if(pTIHeader->href_table != 0xffffffff) {
4321 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4322 pNameTable);
4325 pFirstItem = pBlk;
4327 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4328 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4330 heap_free(ref_lookup);
4334 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4335 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4336 const SLTG_TypeInfoTail *pTITail)
4338 char *pFirstItem;
4339 sltg_ref_lookup_t *ref_lookup = NULL;
4341 if(pTIHeader->href_table != 0xffffffff) {
4342 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4343 pNameTable);
4346 pFirstItem = pBlk;
4348 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4349 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4352 if (pTITail->funcs_off != 0xffff)
4353 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4355 heap_free(ref_lookup);
4357 if (TRACE_ON(typelib))
4358 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4361 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4362 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4363 const SLTG_TypeInfoTail *pTITail)
4365 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4368 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4369 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4370 const SLTG_TypeInfoTail *pTITail)
4372 WORD *pType;
4373 sltg_ref_lookup_t *ref_lookup = NULL;
4375 if (pTITail->simple_alias) {
4376 /* if simple alias, no more processing required */
4377 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4378 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4379 return;
4382 if(pTIHeader->href_table != 0xffffffff) {
4383 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4384 pNameTable);
4387 /* otherwise it is an offset to a type */
4388 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4390 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4391 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4393 heap_free(ref_lookup);
4396 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4397 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4398 const SLTG_TypeInfoTail *pTITail)
4400 sltg_ref_lookup_t *ref_lookup = NULL;
4401 if (pTIHeader->href_table != 0xffffffff)
4402 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4403 pNameTable);
4405 if (pTITail->vars_off != 0xffff)
4406 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4408 if (pTITail->funcs_off != 0xffff)
4409 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4411 if (pTITail->impls_off != 0xffff)
4412 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4414 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4415 * of dispinterface functions including the IDispatch ones, so
4416 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4417 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4419 heap_free(ref_lookup);
4420 if (TRACE_ON(typelib))
4421 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4424 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4425 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4426 const SLTG_TypeInfoTail *pTITail)
4428 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4431 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4432 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4433 const SLTG_TypeInfoTail *pTITail)
4435 sltg_ref_lookup_t *ref_lookup = NULL;
4436 if (pTIHeader->href_table != 0xffffffff)
4437 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4438 pNameTable);
4440 if (pTITail->vars_off != 0xffff)
4441 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4443 if (pTITail->funcs_off != 0xffff)
4444 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4445 heap_free(ref_lookup);
4446 if (TRACE_ON(typelib))
4447 dump_TypeInfo(pTI);
4450 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4451 manageable copy of it into this */
4452 typedef struct {
4453 WORD small_no;
4454 char *index_name;
4455 char *other_name;
4456 WORD res1a;
4457 WORD name_offs;
4458 WORD more_bytes;
4459 char *extra;
4460 WORD res20;
4461 DWORD helpcontext;
4462 WORD res26;
4463 GUID uuid;
4464 } SLTG_InternalOtherTypeInfo;
4466 /****************************************************************************
4467 * ITypeLib2_Constructor_SLTG
4469 * loading a SLTG typelib from an in-memory image
4471 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4473 ITypeLibImpl *pTypeLibImpl;
4474 SLTG_Header *pHeader;
4475 SLTG_BlkEntry *pBlkEntry;
4476 SLTG_Magic *pMagic;
4477 SLTG_Index *pIndex;
4478 SLTG_Pad9 *pPad9;
4479 LPVOID pBlk, pFirstBlk;
4480 SLTG_LibBlk *pLibBlk;
4481 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4482 char *pAfterOTIBlks = NULL;
4483 char *pNameTable, *ptr;
4484 int i;
4485 DWORD len, order;
4486 ITypeInfoImpl **ppTypeInfoImpl;
4488 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4491 pTypeLibImpl = TypeLibImpl_Constructor();
4492 if (!pTypeLibImpl) return NULL;
4494 pHeader = pLib;
4496 TRACE_(typelib)("header:\n");
4497 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4498 pHeader->nrOfFileBlks );
4499 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4500 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4501 pHeader->SLTG_magic);
4502 return NULL;
4505 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4506 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4508 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4509 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4511 /* Next we have a magic block */
4512 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4514 /* Let's see if we're still in sync */
4515 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4516 sizeof(SLTG_COMPOBJ_MAGIC))) {
4517 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4518 return NULL;
4520 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4521 sizeof(SLTG_DIR_MAGIC))) {
4522 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4523 return NULL;
4526 pIndex = (SLTG_Index*)(pMagic+1);
4528 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4530 pFirstBlk = pPad9 + 1;
4532 /* We'll set up a ptr to the main library block, which is the last one. */
4534 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4535 pBlkEntry[order].next != 0;
4536 order = pBlkEntry[order].next - 1, i++) {
4537 pBlk = (char*)pBlk + pBlkEntry[order].len;
4539 pLibBlk = pBlk;
4541 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4543 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4544 interspersed */
4546 len += 0x40;
4548 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4550 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4553 ptr = (char*)pLibBlk + len;
4555 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4556 WORD w, extra;
4557 len = 0;
4559 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4561 w = *(WORD*)(ptr + 2);
4562 if(w != 0xffff) {
4563 len += w;
4564 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4565 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4566 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4568 w = *(WORD*)(ptr + 4 + len);
4569 if(w != 0xffff) {
4570 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4571 len += w;
4572 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4573 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4574 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4576 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4577 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4578 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4579 if(extra) {
4580 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4581 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4582 len += extra;
4584 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4585 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4586 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4587 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4588 len += sizeof(SLTG_OtherTypeInfo);
4589 ptr += len;
4592 pAfterOTIBlks = ptr;
4594 /* Skip this WORD and get the next DWORD */
4595 len = *(DWORD*)(pAfterOTIBlks + 2);
4597 /* Now add this to pLibBLk look at what we're pointing at and
4598 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4599 dust and we should be pointing at the beginning of the name
4600 table */
4602 pNameTable = (char*)pLibBlk + len;
4604 switch(*(WORD*)pNameTable) {
4605 case 0xffff:
4606 break;
4607 case 0x0200:
4608 pNameTable += 0x20;
4609 break;
4610 default:
4611 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4612 break;
4615 pNameTable += 0x216;
4617 pNameTable += 2;
4619 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4621 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4624 /* Hopefully we now have enough ptrs set up to actually read in
4625 some TypeInfos. It's not clear which order to do them in, so
4626 I'll just follow the links along the BlkEntry chain and read
4627 them in the order in which they are in the file */
4629 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4630 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4632 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4633 pBlkEntry[order].next != 0;
4634 order = pBlkEntry[order].next - 1, i++) {
4636 SLTG_TypeInfoHeader *pTIHeader;
4637 SLTG_TypeInfoTail *pTITail;
4638 SLTG_MemberHeader *pMemHeader;
4640 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4641 FIXME_(typelib)("Index strings don't match\n");
4642 heap_free(pOtherTypeInfoBlks);
4643 return NULL;
4646 pTIHeader = pBlk;
4647 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4648 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4649 heap_free(pOtherTypeInfoBlks);
4650 return NULL;
4652 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4653 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4654 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4656 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4657 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4658 (*ppTypeInfoImpl)->index = i;
4659 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4660 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4661 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4662 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4663 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4664 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4665 (*ppTypeInfoImpl)->wTypeFlags =
4666 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4668 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4669 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4671 if((pTIHeader->typeflags1 & 7) != 2)
4672 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4673 if(pTIHeader->typeflags3 != 2)
4674 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4676 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4677 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4678 typekind_desc[pTIHeader->typekind],
4679 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4680 (*ppTypeInfoImpl)->wTypeFlags);
4682 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4684 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4686 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4687 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4688 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4690 switch(pTIHeader->typekind) {
4691 case TKIND_ENUM:
4692 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4693 pTIHeader, pTITail);
4694 break;
4696 case TKIND_RECORD:
4697 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4698 pTIHeader, pTITail);
4699 break;
4701 case TKIND_INTERFACE:
4702 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4703 pTIHeader, pTITail);
4704 break;
4706 case TKIND_COCLASS:
4707 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4708 pTIHeader, pTITail);
4709 break;
4711 case TKIND_ALIAS:
4712 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4713 pTIHeader, pTITail);
4714 break;
4716 case TKIND_DISPATCH:
4717 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4718 pTIHeader, pTITail);
4719 break;
4721 case TKIND_MODULE:
4722 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4723 pTIHeader, pTITail);
4724 break;
4726 default:
4727 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4728 break;
4732 /* could get cFuncs, cVars and cImplTypes from here
4733 but we've already set those */
4734 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4735 X(06);
4736 X(16);
4737 X(18);
4738 X(1a);
4739 X(1e);
4740 X(24);
4741 X(26);
4742 X(2a);
4743 X(2c);
4744 X(2e);
4745 X(30);
4746 X(32);
4747 X(34);
4748 #undef X
4749 ++ppTypeInfoImpl;
4750 pBlk = (char*)pBlk + pBlkEntry[order].len;
4753 if(i != pTypeLibImpl->TypeInfoCount) {
4754 FIXME("Somehow processed %d TypeInfos\n", i);
4755 heap_free(pOtherTypeInfoBlks);
4756 return NULL;
4759 heap_free(pOtherTypeInfoBlks);
4760 return &pTypeLibImpl->ITypeLib2_iface;
4763 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4765 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4767 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4769 if(IsEqualIID(riid, &IID_IUnknown) ||
4770 IsEqualIID(riid,&IID_ITypeLib)||
4771 IsEqualIID(riid,&IID_ITypeLib2))
4773 *ppv = &This->ITypeLib2_iface;
4775 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4776 IsEqualIID(riid, &IID_ICreateTypeLib2))
4778 *ppv = &This->ICreateTypeLib2_iface;
4780 else
4782 *ppv = NULL;
4783 TRACE("-- Interface: E_NOINTERFACE\n");
4784 return E_NOINTERFACE;
4787 IUnknown_AddRef((IUnknown*)*ppv);
4788 return S_OK;
4791 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4793 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4794 ULONG ref = InterlockedIncrement(&This->ref);
4796 TRACE("(%p) ref=%u\n", This, ref);
4798 return ref;
4801 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4803 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4804 ULONG ref = InterlockedDecrement(&This->ref);
4806 TRACE("(%p) ref=%u\n",This, ref);
4808 if (!ref)
4810 TLBImpLib *pImpLib, *pImpLibNext;
4811 TLBRefType *ref_type;
4812 TLBString *tlbstr, *tlbstr_next;
4813 TLBGuid *tlbguid, *tlbguid_next;
4814 void *cursor2;
4815 int i;
4817 /* remove cache entry */
4818 if(This->path)
4820 TRACE("removing from cache list\n");
4821 EnterCriticalSection(&cache_section);
4822 if(This->entry.next)
4823 list_remove(&This->entry);
4824 LeaveCriticalSection(&cache_section);
4825 heap_free(This->path);
4827 TRACE(" destroying ITypeLib(%p)\n",This);
4829 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4830 list_remove(&tlbstr->entry);
4831 SysFreeString(tlbstr->str);
4832 heap_free(tlbstr);
4835 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4836 list_remove(&tlbstr->entry);
4837 SysFreeString(tlbstr->str);
4838 heap_free(tlbstr);
4841 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4842 list_remove(&tlbguid->entry);
4843 heap_free(tlbguid);
4846 TLB_FreeCustData(&This->custdata_list);
4848 for (i = 0; i < This->ctTypeDesc; i++)
4849 if (This->pTypeDesc[i].vt == VT_CARRAY)
4850 heap_free(This->pTypeDesc[i].u.lpadesc);
4852 heap_free(This->pTypeDesc);
4854 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4856 if (pImpLib->pImpTypeLib)
4857 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4858 SysFreeString(pImpLib->name);
4860 list_remove(&pImpLib->entry);
4861 heap_free(pImpLib);
4864 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4866 list_remove(&ref_type->entry);
4867 heap_free(ref_type);
4870 for (i = 0; i < This->TypeInfoCount; ++i){
4871 heap_free(This->typeinfos[i]->tdescAlias);
4872 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4874 heap_free(This->typeinfos);
4875 heap_free(This);
4876 return 0;
4879 return ref;
4882 /* ITypeLib::GetTypeInfoCount
4884 * Returns the number of type descriptions in the type library
4886 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4888 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4889 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4890 return This->TypeInfoCount;
4893 /* ITypeLib::GetTypeInfo
4895 * retrieves the specified type description in the library.
4897 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4898 ITypeLib2 *iface,
4899 UINT index,
4900 ITypeInfo **ppTInfo)
4902 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4904 TRACE("%p %u %p\n", This, index, ppTInfo);
4906 if(!ppTInfo)
4907 return E_INVALIDARG;
4909 if(index >= This->TypeInfoCount)
4910 return TYPE_E_ELEMENTNOTFOUND;
4912 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4913 ITypeInfo_AddRef(*ppTInfo);
4915 return S_OK;
4919 /* ITypeLibs::GetTypeInfoType
4921 * Retrieves the type of a type description.
4923 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4924 ITypeLib2 *iface,
4925 UINT index,
4926 TYPEKIND *pTKind)
4928 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4930 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4932 if(!pTKind)
4933 return E_INVALIDARG;
4935 if(index >= This->TypeInfoCount)
4936 return TYPE_E_ELEMENTNOTFOUND;
4938 *pTKind = This->typeinfos[index]->typekind;
4940 return S_OK;
4943 /* ITypeLib::GetTypeInfoOfGuid
4945 * Retrieves the type description that corresponds to the specified GUID.
4948 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4949 ITypeLib2 *iface,
4950 REFGUID guid,
4951 ITypeInfo **ppTInfo)
4953 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4954 int i;
4956 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4958 for(i = 0; i < This->TypeInfoCount; ++i){
4959 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4960 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4961 ITypeInfo_AddRef(*ppTInfo);
4962 return S_OK;
4966 return TYPE_E_ELEMENTNOTFOUND;
4969 /* ITypeLib::GetLibAttr
4971 * Retrieves the structure that contains the library's attributes.
4974 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4975 ITypeLib2 *iface,
4976 LPTLIBATTR *attr)
4978 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4980 TRACE("(%p, %p)\n", This, attr);
4982 if (!attr) return E_INVALIDARG;
4984 *attr = heap_alloc(sizeof(**attr));
4985 if (!*attr) return E_OUTOFMEMORY;
4987 (*attr)->guid = *TLB_get_guid_null(This->guid);
4988 (*attr)->lcid = This->set_lcid;
4989 (*attr)->syskind = This->syskind;
4990 (*attr)->wMajorVerNum = This->ver_major;
4991 (*attr)->wMinorVerNum = This->ver_minor;
4992 (*attr)->wLibFlags = This->libflags;
4994 return S_OK;
4997 /* ITypeLib::GetTypeComp
4999 * Enables a client compiler to bind to a library's types, variables,
5000 * constants, and global functions.
5003 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
5004 ITypeLib2 *iface,
5005 ITypeComp **ppTComp)
5007 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5009 TRACE("(%p)->(%p)\n",This,ppTComp);
5010 *ppTComp = &This->ITypeComp_iface;
5011 ITypeComp_AddRef(*ppTComp);
5013 return S_OK;
5016 /* ITypeLib::GetDocumentation
5018 * Retrieves the library's documentation string, the complete Help file name
5019 * and path, and the context identifier for the library Help topic in the Help
5020 * file.
5022 * On a successful return all non-null BSTR pointers will have been set,
5023 * possibly to NULL.
5025 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
5026 ITypeLib2 *iface,
5027 INT index,
5028 BSTR *pBstrName,
5029 BSTR *pBstrDocString,
5030 DWORD *pdwHelpContext,
5031 BSTR *pBstrHelpFile)
5033 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5034 HRESULT result = E_INVALIDARG;
5035 ITypeInfo *pTInfo;
5037 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
5038 This, index,
5039 pBstrName, pBstrDocString,
5040 pdwHelpContext, pBstrHelpFile);
5042 if(index<0)
5044 /* documentation for the typelib */
5045 if(pBstrName)
5047 if (This->Name)
5049 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
5050 goto memerr1;
5052 else
5053 *pBstrName = NULL;
5055 if(pBstrDocString)
5057 if (This->DocString)
5059 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
5060 goto memerr2;
5062 else
5063 *pBstrDocString = NULL;
5065 if(pdwHelpContext)
5067 *pdwHelpContext = This->dwHelpContext;
5069 if(pBstrHelpFile)
5071 if (This->HelpFile)
5073 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5074 goto memerr3;
5076 else
5077 *pBstrHelpFile = NULL;
5080 result = S_OK;
5082 else
5084 /* for a typeinfo */
5085 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5087 if(SUCCEEDED(result))
5089 result = ITypeInfo_GetDocumentation(pTInfo,
5090 MEMBERID_NIL,
5091 pBstrName,
5092 pBstrDocString,
5093 pdwHelpContext, pBstrHelpFile);
5095 ITypeInfo_Release(pTInfo);
5098 return result;
5099 memerr3:
5100 if (pBstrDocString) SysFreeString (*pBstrDocString);
5101 memerr2:
5102 if (pBstrName) SysFreeString (*pBstrName);
5103 memerr1:
5104 return STG_E_INSUFFICIENTMEMORY;
5107 /* ITypeLib::IsName
5109 * Indicates whether a passed-in string contains the name of a type or member
5110 * described in the library.
5113 static HRESULT WINAPI ITypeLib2_fnIsName(
5114 ITypeLib2 *iface,
5115 LPOLESTR szNameBuf,
5116 ULONG lHashVal,
5117 BOOL *pfName)
5119 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5120 int tic;
5121 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5123 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5124 pfName);
5126 *pfName=TRUE;
5127 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5128 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5129 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5130 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5131 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5132 int pc;
5133 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5134 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5135 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5136 goto ITypeLib2_fnIsName_exit;
5139 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
5140 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5141 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5145 *pfName=FALSE;
5147 ITypeLib2_fnIsName_exit:
5148 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5149 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5151 return S_OK;
5154 /* ITypeLib::FindName
5156 * Finds occurrences of a type description in a type library. This may be used
5157 * to quickly verify that a name exists in a type library.
5160 static HRESULT WINAPI ITypeLib2_fnFindName(
5161 ITypeLib2 *iface,
5162 LPOLESTR name,
5163 ULONG hash,
5164 ITypeInfo **ppTInfo,
5165 MEMBERID *memid,
5166 UINT16 *found)
5168 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5169 int tic;
5170 UINT count = 0;
5171 UINT len;
5173 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5175 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5176 return E_INVALIDARG;
5178 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5179 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5180 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5181 TLBVarDesc *var;
5182 UINT fdc;
5184 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5185 memid[count] = MEMBERID_NIL;
5186 goto ITypeLib2_fnFindName_exit;
5189 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5190 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5192 if(!TLB_str_memcmp(name, func->Name, len)) {
5193 memid[count] = func->funcdesc.memid;
5194 goto ITypeLib2_fnFindName_exit;
5198 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
5199 if (var) {
5200 memid[count] = var->vardesc.memid;
5201 goto ITypeLib2_fnFindName_exit;
5204 continue;
5205 ITypeLib2_fnFindName_exit:
5206 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5207 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5208 count++;
5210 TRACE("found %d typeinfos\n", count);
5212 *found = count;
5214 return S_OK;
5217 /* ITypeLib::ReleaseTLibAttr
5219 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5222 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5223 ITypeLib2 *iface,
5224 TLIBATTR *pTLibAttr)
5226 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5227 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5228 heap_free(pTLibAttr);
5231 /* ITypeLib2::GetCustData
5233 * gets the custom data
5235 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5236 ITypeLib2 * iface,
5237 REFGUID guid,
5238 VARIANT *pVarVal)
5240 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5241 TLBCustData *pCData;
5243 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5245 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5246 if(!pCData)
5247 return TYPE_E_ELEMENTNOTFOUND;
5249 VariantInit(pVarVal);
5250 VariantCopy(pVarVal, &pCData->data);
5252 return S_OK;
5255 /* ITypeLib2::GetLibStatistics
5257 * Returns statistics about a type library that are required for efficient
5258 * sizing of hash tables.
5261 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5262 ITypeLib2 * iface,
5263 ULONG *pcUniqueNames,
5264 ULONG *pcchUniqueNames)
5266 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5268 FIXME("(%p): stub!\n", This);
5270 if(pcUniqueNames) *pcUniqueNames=1;
5271 if(pcchUniqueNames) *pcchUniqueNames=1;
5272 return S_OK;
5275 /* ITypeLib2::GetDocumentation2
5277 * Retrieves the library's documentation string, the complete Help file name
5278 * and path, the localization context to use, and the context ID for the
5279 * library Help topic in the Help file.
5282 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5283 ITypeLib2 * iface,
5284 INT index,
5285 LCID lcid,
5286 BSTR *pbstrHelpString,
5287 DWORD *pdwHelpStringContext,
5288 BSTR *pbstrHelpStringDll)
5290 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5291 HRESULT result;
5292 ITypeInfo *pTInfo;
5294 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5296 /* the help string should be obtained from the helpstringdll,
5297 * using the _DLLGetDocumentation function, based on the supplied
5298 * lcid. Nice to do sometime...
5300 if(index<0)
5302 /* documentation for the typelib */
5303 if(pbstrHelpString)
5304 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5305 if(pdwHelpStringContext)
5306 *pdwHelpStringContext=This->dwHelpContext;
5307 if(pbstrHelpStringDll)
5308 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5310 result = S_OK;
5312 else
5314 /* for a typeinfo */
5315 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5317 if(SUCCEEDED(result))
5319 ITypeInfo2 * pTInfo2;
5320 result = ITypeInfo_QueryInterface(pTInfo,
5321 &IID_ITypeInfo2,
5322 (LPVOID*) &pTInfo2);
5324 if(SUCCEEDED(result))
5326 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5327 MEMBERID_NIL,
5328 lcid,
5329 pbstrHelpString,
5330 pdwHelpStringContext,
5331 pbstrHelpStringDll);
5333 ITypeInfo2_Release(pTInfo2);
5336 ITypeInfo_Release(pTInfo);
5339 return result;
5342 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5344 TLBCustData *pCData;
5345 unsigned int ct;
5346 CUSTDATAITEM *cdi;
5348 ct = list_count(custdata_list);
5350 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5351 if(!pCustData->prgCustData)
5352 return E_OUTOFMEMORY;
5354 pCustData->cCustData = ct;
5356 cdi = pCustData->prgCustData;
5357 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5358 cdi->guid = *TLB_get_guid_null(pCData->guid);
5359 VariantCopy(&cdi->varValue, &pCData->data);
5360 ++cdi;
5363 return S_OK;
5367 /* ITypeLib2::GetAllCustData
5369 * Gets all custom data items for the library.
5372 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5373 ITypeLib2 * iface,
5374 CUSTDATA *pCustData)
5376 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5377 TRACE("(%p)->(%p)\n", This, pCustData);
5378 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5381 static const ITypeLib2Vtbl tlbvt = {
5382 ITypeLib2_fnQueryInterface,
5383 ITypeLib2_fnAddRef,
5384 ITypeLib2_fnRelease,
5385 ITypeLib2_fnGetTypeInfoCount,
5386 ITypeLib2_fnGetTypeInfo,
5387 ITypeLib2_fnGetTypeInfoType,
5388 ITypeLib2_fnGetTypeInfoOfGuid,
5389 ITypeLib2_fnGetLibAttr,
5390 ITypeLib2_fnGetTypeComp,
5391 ITypeLib2_fnGetDocumentation,
5392 ITypeLib2_fnIsName,
5393 ITypeLib2_fnFindName,
5394 ITypeLib2_fnReleaseTLibAttr,
5396 ITypeLib2_fnGetCustData,
5397 ITypeLib2_fnGetLibStatistics,
5398 ITypeLib2_fnGetDocumentation2,
5399 ITypeLib2_fnGetAllCustData
5403 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5405 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5407 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5410 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5412 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5414 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5417 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5419 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5421 return ITypeLib2_Release(&This->ITypeLib2_iface);
5424 static HRESULT WINAPI ITypeLibComp_fnBind(
5425 ITypeComp * iface,
5426 OLECHAR * szName,
5427 ULONG lHash,
5428 WORD wFlags,
5429 ITypeInfo ** ppTInfo,
5430 DESCKIND * pDescKind,
5431 BINDPTR * pBindPtr)
5433 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5434 BOOL typemismatch = FALSE;
5435 int i;
5437 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5439 *pDescKind = DESCKIND_NONE;
5440 pBindPtr->lptcomp = NULL;
5441 *ppTInfo = NULL;
5443 for(i = 0; i < This->TypeInfoCount; ++i){
5444 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5445 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5447 /* FIXME: check wFlags here? */
5448 /* FIXME: we should use a hash table to look this info up using lHash
5449 * instead of an O(n) search */
5450 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5451 (pTypeInfo->typekind == TKIND_MODULE))
5453 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5455 *pDescKind = DESCKIND_TYPECOMP;
5456 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5457 ITypeComp_AddRef(pBindPtr->lptcomp);
5458 TRACE("module or enum: %s\n", debugstr_w(szName));
5459 return S_OK;
5463 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5464 (pTypeInfo->typekind == TKIND_ENUM))
5466 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5467 HRESULT hr;
5469 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5470 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5472 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5473 return S_OK;
5475 else if (hr == TYPE_E_TYPEMISMATCH)
5476 typemismatch = TRUE;
5479 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5480 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5482 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5483 HRESULT hr;
5484 ITypeInfo *subtypeinfo;
5485 BINDPTR subbindptr;
5486 DESCKIND subdesckind;
5488 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5489 &subtypeinfo, &subdesckind, &subbindptr);
5490 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5492 TYPEDESC tdesc_appobject;
5493 const VARDESC vardesc_appobject =
5495 -2, /* memid */
5496 NULL, /* lpstrSchema */
5498 0 /* oInst */
5501 /* ELEMDESC */
5503 /* TYPEDESC */
5505 &tdesc_appobject
5507 VT_PTR
5510 0, /* wVarFlags */
5511 VAR_STATIC /* varkind */
5514 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5515 tdesc_appobject.vt = VT_USERDEFINED;
5517 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5519 /* cleanup things filled in by Bind call so we can put our
5520 * application object data in there instead */
5521 switch (subdesckind)
5523 case DESCKIND_FUNCDESC:
5524 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5525 break;
5526 case DESCKIND_VARDESC:
5527 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5528 break;
5529 default:
5530 break;
5532 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5534 if (pTypeInfo->hreftype == -1)
5535 FIXME("no hreftype for interface %p\n", pTypeInfo);
5537 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5538 if (FAILED(hr))
5539 return hr;
5541 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5542 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5543 ITypeInfo_AddRef(*ppTInfo);
5544 return S_OK;
5546 else if (hr == TYPE_E_TYPEMISMATCH)
5547 typemismatch = TRUE;
5551 if (typemismatch)
5553 TRACE("type mismatch %s\n", debugstr_w(szName));
5554 return TYPE_E_TYPEMISMATCH;
5556 else
5558 TRACE("name not found %s\n", debugstr_w(szName));
5559 return S_OK;
5563 static HRESULT WINAPI ITypeLibComp_fnBindType(
5564 ITypeComp * iface,
5565 OLECHAR * szName,
5566 ULONG lHash,
5567 ITypeInfo ** ppTInfo,
5568 ITypeComp ** ppTComp)
5570 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5571 ITypeInfoImpl *info;
5573 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5575 if(!szName || !ppTInfo || !ppTComp)
5576 return E_INVALIDARG;
5578 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5579 if(!info){
5580 *ppTInfo = NULL;
5581 *ppTComp = NULL;
5582 return S_OK;
5585 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5586 ITypeInfo_AddRef(*ppTInfo);
5587 *ppTComp = &info->ITypeComp_iface;
5588 ITypeComp_AddRef(*ppTComp);
5590 return S_OK;
5593 static const ITypeCompVtbl tlbtcvt =
5596 ITypeLibComp_fnQueryInterface,
5597 ITypeLibComp_fnAddRef,
5598 ITypeLibComp_fnRelease,
5600 ITypeLibComp_fnBind,
5601 ITypeLibComp_fnBindType
5604 /*================== ITypeInfo(2) Methods ===================================*/
5605 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5607 ITypeInfoImpl *pTypeInfoImpl;
5609 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5610 if (pTypeInfoImpl)
5612 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5613 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5614 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5615 pTypeInfoImpl->ref = 0;
5616 pTypeInfoImpl->hreftype = -1;
5617 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5618 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5619 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5620 list_init(pTypeInfoImpl->pcustdata_list);
5622 TRACE("(%p)\n", pTypeInfoImpl);
5623 return pTypeInfoImpl;
5626 /* ITypeInfo::QueryInterface
5628 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5629 ITypeInfo2 *iface,
5630 REFIID riid,
5631 VOID **ppvObject)
5633 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5635 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5637 *ppvObject=NULL;
5638 if(IsEqualIID(riid, &IID_IUnknown) ||
5639 IsEqualIID(riid,&IID_ITypeInfo)||
5640 IsEqualIID(riid,&IID_ITypeInfo2))
5641 *ppvObject = This;
5642 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5643 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5644 *ppvObject = &This->ICreateTypeInfo2_iface;
5646 if(*ppvObject){
5647 ITypeInfo2_AddRef(iface);
5648 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5649 return S_OK;
5651 TRACE("-- Interface: E_NOINTERFACE\n");
5652 return E_NOINTERFACE;
5655 /* ITypeInfo::AddRef
5657 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5659 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5660 ULONG ref = InterlockedIncrement(&This->ref);
5662 TRACE("(%p)->ref is %u\n",This, ref);
5664 if (ref == 1 /* incremented from 0 */)
5665 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5667 return ref;
5670 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5672 UINT i;
5674 TRACE("destroying ITypeInfo(%p)\n",This);
5676 for (i = 0; i < This->cFuncs; ++i)
5678 int j;
5679 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5680 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5682 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5683 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5684 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5685 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5687 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5688 heap_free(pFInfo->pParamDesc);
5689 TLB_FreeCustData(&pFInfo->custdata_list);
5691 heap_free(This->funcdescs);
5693 for(i = 0; i < This->cVars; ++i)
5695 TLBVarDesc *pVInfo = &This->vardescs[i];
5696 if (pVInfo->vardesc_create) {
5697 TLB_FreeVarDesc(pVInfo->vardesc_create);
5698 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5699 VariantClear(pVInfo->vardesc.u.lpvarValue);
5700 heap_free(pVInfo->vardesc.u.lpvarValue);
5702 TLB_FreeCustData(&pVInfo->custdata_list);
5704 heap_free(This->vardescs);
5706 if(This->impltypes){
5707 for (i = 0; i < This->cImplTypes; ++i){
5708 TLBImplType *pImpl = &This->impltypes[i];
5709 TLB_FreeCustData(&pImpl->custdata_list);
5711 heap_free(This->impltypes);
5714 TLB_FreeCustData(&This->custdata_list);
5716 heap_free(This);
5719 /* ITypeInfo::Release
5721 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5723 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5724 ULONG ref = InterlockedDecrement(&This->ref);
5726 TRACE("(%p)->(%u)\n",This, ref);
5728 if (!ref)
5730 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5731 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5732 if (not_attached_to_typelib)
5733 heap_free(This);
5734 /* otherwise This will be freed when typelib is freed */
5737 return ref;
5740 /* ITypeInfo::GetTypeAttr
5742 * Retrieves a TYPEATTR structure that contains the attributes of the type
5743 * description.
5746 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5747 LPTYPEATTR *ppTypeAttr)
5749 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5750 SIZE_T size;
5752 TRACE("(%p)\n",This);
5754 size = sizeof(**ppTypeAttr);
5755 if (This->typekind == TKIND_ALIAS && This->tdescAlias)
5756 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5758 *ppTypeAttr = heap_alloc(size);
5759 if (!*ppTypeAttr)
5760 return E_OUTOFMEMORY;
5762 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5763 (*ppTypeAttr)->lcid = This->lcid;
5764 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5765 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5766 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5767 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5768 (*ppTypeAttr)->typekind = This->typekind;
5769 (*ppTypeAttr)->cFuncs = This->cFuncs;
5770 (*ppTypeAttr)->cVars = This->cVars;
5771 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5772 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5773 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5774 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5775 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5776 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5777 (*ppTypeAttr)->idldescType = This->idldescType;
5779 if (This->tdescAlias)
5780 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5781 This->tdescAlias, *ppTypeAttr + 1);
5782 else{
5783 (*ppTypeAttr)->tdescAlias.vt = VT_EMPTY;
5784 (*ppTypeAttr)->tdescAlias.u.lptdesc = NULL;
5787 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5788 /* This should include all the inherited funcs */
5789 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5790 /* This is always the size of IDispatch's vtbl */
5791 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5792 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5794 return S_OK;
5797 /* ITypeInfo::GetTypeComp
5799 * Retrieves the ITypeComp interface for the type description, which enables a
5800 * client compiler to bind to the type description's members.
5803 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5804 ITypeComp * *ppTComp)
5806 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5808 TRACE("(%p)->(%p)\n", This, ppTComp);
5810 *ppTComp = &This->ITypeComp_iface;
5811 ITypeComp_AddRef(*ppTComp);
5812 return S_OK;
5815 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5817 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5818 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5819 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5820 return size;
5823 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5825 *dest = *src;
5826 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5827 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5829 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5830 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5831 *buffer += sizeof(PARAMDESCEX);
5832 *pparamdescex_dest = *pparamdescex_src;
5833 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5834 VariantInit(&pparamdescex_dest->varDefaultValue);
5835 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5836 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5838 else
5839 dest->u.paramdesc.pparamdescex = NULL;
5840 return S_OK;
5843 static HRESULT TLB_SanitizeBSTR(BSTR str)
5845 UINT len = SysStringLen(str), i;
5846 for (i = 0; i < len; ++i)
5847 if (str[i] > 0x7f)
5848 str[i] = '?';
5849 return S_OK;
5852 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5854 if (V_VT(var) == VT_INT)
5855 return VariantChangeType(var, var, 0, VT_I4);
5856 else if (V_VT(var) == VT_UINT)
5857 return VariantChangeType(var, var, 0, VT_UI4);
5858 else if (V_VT(var) == VT_BSTR)
5859 return TLB_SanitizeBSTR(V_BSTR(var));
5861 return S_OK;
5864 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5866 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5867 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5870 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5872 FUNCDESC *dest;
5873 char *buffer;
5874 SIZE_T size = sizeof(*src);
5875 SHORT i;
5876 HRESULT hr;
5878 size += sizeof(*src->lprgscode) * src->cScodes;
5879 size += TLB_SizeElemDesc(&src->elemdescFunc);
5880 for (i = 0; i < src->cParams; i++)
5882 size += sizeof(ELEMDESC);
5883 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5886 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5887 if (!dest) return E_OUTOFMEMORY;
5889 *dest = *src;
5890 if (dispinterface) /* overwrite funckind */
5891 dest->funckind = FUNC_DISPATCH;
5892 buffer = (char *)(dest + 1);
5894 dest->oVft = dest->oVft & 0xFFFC;
5896 if (dest->cScodes) {
5897 dest->lprgscode = (SCODE *)buffer;
5898 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5899 buffer += sizeof(*src->lprgscode) * src->cScodes;
5900 } else
5901 dest->lprgscode = NULL;
5903 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5904 if (FAILED(hr))
5906 SysFreeString((BSTR)dest);
5907 return hr;
5910 if (dest->cParams) {
5911 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5912 buffer += sizeof(ELEMDESC) * src->cParams;
5913 for (i = 0; i < src->cParams; i++)
5915 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5916 if (FAILED(hr))
5917 break;
5919 if (FAILED(hr))
5921 /* undo the above actions */
5922 for (i = i - 1; i >= 0; i--)
5923 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5924 TLB_FreeElemDesc(&dest->elemdescFunc);
5925 SysFreeString((BSTR)dest);
5926 return hr;
5928 } else
5929 dest->lprgelemdescParam = NULL;
5931 /* special treatment for dispinterfaces: this makes functions appear
5932 * to return their [retval] value when it is really returning an
5933 * HRESULT */
5934 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5936 if (dest->cParams &&
5937 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5939 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5940 if (elemdesc->tdesc.vt != VT_PTR)
5942 ERR("elemdesc should have started with VT_PTR instead of:\n");
5943 if (ERR_ON(ole))
5944 dump_ELEMDESC(elemdesc);
5945 return E_UNEXPECTED;
5948 /* copy last parameter to the return value. we are using a flat
5949 * buffer so there is no danger of leaking memory in
5950 * elemdescFunc */
5951 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5953 /* remove the last parameter */
5954 dest->cParams--;
5956 else
5957 /* otherwise this function is made to appear to have no return
5958 * value */
5959 dest->elemdescFunc.tdesc.vt = VT_VOID;
5963 *dest_ptr = dest;
5964 return S_OK;
5967 static void TLB_FreeVarDesc(VARDESC *var_desc)
5969 TLB_FreeElemDesc(&var_desc->elemdescVar);
5970 if (var_desc->varkind == VAR_CONST)
5971 VariantClear(var_desc->u.lpvarValue);
5972 SysFreeString((BSTR)var_desc);
5975 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5977 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5979 if (index >= This->cFuncs)
5980 return TYPE_E_ELEMENTNOTFOUND;
5982 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5983 return S_OK;
5986 /* internal function to make the inherited interfaces' methods appear
5987 * part of the interface */
5988 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5989 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5991 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5992 HRESULT hr;
5993 UINT implemented_funcs = 0;
5995 if (funcs)
5996 *funcs = 0;
5997 else
5998 *hrefoffset = DISPATCH_HREF_OFFSET;
6000 if(This->impltypes)
6002 ITypeInfo *pSubTypeInfo;
6003 UINT sub_funcs;
6005 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6006 if (FAILED(hr))
6007 return hr;
6009 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
6010 index,
6011 ppFuncDesc,
6012 &sub_funcs, hrefoffset);
6013 implemented_funcs += sub_funcs;
6014 ITypeInfo_Release(pSubTypeInfo);
6015 if (SUCCEEDED(hr))
6016 return hr;
6017 *hrefoffset += DISPATCH_HREF_OFFSET;
6020 if (funcs)
6021 *funcs = implemented_funcs + This->cFuncs;
6022 else
6023 *hrefoffset = 0;
6025 if (index < implemented_funcs)
6026 return E_INVALIDARG;
6027 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
6028 ppFuncDesc);
6031 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
6033 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
6034 while (TRUE)
6036 switch (pTypeDesc->vt)
6038 case VT_USERDEFINED:
6039 pTypeDesc->u.hreftype += hrefoffset;
6040 return;
6041 case VT_PTR:
6042 case VT_SAFEARRAY:
6043 pTypeDesc = pTypeDesc->u.lptdesc;
6044 break;
6045 case VT_CARRAY:
6046 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
6047 break;
6048 default:
6049 return;
6054 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
6056 SHORT i;
6057 for (i = 0; i < pFuncDesc->cParams; i++)
6058 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
6059 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
6062 /* ITypeInfo::GetFuncDesc
6064 * Retrieves the FUNCDESC structure that contains information about a
6065 * specified function.
6068 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
6069 LPFUNCDESC *ppFuncDesc)
6071 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6072 const FUNCDESC *internal_funcdesc;
6073 HRESULT hr;
6074 UINT hrefoffset = 0;
6076 TRACE("(%p) index %d\n", This, index);
6078 if (!ppFuncDesc)
6079 return E_INVALIDARG;
6081 if (This->needs_layout)
6082 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6084 if (This->typekind == TKIND_DISPATCH)
6085 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6086 &internal_funcdesc, NULL,
6087 &hrefoffset);
6088 else
6089 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6090 &internal_funcdesc);
6091 if (FAILED(hr))
6093 WARN("description for function %d not found\n", index);
6094 return hr;
6097 hr = TLB_AllocAndInitFuncDesc(
6098 internal_funcdesc,
6099 ppFuncDesc,
6100 This->typekind == TKIND_DISPATCH);
6102 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
6103 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6105 TRACE("-- 0x%08x\n", hr);
6106 return hr;
6109 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6111 VARDESC *dest;
6112 char *buffer;
6113 SIZE_T size = sizeof(*src);
6114 HRESULT hr;
6116 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6117 if (src->varkind == VAR_CONST)
6118 size += sizeof(VARIANT);
6119 size += TLB_SizeElemDesc(&src->elemdescVar);
6121 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6122 if (!dest) return E_OUTOFMEMORY;
6124 *dest = *src;
6125 buffer = (char *)(dest + 1);
6126 if (src->lpstrSchema)
6128 int len;
6129 dest->lpstrSchema = (LPOLESTR)buffer;
6130 len = strlenW(src->lpstrSchema);
6131 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6132 buffer += (len + 1) * sizeof(WCHAR);
6135 if (src->varkind == VAR_CONST)
6137 HRESULT hr;
6139 dest->u.lpvarValue = (VARIANT *)buffer;
6140 *dest->u.lpvarValue = *src->u.lpvarValue;
6141 buffer += sizeof(VARIANT);
6142 VariantInit(dest->u.lpvarValue);
6143 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6144 if (FAILED(hr))
6146 SysFreeString((BSTR)dest);
6147 return hr;
6150 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6151 if (FAILED(hr))
6153 if (src->varkind == VAR_CONST)
6154 VariantClear(dest->u.lpvarValue);
6155 SysFreeString((BSTR)dest);
6156 return hr;
6158 *dest_ptr = dest;
6159 return S_OK;
6162 /* ITypeInfo::GetVarDesc
6164 * Retrieves a VARDESC structure that describes the specified variable.
6167 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6168 LPVARDESC *ppVarDesc)
6170 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6171 const TLBVarDesc *pVDesc = &This->vardescs[index];
6173 TRACE("(%p) index %d\n", This, index);
6175 if(index >= This->cVars)
6176 return TYPE_E_ELEMENTNOTFOUND;
6178 if (This->needs_layout)
6179 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6181 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6184 /* ITypeInfo_GetNames
6186 * Retrieves the variable with the specified member ID (or the name of the
6187 * property or method and its parameters) that correspond to the specified
6188 * function ID.
6190 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6191 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6193 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6194 const TLBFuncDesc *pFDesc;
6195 const TLBVarDesc *pVDesc;
6196 int i;
6197 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6199 if(!rgBstrNames)
6200 return E_INVALIDARG;
6202 *pcNames = 0;
6204 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
6205 if(pFDesc)
6207 if(!cMaxNames || !pFDesc->Name)
6208 return S_OK;
6210 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6211 ++(*pcNames);
6213 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6214 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6215 return S_OK;
6216 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6217 ++(*pcNames);
6219 return S_OK;
6222 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
6223 if(pVDesc)
6225 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6226 *pcNames=1;
6228 else
6230 if(This->impltypes &&
6231 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
6232 /* recursive search */
6233 ITypeInfo *pTInfo;
6234 HRESULT result;
6235 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6236 if(SUCCEEDED(result))
6238 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6239 ITypeInfo_Release(pTInfo);
6240 return result;
6242 WARN("Could not search inherited interface!\n");
6244 else
6246 WARN("no names found\n");
6248 *pcNames=0;
6249 return TYPE_E_ELEMENTNOTFOUND;
6251 return S_OK;
6255 /* ITypeInfo::GetRefTypeOfImplType
6257 * If a type description describes a COM class, it retrieves the type
6258 * description of the implemented interface types. For an interface,
6259 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6260 * if any exist.
6263 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6264 ITypeInfo2 *iface,
6265 UINT index,
6266 HREFTYPE *pRefType)
6268 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6269 HRESULT hr = S_OK;
6271 TRACE("(%p) index %d\n", This, index);
6272 if (TRACE_ON(ole)) dump_TypeInfo(This);
6274 if(index==(UINT)-1)
6276 /* only valid on dual interfaces;
6277 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6280 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6282 *pRefType = -2;
6284 else
6286 hr = TYPE_E_ELEMENTNOTFOUND;
6289 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6291 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6292 *pRefType = This->pTypeLib->dispatch_href;
6294 else
6296 if(index >= This->cImplTypes)
6297 hr = TYPE_E_ELEMENTNOTFOUND;
6298 else{
6299 *pRefType = This->impltypes[index].hRef;
6300 if(This->typekind == TKIND_INTERFACE)
6301 *pRefType |= 0x2;
6305 if(TRACE_ON(ole))
6307 if(SUCCEEDED(hr))
6308 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6309 else
6310 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6313 return hr;
6316 /* ITypeInfo::GetImplTypeFlags
6318 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6319 * or base interface in a type description.
6321 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6322 UINT index, INT *pImplTypeFlags)
6324 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6326 TRACE("(%p) index %d\n", This, index);
6328 if(!pImplTypeFlags)
6329 return E_INVALIDARG;
6331 if(This->typekind == TKIND_DISPATCH && index == 0){
6332 *pImplTypeFlags = 0;
6333 return S_OK;
6336 if(index >= This->cImplTypes)
6337 return TYPE_E_ELEMENTNOTFOUND;
6339 *pImplTypeFlags = This->impltypes[index].implflags;
6341 return S_OK;
6344 /* GetIDsOfNames
6345 * Maps between member names and member IDs, and parameter names and
6346 * parameter IDs.
6348 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6349 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6351 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6352 const TLBVarDesc *pVDesc;
6353 HRESULT ret=S_OK;
6354 UINT i, fdc;
6356 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6357 cNames);
6359 /* init out parameters in case of failure */
6360 for (i = 0; i < cNames; i++)
6361 pMemId[i] = MEMBERID_NIL;
6363 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6364 int j;
6365 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6366 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6367 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6368 for(i=1; i < cNames; i++){
6369 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6370 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6371 break;
6372 if( j<pFDesc->funcdesc.cParams)
6373 pMemId[i]=j;
6374 else
6375 ret=DISP_E_UNKNOWNNAME;
6377 TRACE("-- 0x%08x\n", ret);
6378 return ret;
6381 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6382 if(pVDesc){
6383 if(cNames)
6384 *pMemId = pVDesc->vardesc.memid;
6385 return ret;
6387 /* not found, see if it can be found in an inherited interface */
6388 if(This->impltypes) {
6389 /* recursive search */
6390 ITypeInfo *pTInfo;
6391 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6392 if(SUCCEEDED(ret)){
6393 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6394 ITypeInfo_Release(pTInfo);
6395 return ret;
6397 WARN("Could not search inherited interface!\n");
6398 } else
6399 WARN("no names found\n");
6400 return DISP_E_UNKNOWNNAME;
6404 #ifdef __i386__
6406 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6407 __ASM_GLOBAL_FUNC( call_method,
6408 "pushl %ebp\n\t"
6409 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6410 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6411 "movl %esp,%ebp\n\t"
6412 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6413 "pushl %esi\n\t"
6414 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6415 "pushl %edi\n\t"
6416 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6417 "movl 12(%ebp),%edx\n\t"
6418 "movl %esp,%edi\n\t"
6419 "shll $2,%edx\n\t"
6420 "jz 1f\n\t"
6421 "subl %edx,%edi\n\t"
6422 "andl $~15,%edi\n\t"
6423 "movl %edi,%esp\n\t"
6424 "movl 12(%ebp),%ecx\n\t"
6425 "movl 16(%ebp),%esi\n\t"
6426 "cld\n\t"
6427 "rep; movsl\n"
6428 "1:\tcall *8(%ebp)\n\t"
6429 "subl %esp,%edi\n\t"
6430 "movl 20(%ebp),%ecx\n\t"
6431 "movl %edi,(%ecx)\n\t"
6432 "leal -8(%ebp),%esp\n\t"
6433 "popl %edi\n\t"
6434 __ASM_CFI(".cfi_same_value %edi\n\t")
6435 "popl %esi\n\t"
6436 __ASM_CFI(".cfi_same_value %esi\n\t")
6437 "popl %ebp\n\t"
6438 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6439 __ASM_CFI(".cfi_same_value %ebp\n\t")
6440 "ret" )
6442 /* same function but returning floating point */
6443 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6445 /* ITypeInfo::Invoke
6447 * Invokes a method, or accesses a property of an object, that implements the
6448 * interface described by the type description.
6450 DWORD
6451 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6452 DWORD res;
6453 int stack_offset;
6455 if (TRACE_ON(ole)) {
6456 int i;
6457 TRACE("Calling %p(",func);
6458 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6459 if (nrargs > 30) TRACE("...");
6460 TRACE(")\n");
6463 switch (callconv) {
6464 case CC_STDCALL:
6465 case CC_CDECL:
6466 res = call_method( func, nrargs, args, &stack_offset );
6467 break;
6468 default:
6469 FIXME("unsupported calling convention %d\n",callconv);
6470 res = -1;
6471 break;
6473 TRACE("returns %08x\n",res);
6474 return res;
6477 #elif defined(__x86_64__)
6479 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6480 __ASM_GLOBAL_FUNC( call_method,
6481 "pushq %rbp\n\t"
6482 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6483 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6484 "movq %rsp,%rbp\n\t"
6485 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6486 "pushq %rsi\n\t"
6487 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6488 "pushq %rdi\n\t"
6489 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6490 "movq %rcx,%rax\n\t"
6491 "movq $4,%rcx\n\t"
6492 "cmp %rcx,%rdx\n\t"
6493 "cmovgq %rdx,%rcx\n\t"
6494 "leaq 0(,%rcx,8),%rdx\n\t"
6495 "subq %rdx,%rsp\n\t"
6496 "andq $~15,%rsp\n\t"
6497 "movq %rsp,%rdi\n\t"
6498 "movq %r8,%rsi\n\t"
6499 "rep; movsq\n\t"
6500 "movq 0(%rsp),%rcx\n\t"
6501 "movq 8(%rsp),%rdx\n\t"
6502 "movq 16(%rsp),%r8\n\t"
6503 "movq 24(%rsp),%r9\n\t"
6504 "movq %rcx,%xmm0\n\t"
6505 "movq %rdx,%xmm1\n\t"
6506 "movq %r8,%xmm2\n\t"
6507 "movq %r9,%xmm3\n\t"
6508 "callq *%rax\n\t"
6509 "leaq -16(%rbp),%rsp\n\t"
6510 "popq %rdi\n\t"
6511 __ASM_CFI(".cfi_same_value %rdi\n\t")
6512 "popq %rsi\n\t"
6513 __ASM_CFI(".cfi_same_value %rsi\n\t")
6514 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6515 "popq %rbp\n\t"
6516 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6517 __ASM_CFI(".cfi_same_value %rbp\n\t")
6518 "ret")
6520 /* same function but returning floating point */
6521 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6523 #endif /* __x86_64__ */
6525 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6527 HRESULT hr = S_OK;
6528 ITypeInfo *tinfo2 = NULL;
6529 TYPEATTR *tattr = NULL;
6531 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6532 if (hr)
6534 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6535 "hr = 0x%08x\n",
6536 tdesc->u.hreftype, hr);
6537 return hr;
6539 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6540 if (hr)
6542 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6543 ITypeInfo_Release(tinfo2);
6544 return hr;
6547 switch (tattr->typekind)
6549 case TKIND_ENUM:
6550 *vt |= VT_I4;
6551 break;
6553 case TKIND_ALIAS:
6554 tdesc = &tattr->tdescAlias;
6555 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6556 break;
6558 case TKIND_INTERFACE:
6559 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6560 *vt |= VT_DISPATCH;
6561 else
6562 *vt |= VT_UNKNOWN;
6563 break;
6565 case TKIND_DISPATCH:
6566 *vt |= VT_DISPATCH;
6567 break;
6569 case TKIND_COCLASS:
6570 *vt |= VT_DISPATCH;
6571 break;
6573 case TKIND_RECORD:
6574 FIXME("TKIND_RECORD unhandled.\n");
6575 hr = E_NOTIMPL;
6576 break;
6578 case TKIND_UNION:
6579 FIXME("TKIND_UNION unhandled.\n");
6580 hr = E_NOTIMPL;
6581 break;
6583 default:
6584 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6585 hr = E_NOTIMPL;
6586 break;
6588 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6589 ITypeInfo_Release(tinfo2);
6590 return hr;
6593 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6595 HRESULT hr = S_OK;
6597 /* enforce only one level of pointer indirection */
6598 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6600 tdesc = tdesc->u.lptdesc;
6602 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6603 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6604 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6605 if ((tdesc->vt == VT_USERDEFINED) ||
6606 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6608 VARTYPE vt_userdefined = 0;
6609 const TYPEDESC *tdesc_userdefined = tdesc;
6610 if (tdesc->vt == VT_PTR)
6612 vt_userdefined = VT_BYREF;
6613 tdesc_userdefined = tdesc->u.lptdesc;
6615 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6616 if ((hr == S_OK) &&
6617 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6618 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6620 *vt |= vt_userdefined;
6621 return S_OK;
6624 *vt = VT_BYREF;
6627 switch (tdesc->vt)
6629 case VT_HRESULT:
6630 *vt |= VT_ERROR;
6631 break;
6632 case VT_USERDEFINED:
6633 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6634 break;
6635 case VT_VOID:
6636 case VT_CARRAY:
6637 case VT_PTR:
6638 case VT_LPSTR:
6639 case VT_LPWSTR:
6640 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6641 hr = DISP_E_BADVARTYPE;
6642 break;
6643 case VT_SAFEARRAY:
6644 *vt |= VT_ARRAY;
6645 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6646 break;
6647 case VT_INT:
6648 *vt |= VT_I4;
6649 break;
6650 case VT_UINT:
6651 *vt |= VT_UI4;
6652 break;
6653 default:
6654 *vt |= tdesc->vt;
6655 break;
6657 return hr;
6660 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6662 ITypeInfo *tinfo2;
6663 TYPEATTR *tattr;
6664 HRESULT hres;
6666 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6667 if(FAILED(hres))
6668 return hres;
6670 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6671 if(FAILED(hres)) {
6672 ITypeInfo_Release(tinfo2);
6673 return hres;
6676 switch(tattr->typekind) {
6677 case TKIND_ALIAS:
6678 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6679 break;
6681 case TKIND_INTERFACE:
6682 case TKIND_DISPATCH:
6683 *guid = tattr->guid;
6684 break;
6686 default:
6687 ERR("Unexpected typekind %d\n", tattr->typekind);
6688 hres = E_UNEXPECTED;
6691 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6692 ITypeInfo_Release(tinfo2);
6693 return hres;
6696 /***********************************************************************
6697 * DispCallFunc (OLEAUT32.@)
6699 * Invokes a function of the specified calling convention, passing the
6700 * specified arguments and returns the result.
6702 * PARAMS
6703 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6704 * oVft [I] The offset in the vtable. See notes.
6705 * cc [I] Calling convention of the function to call.
6706 * vtReturn [I] The return type of the function.
6707 * cActuals [I] Number of parameters.
6708 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6709 * prgpvarg [I] The arguments to pass.
6710 * pvargResult [O] The return value of the function. Can be NULL.
6712 * RETURNS
6713 * Success: S_OK.
6714 * Failure: HRESULT code.
6716 * NOTES
6717 * The HRESULT return value of this function is not affected by the return
6718 * value of the user supplied function, which is returned in pvargResult.
6720 * If pvInstance is NULL then a non-object function is to be called and oVft
6721 * is the address of the function to call.
6723 * The cc parameter can be one of the following values:
6724 *|CC_FASTCALL
6725 *|CC_CDECL
6726 *|CC_PASCAL
6727 *|CC_STDCALL
6728 *|CC_FPFASTCALL
6729 *|CC_SYSCALL
6730 *|CC_MPWCDECL
6731 *|CC_MPWPASCAL
6734 HRESULT WINAPI
6735 DispCallFunc(
6736 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6737 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6739 #ifdef __i386__
6740 int argspos, stack_offset;
6741 void *func;
6742 UINT i;
6743 DWORD *args;
6745 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6746 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6747 pvargResult, V_VT(pvargResult));
6749 if (cc != CC_STDCALL && cc != CC_CDECL)
6751 FIXME("unsupported calling convention %d\n",cc);
6752 return E_INVALIDARG;
6755 /* maximum size for an argument is sizeof(VARIANT) */
6756 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6758 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6759 argspos = 1;
6760 if (pvInstance)
6762 const FARPROC *vtable = *(FARPROC **)pvInstance;
6763 func = vtable[oVft/sizeof(void *)];
6764 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6766 else func = (void *)oVft;
6768 for (i = 0; i < cActuals; i++)
6770 VARIANT *arg = prgpvarg[i];
6772 switch (prgvt[i])
6774 case VT_EMPTY:
6775 break;
6776 case VT_I8:
6777 case VT_UI8:
6778 case VT_R8:
6779 case VT_DATE:
6780 case VT_CY:
6781 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6782 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6783 break;
6784 case VT_DECIMAL:
6785 case VT_VARIANT:
6786 memcpy( &args[argspos], arg, sizeof(*arg) );
6787 argspos += sizeof(*arg) / sizeof(DWORD);
6788 break;
6789 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6790 args[argspos++] = V_BOOL(arg);
6791 break;
6792 default:
6793 args[argspos++] = V_UI4(arg);
6794 break;
6796 TRACE("arg %u: type %d\n",i,prgvt[i]);
6797 dump_Variant(arg);
6800 switch (vtReturn)
6802 case VT_EMPTY:
6803 call_method( func, argspos - 1, args + 1, &stack_offset );
6804 break;
6805 case VT_R4:
6806 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6807 break;
6808 case VT_R8:
6809 case VT_DATE:
6810 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6811 break;
6812 case VT_DECIMAL:
6813 case VT_VARIANT:
6814 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6815 call_method( func, argspos, args, &stack_offset );
6816 break;
6817 case VT_I8:
6818 case VT_UI8:
6819 case VT_CY:
6820 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6821 break;
6822 case VT_HRESULT:
6823 WARN("invalid return type %u\n", vtReturn);
6824 heap_free( args );
6825 return E_INVALIDARG;
6826 default:
6827 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6828 break;
6830 heap_free( args );
6831 if (stack_offset && cc == CC_STDCALL)
6833 WARN( "stack pointer off by %d\n", stack_offset );
6834 return DISP_E_BADCALLEE;
6836 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6837 TRACE("retval: "); dump_Variant(pvargResult);
6838 return S_OK;
6840 #elif defined(__x86_64__)
6841 int argspos;
6842 UINT i;
6843 DWORD_PTR *args;
6844 void *func;
6846 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6847 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6848 pvargResult, V_VT(pvargResult));
6850 if (cc != CC_STDCALL && cc != CC_CDECL)
6852 FIXME("unsupported calling convention %d\n",cc);
6853 return E_INVALIDARG;
6856 /* maximum size for an argument is sizeof(DWORD_PTR) */
6857 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6859 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6860 argspos = 1;
6861 if (pvInstance)
6863 const FARPROC *vtable = *(FARPROC **)pvInstance;
6864 func = vtable[oVft/sizeof(void *)];
6865 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6867 else func = (void *)oVft;
6869 for (i = 0; i < cActuals; i++)
6871 VARIANT *arg = prgpvarg[i];
6873 switch (prgvt[i])
6875 case VT_DECIMAL:
6876 case VT_VARIANT:
6877 args[argspos++] = (ULONG_PTR)arg;
6878 break;
6879 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6880 args[argspos++] = V_BOOL(arg);
6881 break;
6882 default:
6883 args[argspos++] = V_UI8(arg);
6884 break;
6886 TRACE("arg %u: type %d\n",i,prgvt[i]);
6887 dump_Variant(arg);
6890 switch (vtReturn)
6892 case VT_R4:
6893 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6894 break;
6895 case VT_R8:
6896 case VT_DATE:
6897 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6898 break;
6899 case VT_DECIMAL:
6900 case VT_VARIANT:
6901 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6902 call_method( func, argspos, args );
6903 break;
6904 case VT_HRESULT:
6905 WARN("invalid return type %u\n", vtReturn);
6906 heap_free( args );
6907 return E_INVALIDARG;
6908 default:
6909 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6910 break;
6912 heap_free( args );
6913 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6914 TRACE("retval: "); dump_Variant(pvargResult);
6915 return S_OK;
6917 #else
6918 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6919 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6920 return E_NOTIMPL;
6921 #endif
6924 static inline BOOL func_restricted( const FUNCDESC *desc )
6926 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6929 #define INVBUF_ELEMENT_SIZE \
6930 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6931 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6932 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6933 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6934 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6935 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6936 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6937 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6939 static HRESULT WINAPI ITypeInfo_fnInvoke(
6940 ITypeInfo2 *iface,
6941 VOID *pIUnk,
6942 MEMBERID memid,
6943 UINT16 wFlags,
6944 DISPPARAMS *pDispParams,
6945 VARIANT *pVarResult,
6946 EXCEPINFO *pExcepInfo,
6947 UINT *pArgErr)
6949 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6950 int i;
6951 unsigned int var_index;
6952 TYPEKIND type_kind;
6953 HRESULT hres;
6954 const TLBFuncDesc *pFuncInfo;
6955 UINT fdc;
6957 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6958 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6961 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6962 return DISP_E_MEMBERNOTFOUND;
6964 if (!pDispParams)
6966 ERR("NULL pDispParams not allowed\n");
6967 return E_INVALIDARG;
6970 dump_DispParms(pDispParams);
6972 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6974 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6975 pDispParams->cNamedArgs, pDispParams->cArgs);
6976 return E_INVALIDARG;
6979 /* we do this instead of using GetFuncDesc since it will return a fake
6980 * FUNCDESC for dispinterfaces and we want the real function description */
6981 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6982 pFuncInfo = &This->funcdescs[fdc];
6983 if ((memid == pFuncInfo->funcdesc.memid) &&
6984 (wFlags & pFuncInfo->funcdesc.invkind) &&
6985 !func_restricted( &pFuncInfo->funcdesc ))
6986 break;
6989 if (fdc < This->cFuncs) {
6990 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6992 if (TRACE_ON(ole))
6994 TRACE("invoking:\n");
6995 dump_TLBFuncDescOne(pFuncInfo);
6998 switch (func_desc->funckind) {
6999 case FUNC_PUREVIRTUAL:
7000 case FUNC_VIRTUAL: {
7001 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7002 VARIANT varresult;
7003 VARIANT retval; /* pointer for storing byref retvals in */
7004 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7005 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7006 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7007 UINT cNamedArgs = pDispParams->cNamedArgs;
7008 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7009 UINT vargs_converted=0;
7011 hres = S_OK;
7013 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7015 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7017 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7018 hres = DISP_E_PARAMNOTFOUND;
7019 goto func_fail;
7023 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7025 ERR("functions with the vararg attribute do not support named arguments\n");
7026 hres = DISP_E_NONAMEDARGS;
7027 goto func_fail;
7030 for (i = 0; i < func_desc->cParams; i++)
7032 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7033 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7034 if (FAILED(hres))
7035 goto func_fail;
7038 TRACE("changing args\n");
7039 for (i = 0; i < func_desc->cParams; i++)
7041 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7042 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7043 VARIANTARG *src_arg;
7045 if (wParamFlags & PARAMFLAG_FLCID)
7047 VARIANTARG *arg;
7048 arg = prgpvarg[i] = &rgvarg[i];
7049 V_VT(arg) = VT_I4;
7050 V_I4(arg) = This->pTypeLib->lcid;
7051 continue;
7054 src_arg = NULL;
7056 if (cNamedArgs)
7058 USHORT j;
7059 for (j = 0; j < cNamedArgs; j++)
7060 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7062 src_arg = &pDispParams->rgvarg[j];
7063 break;
7067 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7069 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7070 vargs_converted++;
7073 if (wParamFlags & PARAMFLAG_FRETVAL)
7075 /* under most conditions the caller is not allowed to
7076 * pass in a dispparam arg in the index of what would be
7077 * the retval parameter. however, there is an exception
7078 * where the extra parameter is used in an extra
7079 * IDispatch::Invoke below */
7080 if ((i < pDispParams->cArgs) &&
7081 ((func_desc->cParams != 1) || !pVarResult ||
7082 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7084 hres = DISP_E_BADPARAMCOUNT;
7085 break;
7088 /* note: this check is placed so that if the caller passes
7089 * in a VARIANTARG for the retval we just ignore it, like
7090 * native does */
7091 if (i == func_desc->cParams - 1)
7093 VARIANTARG *arg;
7094 arg = prgpvarg[i] = &rgvarg[i];
7095 memset(arg, 0, sizeof(*arg));
7096 V_VT(arg) = rgvt[i];
7097 memset(&retval, 0, sizeof(retval));
7098 V_BYREF(arg) = &retval;
7100 else
7102 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7103 hres = E_UNEXPECTED;
7104 break;
7107 else if (src_arg)
7109 dump_Variant(src_arg);
7111 if(rgvt[i]!=V_VT(src_arg))
7113 if (rgvt[i] == VT_VARIANT)
7114 hres = VariantCopy(&rgvarg[i], src_arg);
7115 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7117 if (rgvt[i] == V_VT(src_arg))
7118 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7119 else
7121 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7122 if (wParamFlags & PARAMFLAG_FIN)
7123 hres = VariantCopy(&missing_arg[i], src_arg);
7124 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7126 V_VT(&rgvarg[i]) = rgvt[i];
7128 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
7130 SAFEARRAY *a;
7131 SAFEARRAYBOUND bound;
7132 VARIANT *v;
7133 LONG j;
7134 bound.lLbound = 0;
7135 bound.cElements = pDispParams->cArgs-i;
7136 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7138 ERR("SafeArrayCreate failed\n");
7139 break;
7141 hres = SafeArrayAccessData(a, (LPVOID)&v);
7142 if (hres != S_OK)
7144 ERR("SafeArrayAccessData failed with %x\n", hres);
7145 SafeArrayDestroy(a);
7146 break;
7148 for (j = 0; j < bound.cElements; j++)
7149 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7150 hres = SafeArrayUnaccessData(a);
7151 if (hres != S_OK)
7153 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7154 SafeArrayDestroy(a);
7155 break;
7157 V_ARRAY(&rgvarg[i]) = a;
7158 V_VT(&rgvarg[i]) = rgvt[i];
7160 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7162 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7163 if (wParamFlags & PARAMFLAG_FIN)
7164 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7165 else
7166 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7167 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7168 V_VT(&rgvarg[i]) = rgvt[i];
7170 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7172 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7173 V_VT(&rgvarg[i]) = rgvt[i];
7175 else
7177 /* FIXME: this doesn't work for VT_BYREF arguments if
7178 * they are not the same type as in the paramdesc */
7179 V_VT(&rgvarg[i]) = V_VT(src_arg);
7180 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7181 V_VT(&rgvarg[i]) = rgvt[i];
7184 if (FAILED(hres))
7186 ERR("failed to convert param %d to %s%s from %s%s\n", i,
7187 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
7188 debugstr_VT(src_arg), debugstr_VF(src_arg));
7189 break;
7191 prgpvarg[i] = &rgvarg[i];
7193 else
7195 prgpvarg[i] = src_arg;
7198 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7199 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7200 && V_UNKNOWN(prgpvarg[i])) {
7201 IUnknown *userdefined_iface;
7202 GUID guid;
7204 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7205 if(FAILED(hres))
7206 break;
7208 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7209 if(FAILED(hres)) {
7210 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7211 break;
7214 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7215 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7218 else if (wParamFlags & PARAMFLAG_FOPT)
7220 VARIANTARG *arg;
7221 arg = prgpvarg[i] = &rgvarg[i];
7222 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7224 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7225 if (FAILED(hres))
7226 break;
7228 else
7230 VARIANTARG *missing_arg;
7231 /* if the function wants a pointer to a variant then
7232 * set that up, otherwise just pass the VT_ERROR in
7233 * the argument by value */
7234 if (rgvt[i] & VT_BYREF)
7236 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7237 V_VT(arg) = VT_VARIANT | VT_BYREF;
7238 V_VARIANTREF(arg) = missing_arg;
7240 else
7241 missing_arg = arg;
7242 V_VT(missing_arg) = VT_ERROR;
7243 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7246 else
7248 hres = DISP_E_BADPARAMCOUNT;
7249 break;
7252 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7254 /* VT_VOID is a special case for return types, so it is not
7255 * handled in the general function */
7256 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7257 V_VT(&varresult) = VT_EMPTY;
7258 else
7260 V_VT(&varresult) = 0;
7261 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7262 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7265 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7266 V_VT(&varresult), func_desc->cParams, rgvt,
7267 prgpvarg, &varresult);
7269 vargs_converted = 0;
7271 for (i = 0; i < func_desc->cParams; i++)
7273 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7274 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7276 if (wParamFlags & PARAMFLAG_FLCID)
7277 continue;
7278 else if (wParamFlags & PARAMFLAG_FRETVAL)
7280 if (TRACE_ON(ole))
7282 TRACE("[retval] value: ");
7283 dump_Variant(prgpvarg[i]);
7286 if (pVarResult)
7288 VariantInit(pVarResult);
7289 /* deref return value */
7290 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7293 VARIANT_ClearInd(prgpvarg[i]);
7295 else if (vargs_converted < pDispParams->cArgs)
7297 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7298 if (wParamFlags & PARAMFLAG_FOUT)
7300 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7302 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7304 if (FAILED(hres))
7306 ERR("failed to convert param %d to vt %d\n", i,
7307 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7308 break;
7312 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7313 func_desc->cParamsOpt < 0 &&
7314 i == func_desc->cParams-1)
7316 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7317 LONG j, ubound;
7318 VARIANT *v;
7319 hres = SafeArrayGetUBound(a, 1, &ubound);
7320 if (hres != S_OK)
7322 ERR("SafeArrayGetUBound failed with %x\n", hres);
7323 break;
7325 hres = SafeArrayAccessData(a, (LPVOID)&v);
7326 if (hres != S_OK)
7328 ERR("SafeArrayAccessData failed with %x\n", hres);
7329 break;
7331 for (j = 0; j <= ubound; j++)
7332 VariantClear(&v[j]);
7333 hres = SafeArrayUnaccessData(a);
7334 if (hres != S_OK)
7336 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7337 break;
7340 VariantClear(&rgvarg[i]);
7341 vargs_converted++;
7343 else if (wParamFlags & PARAMFLAG_FOPT)
7345 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7346 VariantClear(&rgvarg[i]);
7349 VariantClear(&missing_arg[i]);
7352 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7354 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7355 hres = DISP_E_EXCEPTION;
7356 if (pExcepInfo)
7358 IErrorInfo *pErrorInfo;
7359 pExcepInfo->scode = V_ERROR(&varresult);
7360 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7362 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7363 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7364 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7365 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7367 IErrorInfo_Release(pErrorInfo);
7371 if (V_VT(&varresult) != VT_ERROR)
7373 TRACE("varresult value: ");
7374 dump_Variant(&varresult);
7376 if (pVarResult)
7378 VariantClear(pVarResult);
7379 *pVarResult = varresult;
7381 else
7382 VariantClear(&varresult);
7385 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7386 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7387 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7388 (pDispParams->cArgs != 0))
7390 if (V_VT(pVarResult) == VT_DISPATCH)
7392 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7393 /* Note: not VariantClear; we still need the dispatch
7394 * pointer to be valid */
7395 VariantInit(pVarResult);
7396 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7397 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7398 pDispParams, pVarResult, pExcepInfo, pArgErr);
7399 IDispatch_Release(pDispatch);
7401 else
7403 VariantClear(pVarResult);
7404 hres = DISP_E_NOTACOLLECTION;
7408 func_fail:
7409 heap_free(buffer);
7410 break;
7412 case FUNC_DISPATCH: {
7413 IDispatch *disp;
7415 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7416 if (SUCCEEDED(hres)) {
7417 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7418 hres = IDispatch_Invoke(
7419 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7420 pVarResult,pExcepInfo,pArgErr
7422 if (FAILED(hres))
7423 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7424 IDispatch_Release(disp);
7425 } else
7426 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7427 break;
7429 default:
7430 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7431 hres = E_FAIL;
7432 break;
7435 TRACE("-- 0x%08x\n", hres);
7436 return hres;
7438 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7439 VARDESC *var_desc;
7441 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7442 if(FAILED(hres)) return hres;
7444 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7445 dump_VARDESC(var_desc);
7446 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7447 return E_NOTIMPL;
7450 /* not found, look for it in inherited interfaces */
7451 ITypeInfo2_GetTypeKind(iface, &type_kind);
7452 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7453 if(This->impltypes) {
7454 /* recursive search */
7455 ITypeInfo *pTInfo;
7456 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7457 if(SUCCEEDED(hres)){
7458 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7459 ITypeInfo_Release(pTInfo);
7460 return hres;
7462 WARN("Could not search inherited interface!\n");
7465 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7466 return DISP_E_MEMBERNOTFOUND;
7469 /* ITypeInfo::GetDocumentation
7471 * Retrieves the documentation string, the complete Help file name and path,
7472 * and the context ID for the Help topic for a specified type description.
7474 * (Can be tested by the Visual Basic Editor in Word for instance.)
7476 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7477 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7478 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7480 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7481 const TLBFuncDesc *pFDesc;
7482 const TLBVarDesc *pVDesc;
7483 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7484 " HelpContext(%p) HelpFile(%p)\n",
7485 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7486 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7487 if(pBstrName)
7488 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7489 if(pBstrDocString)
7490 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7491 if(pdwHelpContext)
7492 *pdwHelpContext=This->dwHelpContext;
7493 if(pBstrHelpFile)
7494 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7495 return S_OK;
7496 }else {/* for a member */
7497 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7498 if(pFDesc){
7499 if(pBstrName)
7500 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7501 if(pBstrDocString)
7502 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7503 if(pdwHelpContext)
7504 *pdwHelpContext=pFDesc->helpcontext;
7505 if(pBstrHelpFile)
7506 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7507 return S_OK;
7509 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7510 if(pVDesc){
7511 if(pBstrName)
7512 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7513 if(pBstrDocString)
7514 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7515 if(pdwHelpContext)
7516 *pdwHelpContext=pVDesc->HelpContext;
7517 if(pBstrHelpFile)
7518 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7519 return S_OK;
7523 if(This->impltypes &&
7524 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7525 /* recursive search */
7526 ITypeInfo *pTInfo;
7527 HRESULT result;
7528 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7529 if(SUCCEEDED(result)) {
7530 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7531 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7532 ITypeInfo_Release(pTInfo);
7533 return result;
7535 WARN("Could not search inherited interface!\n");
7538 WARN("member %d not found\n", memid);
7539 return TYPE_E_ELEMENTNOTFOUND;
7542 /* ITypeInfo::GetDllEntry
7544 * Retrieves a description or specification of an entry point for a function
7545 * in a DLL.
7547 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7548 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7549 WORD *pwOrdinal)
7551 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7552 const TLBFuncDesc *pFDesc;
7554 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7556 if (pBstrDllName) *pBstrDllName = NULL;
7557 if (pBstrName) *pBstrName = NULL;
7558 if (pwOrdinal) *pwOrdinal = 0;
7560 if (This->typekind != TKIND_MODULE)
7561 return TYPE_E_BADMODULEKIND;
7563 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7564 if(pFDesc){
7565 dump_TypeInfo(This);
7566 if (TRACE_ON(ole))
7567 dump_TLBFuncDescOne(pFDesc);
7569 if (pBstrDllName)
7570 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7572 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7573 if (pBstrName)
7574 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7575 if (pwOrdinal)
7576 *pwOrdinal = -1;
7577 return S_OK;
7579 if (pBstrName)
7580 *pBstrName = NULL;
7581 if (pwOrdinal)
7582 *pwOrdinal = LOWORD(pFDesc->Entry);
7583 return S_OK;
7585 return TYPE_E_ELEMENTNOTFOUND;
7588 /* internal function to make the inherited interfaces' methods appear
7589 * part of the interface */
7590 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7591 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7593 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7594 HRESULT hr;
7596 TRACE("%p, 0x%x\n", iface, *hRefType);
7598 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7600 ITypeInfo *pSubTypeInfo;
7602 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7603 if (FAILED(hr))
7604 return hr;
7606 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7607 hRefType, ppTInfo);
7608 ITypeInfo_Release(pSubTypeInfo);
7609 if (SUCCEEDED(hr))
7610 return hr;
7612 *hRefType -= DISPATCH_HREF_OFFSET;
7614 if (!(*hRefType & DISPATCH_HREF_MASK))
7615 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7616 else
7617 return E_FAIL;
7620 /* ITypeInfo::GetRefTypeInfo
7622 * If a type description references other type descriptions, it retrieves
7623 * the referenced type descriptions.
7625 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7626 ITypeInfo2 *iface,
7627 HREFTYPE hRefType,
7628 ITypeInfo **ppTInfo)
7630 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7631 HRESULT result = E_FAIL;
7633 if(!ppTInfo)
7634 return E_INVALIDARG;
7636 if ((INT)hRefType < 0) {
7637 ITypeInfoImpl *pTypeInfoImpl;
7639 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7640 !(This->typekind == TKIND_INTERFACE ||
7641 This->typekind == TKIND_DISPATCH))
7642 return TYPE_E_ELEMENTNOTFOUND;
7644 /* when we meet a DUAL typeinfo, we must create the alternate
7645 * version of it.
7647 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7649 *pTypeInfoImpl = *This;
7650 pTypeInfoImpl->ref = 0;
7651 list_init(&pTypeInfoImpl->custdata_list);
7653 if (This->typekind == TKIND_INTERFACE)
7654 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7655 else
7656 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7658 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7659 /* the AddRef implicitly adds a reference to the parent typelib, which
7660 * stops the copied data from being destroyed until the new typeinfo's
7661 * refcount goes to zero, but we need to signal to the new instance to
7662 * not free its data structures when it is destroyed */
7663 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7665 ITypeInfo_AddRef(*ppTInfo);
7667 result = S_OK;
7668 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7669 (This->typekind == TKIND_DISPATCH))
7671 HREFTYPE href_dispatch = hRefType;
7672 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7673 } else {
7674 TLBRefType *ref_type;
7675 ITypeLib *pTLib = NULL;
7676 UINT i;
7678 if(!(hRefType & 0x1)){
7679 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7681 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7683 result = S_OK;
7684 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7685 ITypeInfo_AddRef(*ppTInfo);
7686 goto end;
7691 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7693 if(ref_type->reference == (hRefType & (~0x3)))
7694 break;
7696 if(&ref_type->entry == &This->pTypeLib->ref_list)
7698 FIXME("Can't find pRefType for ref %x\n", hRefType);
7699 goto end;
7702 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7703 UINT Index;
7704 TRACE("internal reference\n");
7705 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7706 } else {
7707 if(ref_type->pImpTLInfo->pImpTypeLib) {
7708 TRACE("typeinfo in imported typelib that is already loaded\n");
7709 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7710 ITypeLib_AddRef(pTLib);
7711 result = S_OK;
7712 } else {
7713 BSTR libnam;
7715 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7717 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7718 ref_type->pImpTLInfo->wVersionMajor,
7719 ref_type->pImpTLInfo->wVersionMinor,
7720 This->pTypeLib->syskind,
7721 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7722 if(FAILED(result))
7723 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7725 result = LoadTypeLib(libnam, &pTLib);
7726 SysFreeString(libnam);
7728 if(SUCCEEDED(result)) {
7729 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7730 ITypeLib_AddRef(pTLib);
7734 if(SUCCEEDED(result)) {
7735 if(ref_type->index == TLB_REF_USE_GUID)
7736 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7737 else
7738 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7740 if (pTLib != NULL)
7741 ITypeLib_Release(pTLib);
7744 end:
7745 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7746 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7747 return result;
7750 /* ITypeInfo::AddressOfMember
7752 * Retrieves the addresses of static functions or variables, such as those
7753 * defined in a DLL.
7755 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7756 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7758 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7759 HRESULT hr;
7760 BSTR dll, entry;
7761 WORD ordinal;
7762 HMODULE module;
7764 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7766 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7767 if (FAILED(hr))
7768 return hr;
7770 module = LoadLibraryW(dll);
7771 if (!module)
7773 ERR("couldn't load %s\n", debugstr_w(dll));
7774 SysFreeString(dll);
7775 SysFreeString(entry);
7776 return STG_E_FILENOTFOUND;
7778 /* FIXME: store library somewhere where we can free it */
7780 if (entry)
7782 LPSTR entryA;
7783 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7784 entryA = heap_alloc(len);
7785 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7787 *ppv = GetProcAddress(module, entryA);
7788 if (!*ppv)
7789 ERR("function not found %s\n", debugstr_a(entryA));
7791 heap_free(entryA);
7793 else
7795 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7796 if (!*ppv)
7797 ERR("function not found %d\n", ordinal);
7800 SysFreeString(dll);
7801 SysFreeString(entry);
7803 if (!*ppv)
7804 return TYPE_E_DLLFUNCTIONNOTFOUND;
7806 return S_OK;
7809 /* ITypeInfo::CreateInstance
7811 * Creates a new instance of a type that describes a component object class
7812 * (coclass).
7814 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7815 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7817 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7818 HRESULT hr;
7819 TYPEATTR *pTA;
7821 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7823 *ppvObj = NULL;
7825 if(pOuterUnk)
7827 WARN("Not able to aggregate\n");
7828 return CLASS_E_NOAGGREGATION;
7831 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7832 if(FAILED(hr)) return hr;
7834 if(pTA->typekind != TKIND_COCLASS)
7836 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7837 hr = E_INVALIDARG;
7838 goto end;
7841 hr = S_FALSE;
7842 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7844 IUnknown *pUnk;
7845 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7846 TRACE("GetActiveObject rets %08x\n", hr);
7847 if(hr == S_OK)
7849 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7850 IUnknown_Release(pUnk);
7854 if(hr != S_OK)
7855 hr = CoCreateInstance(&pTA->guid, NULL,
7856 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7857 riid, ppvObj);
7859 end:
7860 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7861 return hr;
7864 /* ITypeInfo::GetMops
7866 * Retrieves marshalling information.
7868 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7869 BSTR *pBstrMops)
7871 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7872 FIXME("(%p %d) stub!\n", This, memid);
7873 *pBstrMops = NULL;
7874 return S_OK;
7877 /* ITypeInfo::GetContainingTypeLib
7879 * Retrieves the containing type library and the index of the type description
7880 * within that type library.
7882 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7883 ITypeLib * *ppTLib, UINT *pIndex)
7885 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7887 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7888 if (pIndex) {
7889 *pIndex=This->index;
7890 TRACE("returning pIndex=%d\n", *pIndex);
7893 if (ppTLib) {
7894 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7895 ITypeLib_AddRef(*ppTLib);
7896 TRACE("returning ppTLib=%p\n", *ppTLib);
7899 return S_OK;
7902 /* ITypeInfo::ReleaseTypeAttr
7904 * Releases a TYPEATTR previously returned by Get
7907 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7908 TYPEATTR* pTypeAttr)
7910 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7911 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7912 heap_free(pTypeAttr);
7915 /* ITypeInfo::ReleaseFuncDesc
7917 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7919 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7920 ITypeInfo2 *iface,
7921 FUNCDESC *pFuncDesc)
7923 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7924 SHORT i;
7926 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7928 for (i = 0; i < pFuncDesc->cParams; i++)
7929 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7930 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7932 SysFreeString((BSTR)pFuncDesc);
7935 /* ITypeInfo::ReleaseVarDesc
7937 * Releases a VARDESC previously returned by GetVarDesc.
7939 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7940 VARDESC *pVarDesc)
7942 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7943 TRACE("(%p)->(%p)\n", This, pVarDesc);
7945 TLB_FreeVarDesc(pVarDesc);
7948 /* ITypeInfo2::GetTypeKind
7950 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7953 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7954 TYPEKIND *pTypeKind)
7956 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7957 *pTypeKind=This->typekind;
7958 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7959 return S_OK;
7962 /* ITypeInfo2::GetTypeFlags
7964 * Returns the type flags without any allocations. This returns a DWORD type
7965 * flag, which expands the type flags without growing the TYPEATTR (type
7966 * attribute).
7969 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7971 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7972 *pTypeFlags=This->wTypeFlags;
7973 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7974 return S_OK;
7977 /* ITypeInfo2::GetFuncIndexOfMemId
7978 * Binds to a specific member based on a known DISPID, where the member name
7979 * is not known (for example, when binding to a default member).
7982 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7983 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7985 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7986 UINT fdc;
7987 HRESULT result;
7989 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7990 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7991 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7992 break;
7994 if(fdc < This->cFuncs) {
7995 *pFuncIndex = fdc;
7996 result = S_OK;
7997 } else
7998 result = TYPE_E_ELEMENTNOTFOUND;
8000 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8001 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8002 return result;
8005 /* TypeInfo2::GetVarIndexOfMemId
8007 * Binds to a specific member based on a known DISPID, where the member name
8008 * is not known (for example, when binding to a default member).
8011 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8012 MEMBERID memid, UINT *pVarIndex)
8014 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8015 TLBVarDesc *pVarInfo;
8017 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8019 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8020 if(!pVarInfo)
8021 return TYPE_E_ELEMENTNOTFOUND;
8023 *pVarIndex = (pVarInfo - This->vardescs);
8025 return S_OK;
8028 /* ITypeInfo2::GetCustData
8030 * Gets the custom data
8032 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8033 ITypeInfo2 * iface,
8034 REFGUID guid,
8035 VARIANT *pVarVal)
8037 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8038 TLBCustData *pCData;
8040 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8042 if(!guid || !pVarVal)
8043 return E_INVALIDARG;
8045 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8047 VariantInit( pVarVal);
8048 if (pCData)
8049 VariantCopy( pVarVal, &pCData->data);
8050 else
8051 VariantClear( pVarVal );
8052 return S_OK;
8055 /* ITypeInfo2::GetFuncCustData
8057 * Gets the custom data
8059 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8060 ITypeInfo2 * iface,
8061 UINT index,
8062 REFGUID guid,
8063 VARIANT *pVarVal)
8065 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8066 TLBCustData *pCData;
8067 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8069 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8071 if(index >= This->cFuncs)
8072 return TYPE_E_ELEMENTNOTFOUND;
8074 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8075 if(!pCData)
8076 return TYPE_E_ELEMENTNOTFOUND;
8078 VariantInit(pVarVal);
8079 VariantCopy(pVarVal, &pCData->data);
8081 return S_OK;
8084 /* ITypeInfo2::GetParamCustData
8086 * Gets the custom data
8088 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8089 ITypeInfo2 * iface,
8090 UINT indexFunc,
8091 UINT indexParam,
8092 REFGUID guid,
8093 VARIANT *pVarVal)
8095 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8096 TLBCustData *pCData;
8097 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8099 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8100 debugstr_guid(guid), pVarVal);
8102 if(indexFunc >= This->cFuncs)
8103 return TYPE_E_ELEMENTNOTFOUND;
8105 if(indexParam >= pFDesc->funcdesc.cParams)
8106 return TYPE_E_ELEMENTNOTFOUND;
8108 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8109 if(!pCData)
8110 return TYPE_E_ELEMENTNOTFOUND;
8112 VariantInit(pVarVal);
8113 VariantCopy(pVarVal, &pCData->data);
8115 return S_OK;
8118 /* ITypeInfo2::GetVarCustData
8120 * Gets the custom data
8122 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8123 ITypeInfo2 * iface,
8124 UINT index,
8125 REFGUID guid,
8126 VARIANT *pVarVal)
8128 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8129 TLBCustData *pCData;
8130 TLBVarDesc *pVDesc = &This->vardescs[index];
8132 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8134 if(index >= This->cVars)
8135 return TYPE_E_ELEMENTNOTFOUND;
8137 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8138 if(!pCData)
8139 return TYPE_E_ELEMENTNOTFOUND;
8141 VariantInit(pVarVal);
8142 VariantCopy(pVarVal, &pCData->data);
8144 return S_OK;
8147 /* ITypeInfo2::GetImplCustData
8149 * Gets the custom data
8151 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8152 ITypeInfo2 * iface,
8153 UINT index,
8154 REFGUID guid,
8155 VARIANT *pVarVal)
8157 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8158 TLBCustData *pCData;
8159 TLBImplType *pRDesc = &This->impltypes[index];
8161 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8163 if(index >= This->cImplTypes)
8164 return TYPE_E_ELEMENTNOTFOUND;
8166 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8167 if(!pCData)
8168 return TYPE_E_ELEMENTNOTFOUND;
8170 VariantInit(pVarVal);
8171 VariantCopy(pVarVal, &pCData->data);
8173 return S_OK;
8176 /* ITypeInfo2::GetDocumentation2
8178 * Retrieves the documentation string, the complete Help file name and path,
8179 * the localization context to use, and the context ID for the library Help
8180 * topic in the Help file.
8183 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8184 ITypeInfo2 * iface,
8185 MEMBERID memid,
8186 LCID lcid,
8187 BSTR *pbstrHelpString,
8188 DWORD *pdwHelpStringContext,
8189 BSTR *pbstrHelpStringDll)
8191 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8192 const TLBFuncDesc *pFDesc;
8193 const TLBVarDesc *pVDesc;
8194 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8195 "HelpStringContext(%p) HelpStringDll(%p)\n",
8196 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8197 pbstrHelpStringDll );
8198 /* the help string should be obtained from the helpstringdll,
8199 * using the _DLLGetDocumentation function, based on the supplied
8200 * lcid. Nice to do sometime...
8202 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8203 if(pbstrHelpString)
8204 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8205 if(pdwHelpStringContext)
8206 *pdwHelpStringContext=This->dwHelpStringContext;
8207 if(pbstrHelpStringDll)
8208 *pbstrHelpStringDll=
8209 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8210 return S_OK;
8211 }else {/* for a member */
8212 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
8213 if(pFDesc){
8214 if(pbstrHelpString)
8215 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8216 if(pdwHelpStringContext)
8217 *pdwHelpStringContext=pFDesc->HelpStringContext;
8218 if(pbstrHelpStringDll)
8219 *pbstrHelpStringDll=
8220 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8221 return S_OK;
8223 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8224 if(pVDesc){
8225 if(pbstrHelpString)
8226 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8227 if(pdwHelpStringContext)
8228 *pdwHelpStringContext=pVDesc->HelpStringContext;
8229 if(pbstrHelpStringDll)
8230 *pbstrHelpStringDll=
8231 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8232 return S_OK;
8235 return TYPE_E_ELEMENTNOTFOUND;
8238 /* ITypeInfo2::GetAllCustData
8240 * Gets all custom data items for the Type info.
8243 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8244 ITypeInfo2 * iface,
8245 CUSTDATA *pCustData)
8247 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8249 TRACE("%p %p\n", This, pCustData);
8251 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8254 /* ITypeInfo2::GetAllFuncCustData
8256 * Gets all custom data items for the specified Function
8259 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8260 ITypeInfo2 * iface,
8261 UINT index,
8262 CUSTDATA *pCustData)
8264 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8265 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8267 TRACE("%p %u %p\n", This, index, pCustData);
8269 if(index >= This->cFuncs)
8270 return TYPE_E_ELEMENTNOTFOUND;
8272 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8275 /* ITypeInfo2::GetAllParamCustData
8277 * Gets all custom data items for the Functions
8280 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8281 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8283 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8284 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8286 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8288 if(indexFunc >= This->cFuncs)
8289 return TYPE_E_ELEMENTNOTFOUND;
8291 if(indexParam >= pFDesc->funcdesc.cParams)
8292 return TYPE_E_ELEMENTNOTFOUND;
8294 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8297 /* ITypeInfo2::GetAllVarCustData
8299 * Gets all custom data items for the specified Variable
8302 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8303 UINT index, CUSTDATA *pCustData)
8305 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8306 TLBVarDesc * pVDesc = &This->vardescs[index];
8308 TRACE("%p %u %p\n", This, index, pCustData);
8310 if(index >= This->cVars)
8311 return TYPE_E_ELEMENTNOTFOUND;
8313 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8316 /* ITypeInfo2::GetAllImplCustData
8318 * Gets all custom data items for the specified implementation type
8321 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8322 ITypeInfo2 * iface,
8323 UINT index,
8324 CUSTDATA *pCustData)
8326 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8327 TLBImplType *pRDesc = &This->impltypes[index];
8329 TRACE("%p %u %p\n", This, index, pCustData);
8331 if(index >= This->cImplTypes)
8332 return TYPE_E_ELEMENTNOTFOUND;
8334 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8337 static const ITypeInfo2Vtbl tinfvt =
8340 ITypeInfo_fnQueryInterface,
8341 ITypeInfo_fnAddRef,
8342 ITypeInfo_fnRelease,
8344 ITypeInfo_fnGetTypeAttr,
8345 ITypeInfo_fnGetTypeComp,
8346 ITypeInfo_fnGetFuncDesc,
8347 ITypeInfo_fnGetVarDesc,
8348 ITypeInfo_fnGetNames,
8349 ITypeInfo_fnGetRefTypeOfImplType,
8350 ITypeInfo_fnGetImplTypeFlags,
8351 ITypeInfo_fnGetIDsOfNames,
8352 ITypeInfo_fnInvoke,
8353 ITypeInfo_fnGetDocumentation,
8354 ITypeInfo_fnGetDllEntry,
8355 ITypeInfo_fnGetRefTypeInfo,
8356 ITypeInfo_fnAddressOfMember,
8357 ITypeInfo_fnCreateInstance,
8358 ITypeInfo_fnGetMops,
8359 ITypeInfo_fnGetContainingTypeLib,
8360 ITypeInfo_fnReleaseTypeAttr,
8361 ITypeInfo_fnReleaseFuncDesc,
8362 ITypeInfo_fnReleaseVarDesc,
8364 ITypeInfo2_fnGetTypeKind,
8365 ITypeInfo2_fnGetTypeFlags,
8366 ITypeInfo2_fnGetFuncIndexOfMemId,
8367 ITypeInfo2_fnGetVarIndexOfMemId,
8368 ITypeInfo2_fnGetCustData,
8369 ITypeInfo2_fnGetFuncCustData,
8370 ITypeInfo2_fnGetParamCustData,
8371 ITypeInfo2_fnGetVarCustData,
8372 ITypeInfo2_fnGetImplTypeCustData,
8373 ITypeInfo2_fnGetDocumentation2,
8374 ITypeInfo2_fnGetAllCustData,
8375 ITypeInfo2_fnGetAllFuncCustData,
8376 ITypeInfo2_fnGetAllParamCustData,
8377 ITypeInfo2_fnGetAllVarCustData,
8378 ITypeInfo2_fnGetAllImplTypeCustData,
8381 /******************************************************************************
8382 * CreateDispTypeInfo [OLEAUT32.31]
8384 * Build type information for an object so it can be called through an
8385 * IDispatch interface.
8387 * RETURNS
8388 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8389 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8391 * NOTES
8392 * This call allows an objects methods to be accessed through IDispatch, by
8393 * building an ITypeInfo object that IDispatch can use to call through.
8395 HRESULT WINAPI CreateDispTypeInfo(
8396 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8397 LCID lcid, /* [I] Locale Id */
8398 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8400 ITypeInfoImpl *pTIClass, *pTIIface;
8401 ITypeLibImpl *pTypeLibImpl;
8402 unsigned int param, func;
8403 TLBFuncDesc *pFuncDesc;
8404 TLBRefType *ref;
8406 TRACE("\n");
8407 pTypeLibImpl = TypeLibImpl_Constructor();
8408 if (!pTypeLibImpl) return E_FAIL;
8410 pTypeLibImpl->TypeInfoCount = 2;
8411 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8413 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8414 pTIIface->pTypeLib = pTypeLibImpl;
8415 pTIIface->index = 0;
8416 pTIIface->Name = NULL;
8417 pTIIface->dwHelpContext = -1;
8418 pTIIface->guid = NULL;
8419 pTIIface->lcid = lcid;
8420 pTIIface->typekind = TKIND_INTERFACE;
8421 pTIIface->wMajorVerNum = 0;
8422 pTIIface->wMinorVerNum = 0;
8423 pTIIface->cbAlignment = 2;
8424 pTIIface->cbSizeInstance = -1;
8425 pTIIface->cbSizeVft = -1;
8426 pTIIface->cFuncs = 0;
8427 pTIIface->cImplTypes = 0;
8428 pTIIface->cVars = 0;
8429 pTIIface->wTypeFlags = 0;
8430 pTIIface->hreftype = 0;
8432 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8433 pFuncDesc = pTIIface->funcdescs;
8434 for(func = 0; func < pidata->cMembers; func++) {
8435 METHODDATA *md = pidata->pmethdata + func;
8436 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8437 pFuncDesc->funcdesc.memid = md->dispid;
8438 pFuncDesc->funcdesc.lprgscode = NULL;
8439 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8440 pFuncDesc->funcdesc.invkind = md->wFlags;
8441 pFuncDesc->funcdesc.callconv = md->cc;
8442 pFuncDesc->funcdesc.cParams = md->cArgs;
8443 pFuncDesc->funcdesc.cParamsOpt = 0;
8444 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8445 pFuncDesc->funcdesc.cScodes = 0;
8446 pFuncDesc->funcdesc.wFuncFlags = 0;
8447 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8448 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8449 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8450 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8451 md->cArgs * sizeof(ELEMDESC));
8452 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8453 for(param = 0; param < md->cArgs; param++) {
8454 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8455 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8457 pFuncDesc->helpcontext = 0;
8458 pFuncDesc->HelpStringContext = 0;
8459 pFuncDesc->HelpString = NULL;
8460 pFuncDesc->Entry = NULL;
8461 list_init(&pFuncDesc->custdata_list);
8462 pTIIface->cFuncs++;
8463 ++pFuncDesc;
8466 dump_TypeInfo(pTIIface);
8468 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8469 pTIClass->pTypeLib = pTypeLibImpl;
8470 pTIClass->index = 1;
8471 pTIClass->Name = NULL;
8472 pTIClass->dwHelpContext = -1;
8473 pTIClass->guid = NULL;
8474 pTIClass->lcid = lcid;
8475 pTIClass->typekind = TKIND_COCLASS;
8476 pTIClass->wMajorVerNum = 0;
8477 pTIClass->wMinorVerNum = 0;
8478 pTIClass->cbAlignment = 2;
8479 pTIClass->cbSizeInstance = -1;
8480 pTIClass->cbSizeVft = -1;
8481 pTIClass->cFuncs = 0;
8482 pTIClass->cImplTypes = 1;
8483 pTIClass->cVars = 0;
8484 pTIClass->wTypeFlags = 0;
8485 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8487 pTIClass->impltypes = TLBImplType_Alloc(1);
8489 ref = heap_alloc_zero(sizeof(*ref));
8490 ref->pImpTLInfo = TLB_REF_INTERNAL;
8491 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8493 dump_TypeInfo(pTIClass);
8495 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8497 ITypeInfo_AddRef(*pptinfo);
8498 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8500 return S_OK;
8504 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8506 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8508 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8511 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8513 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8515 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8518 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8520 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8522 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8525 static HRESULT WINAPI ITypeComp_fnBind(
8526 ITypeComp * iface,
8527 OLECHAR * szName,
8528 ULONG lHash,
8529 WORD wFlags,
8530 ITypeInfo ** ppTInfo,
8531 DESCKIND * pDescKind,
8532 BINDPTR * pBindPtr)
8534 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8535 const TLBFuncDesc *pFDesc;
8536 const TLBVarDesc *pVDesc;
8537 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8538 UINT fdc;
8540 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8542 *pDescKind = DESCKIND_NONE;
8543 pBindPtr->lpfuncdesc = NULL;
8544 *ppTInfo = NULL;
8546 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8547 pFDesc = &This->funcdescs[fdc];
8548 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8549 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8550 break;
8551 else
8552 /* name found, but wrong flags */
8553 hr = TYPE_E_TYPEMISMATCH;
8557 if (fdc < This->cFuncs)
8559 HRESULT hr = TLB_AllocAndInitFuncDesc(
8560 &pFDesc->funcdesc,
8561 &pBindPtr->lpfuncdesc,
8562 This->typekind == TKIND_DISPATCH);
8563 if (FAILED(hr))
8564 return hr;
8565 *pDescKind = DESCKIND_FUNCDESC;
8566 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8567 ITypeInfo_AddRef(*ppTInfo);
8568 return S_OK;
8569 } else {
8570 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8571 if(pVDesc){
8572 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8573 if (FAILED(hr))
8574 return hr;
8575 *pDescKind = DESCKIND_VARDESC;
8576 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8577 ITypeInfo_AddRef(*ppTInfo);
8578 return S_OK;
8582 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8583 /* recursive search */
8584 ITypeInfo *pTInfo;
8585 ITypeComp *pTComp;
8586 HRESULT hr;
8587 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8588 if (SUCCEEDED(hr))
8590 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8591 ITypeInfo_Release(pTInfo);
8593 if (SUCCEEDED(hr))
8595 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8596 ITypeComp_Release(pTComp);
8597 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8598 This->typekind == TKIND_DISPATCH)
8600 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8601 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8602 SysFreeString((BSTR)tmp);
8604 return hr;
8606 WARN("Could not search inherited interface!\n");
8608 if (hr == DISP_E_MEMBERNOTFOUND)
8609 hr = S_OK;
8610 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8611 return hr;
8614 static HRESULT WINAPI ITypeComp_fnBindType(
8615 ITypeComp * iface,
8616 OLECHAR * szName,
8617 ULONG lHash,
8618 ITypeInfo ** ppTInfo,
8619 ITypeComp ** ppTComp)
8621 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8623 /* strange behaviour (does nothing) but like the
8624 * original */
8626 if (!ppTInfo || !ppTComp)
8627 return E_POINTER;
8629 *ppTInfo = NULL;
8630 *ppTComp = NULL;
8632 return S_OK;
8635 static const ITypeCompVtbl tcompvt =
8638 ITypeComp_fnQueryInterface,
8639 ITypeComp_fnAddRef,
8640 ITypeComp_fnRelease,
8642 ITypeComp_fnBind,
8643 ITypeComp_fnBindType
8646 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8647 ICreateTypeLib2** ppctlib)
8649 ITypeLibImpl *This;
8650 HRESULT hres;
8652 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8654 if (!szFile) return E_INVALIDARG;
8656 This = TypeLibImpl_Constructor();
8657 if (!This)
8658 return E_OUTOFMEMORY;
8660 This->lcid = GetSystemDefaultLCID();
8661 This->syskind = syskind;
8662 This->ptr_size = get_ptr_size(syskind);
8664 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8665 if (!This->path) {
8666 ITypeLib2_Release(&This->ITypeLib2_iface);
8667 return E_OUTOFMEMORY;
8669 lstrcpyW(This->path, szFile);
8671 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8672 ITypeLib2_Release(&This->ITypeLib2_iface);
8673 return hres;
8676 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8677 REFIID riid, void **object)
8679 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8681 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8684 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8686 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8688 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8691 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8693 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8695 return ITypeLib2_Release(&This->ITypeLib2_iface);
8698 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8699 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8701 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8702 ITypeInfoImpl *info;
8703 HRESULT hres;
8705 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8707 if (!ctinfo || !name)
8708 return E_INVALIDARG;
8710 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8711 if (info)
8712 return TYPE_E_NAMECONFLICT;
8714 if (This->typeinfos)
8715 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8716 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8717 else
8718 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8720 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8722 info->pTypeLib = This;
8723 info->Name = TLB_append_str(&This->name_list, name);
8724 info->index = This->TypeInfoCount;
8725 info->typekind = kind;
8726 info->cbAlignment = 4;
8728 switch(info->typekind) {
8729 case TKIND_ENUM:
8730 case TKIND_INTERFACE:
8731 case TKIND_DISPATCH:
8732 case TKIND_COCLASS:
8733 info->cbSizeInstance = This->ptr_size;
8734 break;
8735 case TKIND_RECORD:
8736 case TKIND_UNION:
8737 info->cbSizeInstance = 0;
8738 break;
8739 case TKIND_MODULE:
8740 info->cbSizeInstance = 2;
8741 break;
8742 case TKIND_ALIAS:
8743 info->cbSizeInstance = -0x75;
8744 break;
8745 default:
8746 FIXME("unrecognized typekind %d\n", info->typekind);
8747 info->cbSizeInstance = 0xdeadbeef;
8748 break;
8751 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8752 &IID_ICreateTypeInfo, (void **)ctinfo);
8753 if (FAILED(hres)) {
8754 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8755 return hres;
8758 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8760 ++This->TypeInfoCount;
8762 return S_OK;
8765 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8766 LPOLESTR name)
8768 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8770 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8772 if (!name)
8773 return E_INVALIDARG;
8775 This->Name = TLB_append_str(&This->name_list, name);
8777 return S_OK;
8780 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8781 WORD majorVerNum, WORD minorVerNum)
8783 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8785 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8787 This->ver_major = majorVerNum;
8788 This->ver_minor = minorVerNum;
8790 return S_OK;
8793 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8794 REFGUID guid)
8796 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8798 TRACE("%p %s\n", This, debugstr_guid(guid));
8800 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8802 return S_OK;
8805 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8806 LPOLESTR doc)
8808 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8810 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8812 if (!doc)
8813 return E_INVALIDARG;
8815 This->DocString = TLB_append_str(&This->string_list, doc);
8817 return S_OK;
8820 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8821 LPOLESTR helpFileName)
8823 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8825 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8827 if (!helpFileName)
8828 return E_INVALIDARG;
8830 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8832 return S_OK;
8835 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8836 DWORD helpContext)
8838 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8840 TRACE("%p %d\n", This, helpContext);
8842 This->dwHelpContext = helpContext;
8844 return S_OK;
8847 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8848 LCID lcid)
8850 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8852 TRACE("%p %x\n", This, lcid);
8854 This->set_lcid = lcid;
8856 return S_OK;
8859 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8860 UINT libFlags)
8862 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8864 TRACE("%p %x\n", This, libFlags);
8866 This->libflags = libFlags;
8868 return S_OK;
8871 typedef struct tagWMSFT_SegContents {
8872 DWORD len;
8873 void *data;
8874 } WMSFT_SegContents;
8876 typedef struct tagWMSFT_TLBFile {
8877 MSFT_Header header;
8878 WMSFT_SegContents typeinfo_seg;
8879 WMSFT_SegContents impfile_seg;
8880 WMSFT_SegContents impinfo_seg;
8881 WMSFT_SegContents ref_seg;
8882 WMSFT_SegContents guidhash_seg;
8883 WMSFT_SegContents guid_seg;
8884 WMSFT_SegContents namehash_seg;
8885 WMSFT_SegContents name_seg;
8886 WMSFT_SegContents string_seg;
8887 WMSFT_SegContents typdesc_seg;
8888 WMSFT_SegContents arraydesc_seg;
8889 WMSFT_SegContents custdata_seg;
8890 WMSFT_SegContents cdguids_seg;
8891 MSFT_SegDir segdir;
8892 WMSFT_SegContents aux_seg;
8893 } WMSFT_TLBFile;
8895 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8896 WMSFT_TLBFile *file)
8898 TLBString *str;
8899 UINT last_offs;
8900 char *data;
8902 file->string_seg.len = 0;
8903 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8904 int size;
8906 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8907 if (size == 0)
8908 return E_UNEXPECTED;
8910 size += sizeof(INT16);
8911 if (size % 4)
8912 size = (size + 4) & ~0x3;
8913 if (size < 8)
8914 size = 8;
8916 file->string_seg.len += size;
8918 /* temporarily use str->offset to store the length of the aligned,
8919 * converted string */
8920 str->offset = size;
8923 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8925 last_offs = 0;
8926 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8927 int size;
8929 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8930 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8931 if (size == 0) {
8932 heap_free(file->string_seg.data);
8933 return E_UNEXPECTED;
8936 *((INT16*)data) = size;
8938 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8940 size = str->offset;
8941 data += size;
8942 str->offset = last_offs;
8943 last_offs += size;
8946 return S_OK;
8949 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8950 WMSFT_TLBFile *file)
8952 TLBString *str;
8953 UINT last_offs;
8954 char *data;
8955 MSFT_NameIntro *last_intro = NULL;
8957 file->header.nametablecount = 0;
8958 file->header.nametablechars = 0;
8960 file->name_seg.len = 0;
8961 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8962 int size;
8964 size = strlenW(str->str);
8965 file->header.nametablechars += size;
8966 file->header.nametablecount++;
8968 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8969 if (size == 0)
8970 return E_UNEXPECTED;
8972 size += sizeof(MSFT_NameIntro);
8973 if (size % 4)
8974 size = (size + 4) & ~0x3;
8975 if (size < 8)
8976 size = 8;
8978 file->name_seg.len += size;
8980 /* temporarily use str->offset to store the length of the aligned,
8981 * converted string */
8982 str->offset = size;
8985 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8986 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8988 last_offs = 0;
8989 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8990 int size, hash;
8991 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8993 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8994 data + sizeof(MSFT_NameIntro),
8995 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8996 if (size == 0) {
8997 heap_free(file->name_seg.data);
8998 return E_UNEXPECTED;
9000 data[sizeof(MSFT_NameIntro) + size] = '\0';
9002 intro->hreftype = -1; /* TODO? */
9003 intro->namelen = size & 0xFF;
9004 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9005 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9006 intro->namelen |= hash << 16;
9007 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9008 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9010 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9011 str->offset - size - sizeof(MSFT_NameIntro));
9013 /* update str->offset to actual value to use in other
9014 * compilation functions that require positions within
9015 * the string table */
9016 last_intro = intro;
9017 size = str->offset;
9018 data += size;
9019 str->offset = last_offs;
9020 last_offs += size;
9023 if(last_intro)
9024 last_intro->hreftype = 0; /* last one is 0? */
9026 return S_OK;
9029 static inline int hash_guid(GUID *guid)
9031 int i, hash = 0;
9033 for (i = 0; i < 8; i ++)
9034 hash ^= ((const short *)guid)[i];
9036 return hash & 0x1f;
9039 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9041 TLBGuid *guid;
9042 MSFT_GuidEntry *entry;
9043 DWORD offs;
9044 int hash_key, *guidhashtab;
9046 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9047 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9049 entry = file->guid_seg.data;
9050 offs = 0;
9051 guidhashtab = file->guidhash_seg.data;
9052 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9053 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9054 entry->hreftype = guid->hreftype;
9056 hash_key = hash_guid(&guid->guid);
9057 entry->next_hash = guidhashtab[hash_key];
9058 guidhashtab[hash_key] = offs;
9060 guid->offset = offs;
9061 offs += sizeof(MSFT_GuidEntry);
9062 ++entry;
9065 return S_OK;
9068 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9070 VARIANT v = *value;
9071 VARTYPE arg_type = V_VT(value);
9072 int mask = 0;
9073 HRESULT hres;
9074 DWORD ret = file->custdata_seg.len;
9076 if(arg_type == VT_INT)
9077 arg_type = VT_I4;
9078 if(arg_type == VT_UINT)
9079 arg_type = VT_UI4;
9081 v = *value;
9082 if(V_VT(value) != arg_type) {
9083 hres = VariantChangeType(&v, value, 0, arg_type);
9084 if(FAILED(hres)){
9085 ERR("VariantChangeType failed: %08x\n", hres);
9086 return -1;
9090 /* Check if default value can be stored in-place */
9091 switch(arg_type){
9092 case VT_I4:
9093 case VT_UI4:
9094 mask = 0x3ffffff;
9095 if(V_UI4(&v) > 0x3ffffff)
9096 break;
9097 /* fall through */
9098 case VT_I1:
9099 case VT_UI1:
9100 case VT_BOOL:
9101 if(!mask)
9102 mask = 0xff;
9103 /* fall through */
9104 case VT_I2:
9105 case VT_UI2:
9106 if(!mask)
9107 mask = 0xffff;
9108 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9111 /* have to allocate space in custdata_seg */
9112 switch(arg_type) {
9113 case VT_I4:
9114 case VT_R4:
9115 case VT_UI4:
9116 case VT_INT:
9117 case VT_UINT:
9118 case VT_HRESULT:
9119 case VT_PTR: {
9120 /* Construct the data to be allocated */
9121 int *data;
9123 if(file->custdata_seg.data){
9124 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9125 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9126 file->custdata_seg.len += sizeof(int) * 2;
9127 }else{
9128 file->custdata_seg.len = sizeof(int) * 2;
9129 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9132 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9133 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9135 /* TODO: Check if the encoded data is already present in custdata_seg */
9137 return ret;
9140 case VT_BSTR: {
9141 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9142 char *data;
9144 if(file->custdata_seg.data){
9145 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9146 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9147 file->custdata_seg.len += len;
9148 }else{
9149 file->custdata_seg.len = len;
9150 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9153 *((unsigned short *)data) = V_VT(value);
9154 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9155 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9156 if(V_BSTR(&v)[i] <= 0x7f)
9157 data[i+6] = V_BSTR(&v)[i];
9158 else
9159 data[i+6] = '?';
9161 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9162 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9163 data[i] = 0x57;
9165 /* TODO: Check if the encoded data is already present in custdata_seg */
9167 return ret;
9169 default:
9170 FIXME("Argument type not yet handled\n");
9171 return -1;
9175 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9177 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9179 DWORD offs = file->arraydesc_seg.len;
9180 DWORD *encoded;
9181 USHORT i;
9183 /* TODO: we should check for duplicates, but that's harder because each
9184 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9185 * at the library-level) */
9187 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9188 if(!file->arraydesc_seg.data)
9189 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9190 else
9191 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9192 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
9194 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9195 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9196 for(i = 0; i < desc->cDims; ++i){
9197 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9198 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9201 return offs;
9204 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9206 DWORD junk;
9207 INT16 junk2;
9208 DWORD offs = 0;
9209 DWORD encoded[2];
9210 VARTYPE vt, subtype;
9211 char *data;
9213 if(!desc)
9214 return -1;
9216 if(!out_mix)
9217 out_mix = &junk;
9218 if(!out_size)
9219 out_size = &junk2;
9221 vt = desc->vt & VT_TYPEMASK;
9223 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9224 DWORD mix;
9225 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9226 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9227 *out_mix = 0x7FFF;
9228 *out_size += 2 * sizeof(DWORD);
9229 }else if(vt == VT_CARRAY){
9230 encoded[0] = desc->vt | (0x7FFE << 16);
9231 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9232 *out_mix = 0x7FFE;
9233 }else if(vt == VT_USERDEFINED){
9234 encoded[0] = desc->vt | (0x7FFF << 16);
9235 encoded[1] = desc->u.hreftype;
9236 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9237 }else{
9238 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9240 switch(vt){
9241 case VT_INT:
9242 subtype = VT_I4;
9243 break;
9244 case VT_UINT:
9245 subtype = VT_UI4;
9246 break;
9247 case VT_VOID:
9248 subtype = VT_EMPTY;
9249 break;
9250 default:
9251 subtype = vt;
9252 break;
9255 *out_mix = subtype;
9256 return 0x80000000 | (subtype << 16) | desc->vt;
9259 data = file->typdesc_seg.data;
9260 while(offs < file->typdesc_seg.len){
9261 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9262 return offs;
9263 offs += sizeof(encoded);
9266 file->typdesc_seg.len += sizeof(encoded);
9267 if(!file->typdesc_seg.data)
9268 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9269 else
9270 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9272 memcpy(&data[offs], encoded, sizeof(encoded));
9274 return offs;
9277 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9279 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9280 DWORD ret = cdguids_seg->len, offs;
9281 MSFT_CDGuid *cdguid = cdguids_seg->data;
9282 TLBCustData *cd;
9284 if(list_empty(custdata_list))
9285 return -1;
9287 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9288 if(!cdguids_seg->data){
9289 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9290 }else
9291 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9293 offs = ret + sizeof(MSFT_CDGuid);
9294 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9295 cdguid->GuidOffset = cd->guid->offset;
9296 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9297 cdguid->next = offs;
9298 offs += sizeof(MSFT_CDGuid);
9299 ++cdguid;
9302 --cdguid;
9303 cdguid->next = -1;
9305 return ret;
9308 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9309 WMSFT_TLBFile *file)
9311 WMSFT_SegContents *aux_seg = &file->aux_seg;
9312 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9313 MSFT_VarRecord *varrecord;
9314 MSFT_FuncRecord *funcrecord;
9315 MEMBERID *memid;
9316 DWORD *name, *offsets, offs;
9318 for(i = 0; i < info->cFuncs; ++i){
9319 TLBFuncDesc *desc = &info->funcdescs[i];
9321 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9323 /* optional fields */
9324 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9325 if(!list_empty(&desc->custdata_list))
9326 recorded_size += 7 * sizeof(INT);
9327 else if(desc->HelpStringContext != 0)
9328 recorded_size += 6 * sizeof(INT);
9329 /* res9? resA? */
9330 else if(desc->Entry)
9331 recorded_size += 3 * sizeof(INT);
9332 else if(desc->HelpString)
9333 recorded_size += 2 * sizeof(INT);
9334 else if(desc->helpcontext)
9335 recorded_size += sizeof(INT);
9337 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9339 for(j = 0; j < desc->funcdesc.cParams; ++j){
9340 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9341 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9342 break;
9346 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9349 for(i = 0; i < info->cVars; ++i){
9350 TLBVarDesc *desc = &info->vardescs[i];
9352 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9354 /* optional fields */
9355 if(desc->HelpStringContext != 0)
9356 recorded_size += 5 * sizeof(INT);
9357 else if(!list_empty(&desc->custdata_list))
9358 recorded_size += 4 * sizeof(INT);
9359 /* res9? */
9360 else if(desc->HelpString)
9361 recorded_size += 2 * sizeof(INT);
9362 else if(desc->HelpContext != 0)
9363 recorded_size += sizeof(INT);
9365 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9368 if(!recorded_size && !extra_size)
9369 return ret;
9371 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9373 aux_seg->len += recorded_size + extra_size;
9375 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9377 if(aux_seg->data)
9378 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9379 else
9380 aux_seg->data = heap_alloc(aux_seg->len);
9382 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9384 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9385 offs = 0;
9387 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9388 for(i = 0; i < info->cFuncs; ++i){
9389 TLBFuncDesc *desc = &info->funcdescs[i];
9390 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9392 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9393 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9394 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9395 funcrecord->VtableOffset = desc->funcdesc.oVft;
9397 /* FKCCIC:
9398 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9399 * ^^^funckind
9400 * ^^^ ^invkind
9401 * ^has_cust_data
9402 * ^^^^callconv
9403 * ^has_param_defaults
9404 * ^oEntry_is_intresource
9406 funcrecord->FKCCIC =
9407 desc->funcdesc.funckind |
9408 (desc->funcdesc.invkind << 3) |
9409 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9410 (desc->funcdesc.callconv << 8);
9412 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9413 funcrecord->FKCCIC |= 0x2000;
9415 for(j = 0; j < desc->funcdesc.cParams; ++j){
9416 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9417 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9418 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9421 if(paramdefault_size > 0)
9422 funcrecord->FKCCIC |= 0x1000;
9424 funcrecord->nrargs = desc->funcdesc.cParams;
9425 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9427 /* optional fields */
9428 /* res9? resA? */
9429 if(!list_empty(&desc->custdata_list)){
9430 size += 7 * sizeof(INT);
9431 funcrecord->HelpContext = desc->helpcontext;
9432 if(desc->HelpString)
9433 funcrecord->oHelpString = desc->HelpString->offset;
9434 else
9435 funcrecord->oHelpString = -1;
9436 if(!desc->Entry)
9437 funcrecord->oEntry = -1;
9438 else if(IS_INTRESOURCE(desc->Entry))
9439 funcrecord->oEntry = LOWORD(desc->Entry);
9440 else
9441 funcrecord->oEntry = desc->Entry->offset;
9442 funcrecord->res9 = -1;
9443 funcrecord->resA = -1;
9444 funcrecord->HelpStringContext = desc->HelpStringContext;
9445 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9446 }else if(desc->HelpStringContext != 0){
9447 size += 6 * sizeof(INT);
9448 funcrecord->HelpContext = desc->helpcontext;
9449 if(desc->HelpString)
9450 funcrecord->oHelpString = desc->HelpString->offset;
9451 else
9452 funcrecord->oHelpString = -1;
9453 if(!desc->Entry)
9454 funcrecord->oEntry = -1;
9455 else if(IS_INTRESOURCE(desc->Entry))
9456 funcrecord->oEntry = LOWORD(desc->Entry);
9457 else
9458 funcrecord->oEntry = desc->Entry->offset;
9459 funcrecord->res9 = -1;
9460 funcrecord->resA = -1;
9461 funcrecord->HelpStringContext = desc->HelpStringContext;
9462 }else if(desc->Entry){
9463 size += 3 * sizeof(INT);
9464 funcrecord->HelpContext = desc->helpcontext;
9465 if(desc->HelpString)
9466 funcrecord->oHelpString = desc->HelpString->offset;
9467 else
9468 funcrecord->oHelpString = -1;
9469 if(!desc->Entry)
9470 funcrecord->oEntry = -1;
9471 else if(IS_INTRESOURCE(desc->Entry))
9472 funcrecord->oEntry = LOWORD(desc->Entry);
9473 else
9474 funcrecord->oEntry = desc->Entry->offset;
9475 }else if(desc->HelpString){
9476 size += 2 * sizeof(INT);
9477 funcrecord->HelpContext = desc->helpcontext;
9478 funcrecord->oHelpString = desc->HelpString->offset;
9479 }else if(desc->helpcontext){
9480 size += sizeof(INT);
9481 funcrecord->HelpContext = desc->helpcontext;
9484 paramdefault = (DWORD*)((char *)funcrecord + size);
9485 size += paramdefault_size;
9487 for(j = 0; j < desc->funcdesc.cParams; ++j){
9488 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9490 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9491 if(desc->pParamDesc[j].Name)
9492 info->oName = desc->pParamDesc[j].Name->offset;
9493 else
9494 info->oName = -1;
9495 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9497 if(paramdefault_size){
9498 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9499 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9500 else if(paramdefault_size)
9501 *paramdefault = -1;
9502 ++paramdefault;
9505 size += sizeof(MSFT_ParameterInfo);
9508 funcrecord->Info = size | (i << 16); /* is it just the index? */
9510 *offsets = offs;
9511 offs += size;
9512 ++offsets;
9514 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9517 varrecord = (MSFT_VarRecord*)funcrecord;
9518 for(i = 0; i < info->cVars; ++i){
9519 TLBVarDesc *desc = &info->vardescs[i];
9520 DWORD size = 5 * sizeof(INT);
9522 varrecord->vardescsize = sizeof(desc->vardesc);
9523 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9524 varrecord->Flags = desc->vardesc.wVarFlags;
9525 varrecord->VarKind = desc->vardesc.varkind;
9527 if(desc->vardesc.varkind == VAR_CONST){
9528 varrecord->vardescsize += sizeof(VARIANT);
9529 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9530 }else
9531 varrecord->OffsValue = desc->vardesc.u.oInst;
9533 /* res9? */
9534 if(desc->HelpStringContext != 0){
9535 size += 5 * sizeof(INT);
9536 varrecord->HelpContext = desc->HelpContext;
9537 if(desc->HelpString)
9538 varrecord->HelpString = desc->HelpString->offset;
9539 else
9540 varrecord->HelpString = -1;
9541 varrecord->res9 = -1;
9542 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9543 varrecord->HelpStringContext = desc->HelpStringContext;
9544 }else if(!list_empty(&desc->custdata_list)){
9545 size += 4 * sizeof(INT);
9546 varrecord->HelpContext = desc->HelpContext;
9547 if(desc->HelpString)
9548 varrecord->HelpString = desc->HelpString->offset;
9549 else
9550 varrecord->HelpString = -1;
9551 varrecord->res9 = -1;
9552 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9553 }else if(desc->HelpString){
9554 size += 2 * sizeof(INT);
9555 varrecord->HelpContext = desc->HelpContext;
9556 if(desc->HelpString)
9557 varrecord->HelpString = desc->HelpString->offset;
9558 else
9559 varrecord->HelpString = -1;
9560 }else if(desc->HelpContext != 0){
9561 size += sizeof(INT);
9562 varrecord->HelpContext = desc->HelpContext;
9565 varrecord->Info = size | (i << 16);
9567 *offsets = offs;
9568 offs += size;
9569 ++offsets;
9571 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9574 memid = (MEMBERID*)varrecord;
9575 for(i = 0; i < info->cFuncs; ++i){
9576 TLBFuncDesc *desc = &info->funcdescs[i];
9577 *memid = desc->funcdesc.memid;
9578 ++memid;
9580 for(i = 0; i < info->cVars; ++i){
9581 TLBVarDesc *desc = &info->vardescs[i];
9582 *memid = desc->vardesc.memid;
9583 ++memid;
9586 name = (UINT*)memid;
9587 for(i = 0; i < info->cFuncs; ++i){
9588 TLBFuncDesc *desc = &info->funcdescs[i];
9589 if(desc->Name)
9590 *name = desc->Name->offset;
9591 else
9592 *name = -1;
9593 ++name;
9595 for(i = 0; i < info->cVars; ++i){
9596 TLBVarDesc *desc = &info->vardescs[i];
9597 if(desc->Name)
9598 *name = desc->Name->offset;
9599 else
9600 *name = -1;
9601 ++name;
9604 return ret;
9607 typedef struct tagWMSFT_RefChunk {
9608 DWORD href;
9609 DWORD res04;
9610 DWORD res08;
9611 DWORD next;
9612 } WMSFT_RefChunk;
9614 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9616 DWORD offs = file->ref_seg.len, i;
9617 WMSFT_RefChunk *chunk;
9619 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9620 if(!file->ref_seg.data)
9621 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9622 else
9623 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9625 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9627 for(i = 0; i < info->cImplTypes; ++i){
9628 chunk->href = info->impltypes[i].hRef;
9629 chunk->res04 = info->impltypes[i].implflags;
9630 chunk->res08 = -1;
9631 if(i < info->cImplTypes - 1)
9632 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9633 else
9634 chunk->next = -1;
9635 ++chunk;
9638 return offs;
9641 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9643 DWORD size;
9645 size = sizeof(MSFT_TypeInfoBase);
9647 if(data){
9648 MSFT_TypeInfoBase *base = (void*)data;
9649 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9650 base->typekind = TKIND_DISPATCH;
9651 else
9652 base->typekind = info->typekind;
9653 base->typekind |= index << 16; /* TODO: There are some other flags here */
9654 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9655 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9656 base->res2 = 0;
9657 base->res3 = 0;
9658 base->res4 = 3;
9659 base->res5 = 0;
9660 base->cElement = (info->cVars << 16) | info->cFuncs;
9661 base->res7 = 0;
9662 base->res8 = 0;
9663 base->res9 = 0;
9664 base->resA = 0;
9665 if(info->guid)
9666 base->posguid = info->guid->offset;
9667 else
9668 base->posguid = -1;
9669 base->flags = info->wTypeFlags;
9670 if(info->Name) {
9671 base->NameOffset = info->Name->offset;
9673 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9674 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9675 }else {
9676 base->NameOffset = -1;
9678 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9679 if(info->DocString)
9680 base->docstringoffs = info->DocString->offset;
9681 else
9682 base->docstringoffs = -1;
9683 base->helpstringcontext = info->dwHelpStringContext;
9684 base->helpcontext = info->dwHelpContext;
9685 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9686 base->cImplTypes = info->cImplTypes;
9687 base->cbSizeVft = info->cbSizeVft;
9688 base->size = info->cbSizeInstance;
9689 if(info->typekind == TKIND_COCLASS){
9690 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9691 }else if(info->typekind == TKIND_ALIAS){
9692 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9693 }else if(info->typekind == TKIND_MODULE){
9694 if(info->DllName)
9695 base->datatype1 = info->DllName->offset;
9696 else
9697 base->datatype1 = -1;
9698 }else{
9699 if(info->cImplTypes > 0)
9700 base->datatype1 = info->impltypes[0].hRef;
9701 else
9702 base->datatype1 = -1;
9704 base->datatype2 = index; /* FIXME: i think there's more here */
9705 base->res18 = 0;
9706 base->res19 = -1;
9709 return size;
9712 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9714 UINT i;
9716 file->typeinfo_seg.len = 0;
9717 for(i = 0; i < This->TypeInfoCount; ++i){
9718 ITypeInfoImpl *info = This->typeinfos[i];
9719 *junk = file->typeinfo_seg.len;
9720 ++junk;
9721 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9724 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9725 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9727 file->aux_seg.len = 0;
9728 file->aux_seg.data = NULL;
9730 file->typeinfo_seg.len = 0;
9731 for(i = 0; i < This->TypeInfoCount; ++i){
9732 ITypeInfoImpl *info = This->typeinfos[i];
9733 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9734 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9738 typedef struct tagWMSFT_ImpFile {
9739 INT guid_offs;
9740 LCID lcid;
9741 DWORD version;
9742 } WMSFT_ImpFile;
9744 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9746 TLBImpLib *implib;
9747 WMSFT_ImpFile *impfile;
9748 char *data;
9749 DWORD last_offs = 0;
9751 file->impfile_seg.len = 0;
9752 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9753 int size = 0;
9755 if(implib->name){
9756 WCHAR *path = strrchrW(implib->name, '\\');
9757 if(path)
9758 ++path;
9759 else
9760 path = implib->name;
9761 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9762 if (size == 0)
9763 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9766 size += sizeof(INT16);
9767 if (size % 4)
9768 size = (size + 4) & ~0x3;
9769 if (size < 8)
9770 size = 8;
9772 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9775 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9777 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9778 int strlen = 0, size;
9780 impfile = (WMSFT_ImpFile*)data;
9781 impfile->guid_offs = implib->guid->offset;
9782 impfile->lcid = implib->lcid;
9783 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9785 data += sizeof(WMSFT_ImpFile);
9787 if(implib->name){
9788 WCHAR *path= strrchrW(implib->name, '\\');
9789 if(path)
9790 ++path;
9791 else
9792 path = implib->name;
9793 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9794 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9795 if (strlen == 0)
9796 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9799 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9801 size = strlen + sizeof(INT16);
9802 if (size % 4)
9803 size = (size + 4) & ~0x3;
9804 if (size < 8)
9805 size = 8;
9806 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9808 data += size;
9809 implib->offset = last_offs;
9810 last_offs += size + sizeof(WMSFT_ImpFile);
9814 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9816 MSFT_ImpInfo *info;
9817 TLBRefType *ref_type;
9818 UINT i = 0;
9820 WMSFT_compile_impfile(This, file);
9822 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9823 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9825 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9826 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9827 if(ref_type->index == TLB_REF_USE_GUID){
9828 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9829 info->oGuid = ref_type->guid->offset;
9830 }else
9831 info->oGuid = ref_type->index;
9832 info->oImpFile = ref_type->pImpTLInfo->offset;
9833 ++i;
9834 ++info;
9838 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9840 file->guidhash_seg.len = 0x80;
9841 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9842 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9845 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9847 file->namehash_seg.len = 0x200;
9848 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9849 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9852 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9854 if(contents && contents->len){
9855 segdir->offset = *running_offset;
9856 segdir->length = contents->len;
9857 *running_offset += segdir->length;
9858 }else{
9859 segdir->offset = -1;
9860 segdir->length = 0;
9863 /* TODO: do these ever change? */
9864 segdir->res08 = -1;
9865 segdir->res0c = 0xf;
9868 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9870 DWORD written;
9871 if(segment)
9872 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9875 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9876 DWORD file_len)
9878 DWORD i;
9879 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9881 for(i = 0; i < This->TypeInfoCount; ++i){
9882 base->memoffset += file_len;
9883 ++base;
9886 return S_OK;
9889 static void WMSFT_free_file(WMSFT_TLBFile *file)
9891 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9892 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9893 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9894 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9895 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9896 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9897 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9898 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9899 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9900 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9901 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9902 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9903 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9904 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9907 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9909 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9910 WMSFT_TLBFile file;
9911 DWORD written, junk_size, junk_offs, running_offset;
9912 BOOL br;
9913 HANDLE outfile;
9914 HRESULT hres;
9915 DWORD *junk;
9916 UINT i;
9918 TRACE("%p\n", This);
9920 for(i = 0; i < This->TypeInfoCount; ++i)
9921 if(This->typeinfos[i]->needs_layout)
9922 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9924 memset(&file, 0, sizeof(file));
9926 file.header.magic1 = 0x5446534D;
9927 file.header.magic2 = 0x00010002;
9928 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9929 file.header.lcid2 = This->set_lcid;
9930 file.header.varflags = 0x40 | This->syskind;
9931 if (This->HelpFile)
9932 file.header.varflags |= 0x10;
9933 if (This->HelpStringDll)
9934 file.header.varflags |= HELPDLLFLAG;
9935 file.header.version = (This->ver_minor << 16) | This->ver_major;
9936 file.header.flags = This->libflags;
9937 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9938 file.header.helpcontext = This->dwHelpContext;
9939 file.header.res44 = 0x20;
9940 file.header.res48 = 0x80;
9941 file.header.dispatchpos = This->dispatch_href;
9943 WMSFT_compile_namehash(This, &file);
9944 /* do name and string compilation to get offsets for other compilations */
9945 hres = WMSFT_compile_names(This, &file);
9946 if (FAILED(hres)){
9947 WMSFT_free_file(&file);
9948 return hres;
9951 hres = WMSFT_compile_strings(This, &file);
9952 if (FAILED(hres)){
9953 WMSFT_free_file(&file);
9954 return hres;
9957 WMSFT_compile_guidhash(This, &file);
9958 hres = WMSFT_compile_guids(This, &file);
9959 if (FAILED(hres)){
9960 WMSFT_free_file(&file);
9961 return hres;
9964 if(This->HelpFile)
9965 file.header.helpfile = This->HelpFile->offset;
9966 else
9967 file.header.helpfile = -1;
9969 if(This->DocString)
9970 file.header.helpstring = This->DocString->offset;
9971 else
9972 file.header.helpstring = -1;
9974 /* do some more segment compilation */
9975 file.header.nimpinfos = list_count(&This->ref_list);
9976 file.header.nrtypeinfos = This->TypeInfoCount;
9978 if(This->Name)
9979 file.header.NameOffset = This->Name->offset;
9980 else
9981 file.header.NameOffset = -1;
9983 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9985 if(This->guid)
9986 file.header.posguid = This->guid->offset;
9987 else
9988 file.header.posguid = -1;
9990 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9991 if(file.header.varflags & HELPDLLFLAG)
9992 junk_size += sizeof(DWORD);
9993 if(junk_size){
9994 junk = heap_alloc_zero(junk_size);
9995 if(file.header.varflags & HELPDLLFLAG){
9996 *junk = This->HelpStringDll->offset;
9997 junk_offs = 1;
9998 }else
9999 junk_offs = 0;
10000 }else{
10001 junk = NULL;
10002 junk_offs = 0;
10005 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10006 WMSFT_compile_impinfo(This, &file);
10008 running_offset = 0;
10010 TRACE("header at: 0x%x\n", running_offset);
10011 running_offset += sizeof(file.header);
10013 TRACE("junk at: 0x%x\n", running_offset);
10014 running_offset += junk_size;
10016 TRACE("segdir at: 0x%x\n", running_offset);
10017 running_offset += sizeof(file.segdir);
10019 TRACE("typeinfo at: 0x%x\n", running_offset);
10020 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10022 TRACE("guidhashtab at: 0x%x\n", running_offset);
10023 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10025 TRACE("guidtab at: 0x%x\n", running_offset);
10026 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10028 TRACE("reftab at: 0x%x\n", running_offset);
10029 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10031 TRACE("impinfo at: 0x%x\n", running_offset);
10032 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10034 TRACE("impfiles at: 0x%x\n", running_offset);
10035 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10037 TRACE("namehashtab at: 0x%x\n", running_offset);
10038 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10040 TRACE("nametab at: 0x%x\n", running_offset);
10041 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10043 TRACE("stringtab at: 0x%x\n", running_offset);
10044 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10046 TRACE("typdesc at: 0x%x\n", running_offset);
10047 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10049 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10050 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10052 TRACE("custdata at: 0x%x\n", running_offset);
10053 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10055 TRACE("cdguids at: 0x%x\n", running_offset);
10056 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10058 TRACE("res0e at: 0x%x\n", running_offset);
10059 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10061 TRACE("res0f at: 0x%x\n", running_offset);
10062 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10064 TRACE("aux_seg at: 0x%x\n", running_offset);
10066 WMSFT_fixup_typeinfos(This, &file, running_offset);
10068 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10069 FILE_ATTRIBUTE_NORMAL, 0);
10070 if (outfile == INVALID_HANDLE_VALUE){
10071 WMSFT_free_file(&file);
10072 heap_free(junk);
10073 return TYPE_E_IOERROR;
10076 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10077 if (!br) {
10078 WMSFT_free_file(&file);
10079 CloseHandle(outfile);
10080 heap_free(junk);
10081 return TYPE_E_IOERROR;
10084 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10085 heap_free(junk);
10086 if (!br) {
10087 WMSFT_free_file(&file);
10088 CloseHandle(outfile);
10089 return TYPE_E_IOERROR;
10092 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10093 if (!br) {
10094 WMSFT_free_file(&file);
10095 CloseHandle(outfile);
10096 return TYPE_E_IOERROR;
10099 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10100 WMSFT_write_segment(outfile, &file.guidhash_seg);
10101 WMSFT_write_segment(outfile, &file.guid_seg);
10102 WMSFT_write_segment(outfile, &file.ref_seg);
10103 WMSFT_write_segment(outfile, &file.impinfo_seg);
10104 WMSFT_write_segment(outfile, &file.impfile_seg);
10105 WMSFT_write_segment(outfile, &file.namehash_seg);
10106 WMSFT_write_segment(outfile, &file.name_seg);
10107 WMSFT_write_segment(outfile, &file.string_seg);
10108 WMSFT_write_segment(outfile, &file.typdesc_seg);
10109 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10110 WMSFT_write_segment(outfile, &file.custdata_seg);
10111 WMSFT_write_segment(outfile, &file.cdguids_seg);
10112 WMSFT_write_segment(outfile, &file.aux_seg);
10114 WMSFT_free_file(&file);
10116 CloseHandle(outfile);
10118 return S_OK;
10121 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10122 LPOLESTR name)
10124 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10125 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10126 return E_NOTIMPL;
10129 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10130 REFGUID guid, VARIANT *varVal)
10132 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10133 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
10134 return E_NOTIMPL;
10137 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10138 ULONG helpStringContext)
10140 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10141 FIXME("%p %u - stub\n", This, helpStringContext);
10142 return E_NOTIMPL;
10145 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10146 LPOLESTR filename)
10148 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10149 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10151 if (!filename)
10152 return E_INVALIDARG;
10154 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10156 return S_OK;
10159 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10160 ICreateTypeLib2_fnQueryInterface,
10161 ICreateTypeLib2_fnAddRef,
10162 ICreateTypeLib2_fnRelease,
10163 ICreateTypeLib2_fnCreateTypeInfo,
10164 ICreateTypeLib2_fnSetName,
10165 ICreateTypeLib2_fnSetVersion,
10166 ICreateTypeLib2_fnSetGuid,
10167 ICreateTypeLib2_fnSetDocString,
10168 ICreateTypeLib2_fnSetHelpFileName,
10169 ICreateTypeLib2_fnSetHelpContext,
10170 ICreateTypeLib2_fnSetLcid,
10171 ICreateTypeLib2_fnSetLibFlags,
10172 ICreateTypeLib2_fnSaveAllChanges,
10173 ICreateTypeLib2_fnDeleteTypeInfo,
10174 ICreateTypeLib2_fnSetCustData,
10175 ICreateTypeLib2_fnSetHelpStringContext,
10176 ICreateTypeLib2_fnSetHelpStringDll
10179 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10180 REFIID riid, void **object)
10182 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10184 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10187 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10189 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10191 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10194 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10196 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10198 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10201 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10202 REFGUID guid)
10204 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10206 TRACE("%p %s\n", This, debugstr_guid(guid));
10208 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10210 return S_OK;
10213 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10214 UINT typeFlags)
10216 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10217 WORD old_flags;
10218 HRESULT hres;
10220 TRACE("%p %x\n", This, typeFlags);
10222 if (typeFlags & TYPEFLAG_FDUAL) {
10223 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10224 ITypeLib *stdole;
10225 ITypeInfo *dispatch;
10226 HREFTYPE hreftype;
10227 HRESULT hres;
10229 hres = LoadTypeLib(stdole2tlb, &stdole);
10230 if(FAILED(hres))
10231 return hres;
10233 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10234 ITypeLib_Release(stdole);
10235 if(FAILED(hres))
10236 return hres;
10238 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10239 ITypeInfo_Release(dispatch);
10240 if(FAILED(hres))
10241 return hres;
10244 old_flags = This->wTypeFlags;
10245 This->wTypeFlags = typeFlags;
10247 hres = ICreateTypeInfo2_LayOut(iface);
10248 if (FAILED(hres)) {
10249 This->wTypeFlags = old_flags;
10250 return hres;
10253 return S_OK;
10256 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10257 LPOLESTR doc)
10259 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10261 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10263 if (!doc)
10264 return E_INVALIDARG;
10266 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10268 return S_OK;
10271 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10272 DWORD helpContext)
10274 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10276 TRACE("%p %d\n", This, helpContext);
10278 This->dwHelpContext = helpContext;
10280 return S_OK;
10283 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10284 WORD majorVerNum, WORD minorVerNum)
10286 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10288 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10290 This->wMajorVerNum = majorVerNum;
10291 This->wMinorVerNum = minorVerNum;
10293 return S_OK;
10296 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10297 ITypeInfo *typeInfo, HREFTYPE *refType)
10299 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10300 UINT index;
10301 ITypeLib *container;
10302 TLBRefType *ref_type;
10303 TLBImpLib *implib;
10304 TYPEATTR *typeattr;
10305 TLIBATTR *libattr;
10306 HRESULT hres;
10308 TRACE("%p %p %p\n", This, typeInfo, refType);
10310 if (!typeInfo || !refType)
10311 return E_INVALIDARG;
10313 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10314 if (FAILED(hres))
10315 return hres;
10317 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10318 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10320 ITypeLib_Release(container);
10322 *refType = target->hreftype;
10324 return S_OK;
10327 hres = ITypeLib_GetLibAttr(container, &libattr);
10328 if (FAILED(hres)) {
10329 ITypeLib_Release(container);
10330 return hres;
10333 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10334 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10335 implib->lcid == libattr->lcid &&
10336 implib->wVersionMajor == libattr->wMajorVerNum &&
10337 implib->wVersionMinor == libattr->wMinorVerNum)
10338 break;
10341 if(&implib->entry == &This->pTypeLib->implib_list){
10342 implib = heap_alloc_zero(sizeof(TLBImpLib));
10344 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10345 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10346 implib->name = SysAllocString(our_container->path);
10347 }else{
10348 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10349 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10350 if(FAILED(hres)){
10351 implib->name = NULL;
10352 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10356 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10357 implib->lcid = libattr->lcid;
10358 implib->wVersionMajor = libattr->wMajorVerNum;
10359 implib->wVersionMinor = libattr->wMinorVerNum;
10361 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10364 ITypeLib_ReleaseTLibAttr(container, libattr);
10365 ITypeLib_Release(container);
10367 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10368 if (FAILED(hres))
10369 return hres;
10371 index = 0;
10372 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10373 if(ref_type->index == TLB_REF_USE_GUID &&
10374 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10375 ref_type->tkind == typeattr->typekind)
10376 break;
10377 ++index;
10380 if(&ref_type->entry == &This->pTypeLib->ref_list){
10381 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10383 ref_type->tkind = typeattr->typekind;
10384 ref_type->pImpTLInfo = implib;
10385 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10387 ref_type->index = TLB_REF_USE_GUID;
10389 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10391 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10394 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10396 *refType = ref_type->reference | 0x1;
10398 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10399 This->pTypeLib->dispatch_href = *refType;
10401 return S_OK;
10404 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10405 UINT index, FUNCDESC *funcDesc)
10407 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10408 TLBFuncDesc tmp_func_desc, *func_desc;
10409 int buf_size, i;
10410 char *buffer;
10411 HRESULT hres;
10413 TRACE("%p %u %p\n", This, index, funcDesc);
10415 if (!funcDesc || funcDesc->oVft & 3)
10416 return E_INVALIDARG;
10418 switch (This->typekind) {
10419 case TKIND_MODULE:
10420 if (funcDesc->funckind != FUNC_STATIC)
10421 return TYPE_E_BADMODULEKIND;
10422 break;
10423 case TKIND_DISPATCH:
10424 if (funcDesc->funckind != FUNC_DISPATCH)
10425 return TYPE_E_BADMODULEKIND;
10426 break;
10427 default:
10428 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10429 return TYPE_E_BADMODULEKIND;
10432 if (index > This->cFuncs)
10433 return TYPE_E_ELEMENTNOTFOUND;
10435 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10436 !funcDesc->cParams)
10437 return TYPE_E_INCONSISTENTPROPFUNCS;
10439 #ifdef _WIN64
10440 if(This->pTypeLib->syskind == SYS_WIN64 &&
10441 funcDesc->oVft % 8 != 0)
10442 return E_INVALIDARG;
10443 #endif
10445 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10446 TLBFuncDesc_Constructor(&tmp_func_desc);
10448 tmp_func_desc.funcdesc = *funcDesc;
10450 if (tmp_func_desc.funcdesc.oVft != 0)
10451 tmp_func_desc.funcdesc.oVft |= 1;
10453 if (funcDesc->cScodes) {
10454 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10455 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10456 } else
10457 tmp_func_desc.funcdesc.lprgscode = NULL;
10459 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10460 for (i = 0; i < funcDesc->cParams; ++i) {
10461 buf_size += sizeof(ELEMDESC);
10462 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10464 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10465 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10467 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10468 if (FAILED(hres)) {
10469 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10470 heap_free(tmp_func_desc.funcdesc.lprgscode);
10471 return hres;
10474 for (i = 0; i < funcDesc->cParams; ++i) {
10475 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10476 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10477 if (FAILED(hres)) {
10478 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10479 heap_free(tmp_func_desc.funcdesc.lprgscode);
10480 return hres;
10482 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10483 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10484 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10485 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10486 if (FAILED(hres)) {
10487 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10488 heap_free(tmp_func_desc.funcdesc.lprgscode);
10489 return hres;
10494 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10496 if (This->funcdescs) {
10497 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10498 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10500 if (index < This->cFuncs) {
10501 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10502 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10503 func_desc = This->funcdescs + index;
10504 } else
10505 func_desc = This->funcdescs + This->cFuncs;
10507 /* move custdata lists to the new memory location */
10508 for(i = 0; i < This->cFuncs + 1; ++i){
10509 if(index != i){
10510 TLBFuncDesc *fd = &This->funcdescs[i];
10511 if(fd->custdata_list.prev == fd->custdata_list.next)
10512 list_init(&fd->custdata_list);
10513 else{
10514 fd->custdata_list.prev->next = &fd->custdata_list;
10515 fd->custdata_list.next->prev = &fd->custdata_list;
10519 } else
10520 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10522 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10523 list_init(&func_desc->custdata_list);
10525 ++This->cFuncs;
10527 This->needs_layout = TRUE;
10529 return S_OK;
10532 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10533 UINT index, HREFTYPE refType)
10535 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10536 TLBImplType *impl_type;
10537 HRESULT hres;
10539 TRACE("%p %u %d\n", This, index, refType);
10541 switch(This->typekind){
10542 case TKIND_COCLASS: {
10543 if (index == -1) {
10544 FIXME("Unhandled index: -1\n");
10545 return E_NOTIMPL;
10548 if(index != This->cImplTypes)
10549 return TYPE_E_ELEMENTNOTFOUND;
10551 break;
10553 case TKIND_INTERFACE:
10554 case TKIND_DISPATCH:
10555 if (index != 0 || This->cImplTypes)
10556 return TYPE_E_ELEMENTNOTFOUND;
10557 break;
10558 default:
10559 FIXME("Unimplemented typekind: %d\n", This->typekind);
10560 return E_NOTIMPL;
10563 if (This->impltypes){
10564 UINT i;
10566 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10567 sizeof(TLBImplType) * (This->cImplTypes + 1));
10569 if (index < This->cImplTypes) {
10570 memmove(This->impltypes + index + 1, This->impltypes + index,
10571 (This->cImplTypes - index) * sizeof(TLBImplType));
10572 impl_type = This->impltypes + index;
10573 } else
10574 impl_type = This->impltypes + This->cImplTypes;
10576 /* move custdata lists to the new memory location */
10577 for(i = 0; i < This->cImplTypes + 1; ++i){
10578 if(index != i){
10579 TLBImplType *it = &This->impltypes[i];
10580 if(it->custdata_list.prev == it->custdata_list.next)
10581 list_init(&it->custdata_list);
10582 else{
10583 it->custdata_list.prev->next = &it->custdata_list;
10584 it->custdata_list.next->prev = &it->custdata_list;
10588 } else
10589 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10591 memset(impl_type, 0, sizeof(TLBImplType));
10592 TLBImplType_Constructor(impl_type);
10593 impl_type->hRef = refType;
10595 ++This->cImplTypes;
10597 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10598 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10600 hres = ICreateTypeInfo2_LayOut(iface);
10601 if (FAILED(hres))
10602 return hres;
10604 return S_OK;
10607 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10608 UINT index, INT implTypeFlags)
10610 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10611 TLBImplType *impl_type = &This->impltypes[index];
10613 TRACE("%p %u %x\n", This, index, implTypeFlags);
10615 if (This->typekind != TKIND_COCLASS)
10616 return TYPE_E_BADMODULEKIND;
10618 if (index >= This->cImplTypes)
10619 return TYPE_E_ELEMENTNOTFOUND;
10621 impl_type->implflags = implTypeFlags;
10623 return S_OK;
10626 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10627 WORD alignment)
10629 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10631 TRACE("%p %d\n", This, alignment);
10633 This->cbAlignment = alignment;
10635 return S_OK;
10638 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10639 LPOLESTR schema)
10641 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10643 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10645 if (!schema)
10646 return E_INVALIDARG;
10648 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10650 This->lpstrSchema = This->Schema->str;
10652 return S_OK;
10655 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10656 UINT index, VARDESC *varDesc)
10658 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10659 TLBVarDesc *var_desc;
10661 TRACE("%p %u %p\n", This, index, varDesc);
10663 if (This->vardescs){
10664 UINT i;
10666 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10667 sizeof(TLBVarDesc) * (This->cVars + 1));
10669 if (index < This->cVars) {
10670 memmove(This->vardescs + index + 1, This->vardescs + index,
10671 (This->cVars - index) * sizeof(TLBVarDesc));
10672 var_desc = This->vardescs + index;
10673 } else
10674 var_desc = This->vardescs + This->cVars;
10676 /* move custdata lists to the new memory location */
10677 for(i = 0; i < This->cVars + 1; ++i){
10678 if(index != i){
10679 TLBVarDesc *var = &This->vardescs[i];
10680 if(var->custdata_list.prev == var->custdata_list.next)
10681 list_init(&var->custdata_list);
10682 else{
10683 var->custdata_list.prev->next = &var->custdata_list;
10684 var->custdata_list.next->prev = &var->custdata_list;
10688 } else
10689 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10691 TLBVarDesc_Constructor(var_desc);
10692 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10693 var_desc->vardesc = *var_desc->vardesc_create;
10695 ++This->cVars;
10697 This->needs_layout = TRUE;
10699 return S_OK;
10702 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10703 UINT index, LPOLESTR *names, UINT numNames)
10705 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10706 TLBFuncDesc *func_desc = &This->funcdescs[index];
10707 int i;
10709 TRACE("%p %u %p %u\n", This, index, names, numNames);
10711 if (!names)
10712 return E_INVALIDARG;
10714 if (index >= This->cFuncs || numNames == 0)
10715 return TYPE_E_ELEMENTNOTFOUND;
10717 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10718 if(numNames > func_desc->funcdesc.cParams)
10719 return TYPE_E_ELEMENTNOTFOUND;
10720 } else
10721 if(numNames > func_desc->funcdesc.cParams + 1)
10722 return TYPE_E_ELEMENTNOTFOUND;
10724 for(i = 0; i < This->cFuncs; ++i) {
10725 TLBFuncDesc *iter = &This->funcdescs[i];
10726 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10727 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10728 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10729 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10730 continue;
10731 return TYPE_E_AMBIGUOUSNAME;
10735 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10737 for (i = 1; i < numNames; ++i) {
10738 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10739 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10742 return S_OK;
10745 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10746 UINT index, LPOLESTR name)
10748 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10750 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10752 if(!name)
10753 return E_INVALIDARG;
10755 if(index >= This->cVars)
10756 return TYPE_E_ELEMENTNOTFOUND;
10758 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10759 return S_OK;
10762 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10763 TYPEDESC *tdescAlias)
10765 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10766 HRESULT hr;
10768 TRACE("%p %p\n", This, tdescAlias);
10770 if(!tdescAlias)
10771 return E_INVALIDARG;
10773 if(This->typekind != TKIND_ALIAS)
10774 return TYPE_E_BADMODULEKIND;
10776 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->cbSizeInstance, &This->cbAlignment);
10777 if(FAILED(hr))
10778 return hr;
10780 heap_free(This->tdescAlias);
10781 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10782 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10784 return S_OK;
10787 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10788 UINT index, LPOLESTR dllName, LPOLESTR procName)
10790 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10791 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10792 return E_NOTIMPL;
10795 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10796 UINT index, LPOLESTR docString)
10798 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10799 TLBFuncDesc *func_desc = &This->funcdescs[index];
10801 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10803 if(!docString)
10804 return E_INVALIDARG;
10806 if(index >= This->cFuncs)
10807 return TYPE_E_ELEMENTNOTFOUND;
10809 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10811 return S_OK;
10814 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10815 UINT index, LPOLESTR docString)
10817 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10818 TLBVarDesc *var_desc = &This->vardescs[index];
10820 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10822 if(!docString)
10823 return E_INVALIDARG;
10825 if(index >= This->cVars)
10826 return TYPE_E_ELEMENTNOTFOUND;
10828 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10830 return S_OK;
10833 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10834 UINT index, DWORD helpContext)
10836 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10837 TLBFuncDesc *func_desc = &This->funcdescs[index];
10839 TRACE("%p %u %d\n", This, index, helpContext);
10841 if(index >= This->cFuncs)
10842 return TYPE_E_ELEMENTNOTFOUND;
10844 func_desc->helpcontext = helpContext;
10846 return S_OK;
10849 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10850 UINT index, DWORD helpContext)
10852 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10853 TLBVarDesc *var_desc = &This->vardescs[index];
10855 TRACE("%p %u %d\n", This, index, helpContext);
10857 if(index >= This->cVars)
10858 return TYPE_E_ELEMENTNOTFOUND;
10860 var_desc->HelpContext = helpContext;
10862 return S_OK;
10865 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10866 UINT index, BSTR bstrMops)
10868 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10869 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10870 return E_NOTIMPL;
10873 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10874 IDLDESC *idlDesc)
10876 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10878 TRACE("%p %p\n", This, idlDesc);
10880 if (!idlDesc)
10881 return E_INVALIDARG;
10883 This->idldescType.dwReserved = idlDesc->dwReserved;
10884 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10886 return S_OK;
10889 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10891 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10892 ITypeInfo *tinfo;
10893 TLBFuncDesc *func_desc;
10894 UINT user_vft = 0, i, depth = 0;
10895 HRESULT hres = S_OK;
10897 TRACE("%p\n", This);
10899 This->needs_layout = FALSE;
10901 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10902 if (FAILED(hres))
10903 return hres;
10905 if (This->typekind == TKIND_INTERFACE) {
10906 ITypeInfo *inh;
10907 TYPEATTR *attr;
10908 HREFTYPE inh_href;
10910 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10912 if (SUCCEEDED(hres)) {
10913 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10915 if (SUCCEEDED(hres)) {
10916 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10917 if (FAILED(hres)) {
10918 ITypeInfo_Release(inh);
10919 ITypeInfo_Release(tinfo);
10920 return hres;
10922 This->cbSizeVft = attr->cbSizeVft;
10923 ITypeInfo_ReleaseTypeAttr(inh, attr);
10926 ++depth;
10927 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10928 if(SUCCEEDED(hres)){
10929 ITypeInfo *next;
10930 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10931 if(SUCCEEDED(hres)){
10932 ITypeInfo_Release(inh);
10933 inh = next;
10936 }while(SUCCEEDED(hres));
10937 hres = S_OK;
10939 ITypeInfo_Release(inh);
10940 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10941 This->cbSizeVft = 0;
10942 hres = S_OK;
10943 } else {
10944 ITypeInfo_Release(tinfo);
10945 return hres;
10947 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10948 This->cbSizeVft = 0;
10949 hres = S_OK;
10950 } else {
10951 ITypeInfo_Release(tinfo);
10952 return hres;
10954 } else if (This->typekind == TKIND_DISPATCH)
10955 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10956 else
10957 This->cbSizeVft = 0;
10959 func_desc = This->funcdescs;
10960 i = 0;
10961 while (i < This->cFuncs) {
10962 if (!(func_desc->funcdesc.oVft & 0x1))
10963 func_desc->funcdesc.oVft = This->cbSizeVft;
10965 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10966 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10968 This->cbSizeVft += This->pTypeLib->ptr_size;
10970 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10971 TLBFuncDesc *iter;
10972 UINT j = 0;
10973 BOOL reset = FALSE;
10975 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10977 iter = This->funcdescs;
10978 while (j < This->cFuncs) {
10979 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10980 if (!reset) {
10981 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10982 reset = TRUE;
10983 } else
10984 ++func_desc->funcdesc.memid;
10985 iter = This->funcdescs;
10986 j = 0;
10987 } else {
10988 ++iter;
10989 ++j;
10994 ++func_desc;
10995 ++i;
10998 if (user_vft > This->cbSizeVft)
10999 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11001 for(i = 0; i < This->cVars; ++i){
11002 TLBVarDesc *var_desc = &This->vardescs[i];
11003 if(var_desc->vardesc.memid == MEMBERID_NIL){
11004 UINT j = 0;
11005 BOOL reset = FALSE;
11006 TLBVarDesc *iter;
11008 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11010 iter = This->vardescs;
11011 while (j < This->cVars) {
11012 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11013 if (!reset) {
11014 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->cVars;
11015 reset = TRUE;
11016 } else
11017 ++var_desc->vardesc.memid;
11018 iter = This->vardescs;
11019 j = 0;
11020 } else {
11021 ++iter;
11022 ++j;
11028 ITypeInfo_Release(tinfo);
11029 return hres;
11032 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11033 UINT index)
11035 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11036 FIXME("%p %u - stub\n", This, index);
11037 return E_NOTIMPL;
11040 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11041 MEMBERID memid, INVOKEKIND invKind)
11043 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11044 FIXME("%p %x %d - stub\n", This, memid, invKind);
11045 return E_NOTIMPL;
11048 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11049 UINT index)
11051 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11052 FIXME("%p %u - stub\n", This, index);
11053 return E_NOTIMPL;
11056 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11057 MEMBERID memid)
11059 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11060 FIXME("%p %x - stub\n", This, memid);
11061 return E_NOTIMPL;
11064 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11065 UINT index)
11067 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11068 FIXME("%p %u - stub\n", This, index);
11069 return E_NOTIMPL;
11072 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11073 REFGUID guid, VARIANT *varVal)
11075 TLBGuid *tlbguid;
11077 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11079 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11081 if (!guid || !varVal)
11082 return E_INVALIDARG;
11084 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11086 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11089 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11090 UINT index, REFGUID guid, VARIANT *varVal)
11092 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11093 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11094 return E_NOTIMPL;
11097 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11098 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11100 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11101 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11102 return E_NOTIMPL;
11105 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11106 UINT index, REFGUID guid, VARIANT *varVal)
11108 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11109 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11110 return E_NOTIMPL;
11113 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11114 UINT index, REFGUID guid, VARIANT *varVal)
11116 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11117 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11118 return E_NOTIMPL;
11121 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11122 ULONG helpStringContext)
11124 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11126 TRACE("%p %u\n", This, helpStringContext);
11128 This->dwHelpStringContext = helpStringContext;
11130 return S_OK;
11133 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11134 UINT index, ULONG helpStringContext)
11136 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11137 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11138 return E_NOTIMPL;
11141 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11142 UINT index, ULONG helpStringContext)
11144 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11145 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11146 return E_NOTIMPL;
11149 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11151 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11152 FIXME("%p - stub\n", This);
11153 return E_NOTIMPL;
11156 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11157 LPOLESTR name)
11159 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11161 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11163 if (!name)
11164 return E_INVALIDARG;
11166 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11168 return S_OK;
11171 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11172 ICreateTypeInfo2_fnQueryInterface,
11173 ICreateTypeInfo2_fnAddRef,
11174 ICreateTypeInfo2_fnRelease,
11175 ICreateTypeInfo2_fnSetGuid,
11176 ICreateTypeInfo2_fnSetTypeFlags,
11177 ICreateTypeInfo2_fnSetDocString,
11178 ICreateTypeInfo2_fnSetHelpContext,
11179 ICreateTypeInfo2_fnSetVersion,
11180 ICreateTypeInfo2_fnAddRefTypeInfo,
11181 ICreateTypeInfo2_fnAddFuncDesc,
11182 ICreateTypeInfo2_fnAddImplType,
11183 ICreateTypeInfo2_fnSetImplTypeFlags,
11184 ICreateTypeInfo2_fnSetAlignment,
11185 ICreateTypeInfo2_fnSetSchema,
11186 ICreateTypeInfo2_fnAddVarDesc,
11187 ICreateTypeInfo2_fnSetFuncAndParamNames,
11188 ICreateTypeInfo2_fnSetVarName,
11189 ICreateTypeInfo2_fnSetTypeDescAlias,
11190 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11191 ICreateTypeInfo2_fnSetFuncDocString,
11192 ICreateTypeInfo2_fnSetVarDocString,
11193 ICreateTypeInfo2_fnSetFuncHelpContext,
11194 ICreateTypeInfo2_fnSetVarHelpContext,
11195 ICreateTypeInfo2_fnSetMops,
11196 ICreateTypeInfo2_fnSetTypeIdldesc,
11197 ICreateTypeInfo2_fnLayOut,
11198 ICreateTypeInfo2_fnDeleteFuncDesc,
11199 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11200 ICreateTypeInfo2_fnDeleteVarDesc,
11201 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11202 ICreateTypeInfo2_fnDeleteImplType,
11203 ICreateTypeInfo2_fnSetCustData,
11204 ICreateTypeInfo2_fnSetFuncCustData,
11205 ICreateTypeInfo2_fnSetParamCustData,
11206 ICreateTypeInfo2_fnSetVarCustData,
11207 ICreateTypeInfo2_fnSetImplTypeCustData,
11208 ICreateTypeInfo2_fnSetHelpStringContext,
11209 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11210 ICreateTypeInfo2_fnSetVarHelpStringContext,
11211 ICreateTypeInfo2_fnInvalidate,
11212 ICreateTypeInfo2_fnSetName
11215 /******************************************************************************
11216 * ClearCustData (OLEAUT32.171)
11218 * Clear a custom data type's data.
11220 * PARAMS
11221 * lpCust [I] The custom data type instance
11223 * RETURNS
11224 * Nothing.
11226 void WINAPI ClearCustData(CUSTDATA *lpCust)
11228 if (lpCust && lpCust->cCustData)
11230 if (lpCust->prgCustData)
11232 DWORD i;
11234 for (i = 0; i < lpCust->cCustData; i++)
11235 VariantClear(&lpCust->prgCustData[i].varValue);
11237 CoTaskMemFree(lpCust->prgCustData);
11238 lpCust->prgCustData = NULL;
11240 lpCust->cCustData = 0;