oleaut32: Explicitly define call_double_method() to avoid function mismatch warning.
[wine.git] / dlls / oleaut32 / typelib.c
blobb907c96699803438f8cf78df4e25dfe713dc3203
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
62 #include "winerror.h"
63 #include "windef.h"
64 #include "winbase.h"
65 #include "winnls.h"
66 #include "winreg.h"
67 #include "winuser.h"
68 #include "winternl.h"
69 #include "lzexpand.h"
71 #include "wine/unicode.h"
72 #include "objbase.h"
73 #include "typelib.h"
74 #include "wine/debug.h"
75 #include "variant.h"
76 #include "wine/heap.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 ((wMaj != 0xffff || wMin != 0xffff) && (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 if (!szFile || !pptLib)
477 return E_INVALIDARG;
479 *pptLib = NULL;
481 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
483 if (SUCCEEDED(res))
484 switch(regkind)
486 case REGKIND_DEFAULT:
487 /* don't register typelibs supplied with full path. Experimentation confirms the following */
488 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
489 (szFile[0] && (szFile[1] == ':'))) break;
490 /* else fall-through */
492 case REGKIND_REGISTER:
493 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
495 ITypeLib_Release(*pptLib);
496 *pptLib = 0;
498 break;
499 case REGKIND_NONE:
500 break;
503 TRACE(" returns %08x\n",res);
504 return res;
507 /******************************************************************************
508 * LoadRegTypeLib [OLEAUT32.162]
510 * Loads a registered type library.
512 * PARAMS
513 * rguid [I] GUID of the registered type library.
514 * wVerMajor [I] major version.
515 * wVerMinor [I] minor version.
516 * lcid [I] locale ID.
517 * ppTLib [O] pointer that receives an ITypeLib object on success.
519 * RETURNS
520 * Success: S_OK.
521 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
522 * LoadTypeLib.
524 HRESULT WINAPI LoadRegTypeLib(
525 REFGUID rguid,
526 WORD wVerMajor,
527 WORD wVerMinor,
528 LCID lcid,
529 ITypeLib **ppTLib)
531 BSTR bstr=NULL;
532 HRESULT res;
534 *ppTLib = NULL;
536 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
538 if(SUCCEEDED(res))
540 res= LoadTypeLib(bstr, ppTLib);
541 SysFreeString(bstr);
543 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
545 TLIBATTR *attr;
547 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
548 if (res == S_OK)
550 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
551 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
553 if (mismatch)
555 ITypeLib_Release(*ppTLib);
556 *ppTLib = NULL;
557 res = TYPE_E_LIBNOTREGISTERED;
563 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
565 return res;
569 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
570 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
571 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
572 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
573 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
574 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
576 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
578 WCHAR keyName[60];
579 HKEY key, subKey;
581 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
582 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
583 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
585 get_interface_key( &tattr->guid, keyName );
586 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
587 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
589 if (name)
590 RegSetValueExW(key, NULL, 0, REG_SZ,
591 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
593 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
594 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
595 RegSetValueExW(subKey, NULL, 0, REG_SZ,
596 (const BYTE *)PSOA, sizeof PSOA);
597 RegCloseKey(subKey);
600 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
601 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
602 RegSetValueExW(subKey, NULL, 0, REG_SZ,
603 (const BYTE *)PSOA, sizeof PSOA);
604 RegCloseKey(subKey);
607 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
608 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
610 WCHAR buffer[40];
611 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
612 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
614 StringFromGUID2(&libattr->guid, buffer, 40);
615 RegSetValueExW(subKey, NULL, 0, REG_SZ,
616 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
617 sprintfW(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
618 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
619 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
620 RegCloseKey(subKey);
623 RegCloseKey(key);
627 /******************************************************************************
628 * RegisterTypeLib [OLEAUT32.163]
629 * Adds information about a type library to the System Registry
630 * NOTES
631 * Docs: ITypeLib FAR * ptlib
632 * Docs: OLECHAR FAR* szFullPath
633 * Docs: OLECHAR FAR* szHelpDir
635 * RETURNS
636 * Success: S_OK
637 * Failure: Status
639 HRESULT WINAPI RegisterTypeLib(
640 ITypeLib * ptlib, /* [in] Pointer to the library*/
641 OLECHAR * szFullPath, /* [in] full Path of the library*/
642 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
643 may be NULL*/
645 HRESULT res;
646 TLIBATTR *attr;
647 WCHAR keyName[60];
648 WCHAR tmp[16];
649 HKEY key, subKey;
650 UINT types, tidx;
651 TYPEKIND kind;
652 DWORD disposition;
654 if (ptlib == NULL || szFullPath == NULL)
655 return E_INVALIDARG;
657 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
658 return E_FAIL;
660 #ifndef _WIN64
661 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
662 #endif
664 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
666 res = S_OK;
667 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
668 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
670 LPOLESTR doc;
672 /* Set the human-readable name of the typelib */
673 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
674 res = E_FAIL;
675 else if (doc)
677 if (RegSetValueExW(key, NULL, 0, REG_SZ,
678 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
679 res = E_FAIL;
681 SysFreeString(doc);
684 /* Make up the name of the typelib path subkey */
685 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
687 /* Create the typelib path subkey */
688 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
689 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
691 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
692 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
693 res = E_FAIL;
695 RegCloseKey(subKey);
697 else
698 res = E_FAIL;
700 /* Create the flags subkey */
701 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
702 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
704 /* FIXME: is %u correct? */
705 static const WCHAR formatW[] = {'%','u',0};
706 WCHAR buf[20];
707 sprintfW(buf, formatW, attr->wLibFlags);
708 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
709 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
710 res = E_FAIL;
712 RegCloseKey(subKey);
714 else
715 res = E_FAIL;
717 /* create the helpdir subkey */
718 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
719 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
721 BOOL freeHelpDir = FALSE;
722 OLECHAR* pIndexStr;
724 /* if we created a new key, and helpDir was null, set the helpdir
725 to the directory which contains the typelib. However,
726 if we just opened an existing key, we leave the helpdir alone */
727 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
728 szHelpDir = SysAllocString(szFullPath);
729 pIndexStr = strrchrW(szHelpDir, '\\');
730 if (pIndexStr) {
731 *pIndexStr = 0;
733 freeHelpDir = TRUE;
736 /* if we have an szHelpDir, set it! */
737 if (szHelpDir != NULL) {
738 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
739 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
740 res = E_FAIL;
744 /* tidy up */
745 if (freeHelpDir) SysFreeString(szHelpDir);
746 RegCloseKey(subKey);
748 } else {
749 res = E_FAIL;
752 RegCloseKey(key);
754 else
755 res = E_FAIL;
757 /* register OLE Automation-compatible interfaces for this typelib */
758 types = ITypeLib_GetTypeInfoCount(ptlib);
759 for (tidx=0; tidx<types; tidx++) {
760 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
761 LPOLESTR name = NULL;
762 ITypeInfo *tinfo = NULL;
764 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
766 switch (kind) {
767 case TKIND_INTERFACE:
768 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
769 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
770 break;
772 case TKIND_DISPATCH:
773 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
774 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
775 break;
777 default:
778 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
779 break;
782 if (tinfo) {
783 TYPEATTR *tattr = NULL;
784 ITypeInfo_GetTypeAttr(tinfo, &tattr);
786 if (tattr) {
787 TRACE_(typelib)("guid=%s, flags=%04x (",
788 debugstr_guid(&tattr->guid),
789 tattr->wTypeFlags);
791 if (TRACE_ON(typelib)) {
792 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
793 XX(FAPPOBJECT);
794 XX(FCANCREATE);
795 XX(FLICENSED);
796 XX(FPREDECLID);
797 XX(FHIDDEN);
798 XX(FCONTROL);
799 XX(FDUAL);
800 XX(FNONEXTENSIBLE);
801 XX(FOLEAUTOMATION);
802 XX(FRESTRICTED);
803 XX(FAGGREGATABLE);
804 XX(FREPLACEABLE);
805 XX(FDISPATCHABLE);
806 XX(FREVERSEBIND);
807 XX(FPROXY);
808 #undef XX
809 MESSAGE("\n");
812 /* Register all dispinterfaces (which includes dual interfaces) and
813 oleautomation interfaces */
814 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
815 kind == TKIND_DISPATCH)
817 BOOL is_wow64;
818 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
820 /* register interface<->typelib coupling */
821 TLB_register_interface(attr, name, tattr, 0);
823 /* register TLBs into the opposite registry view, too */
824 if(opposite == KEY_WOW64_32KEY ||
825 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
826 TLB_register_interface(attr, name, tattr, opposite);
829 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
832 ITypeInfo_Release(tinfo);
835 SysFreeString(name);
839 ITypeLib_ReleaseTLibAttr(ptlib, attr);
841 return res;
844 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
846 WCHAR subKeyName[50];
847 HKEY subKey;
849 /* the path to the type */
850 get_interface_key( guid, subKeyName );
852 /* Delete its bits */
853 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
854 return;
856 RegDeleteKeyW(subKey, ProxyStubClsidW);
857 RegDeleteKeyW(subKey, ProxyStubClsid32W);
858 RegDeleteKeyW(subKey, TypeLibW);
859 RegCloseKey(subKey);
860 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
863 /******************************************************************************
864 * UnRegisterTypeLib [OLEAUT32.186]
865 * Removes information about a type library from the System Registry
866 * NOTES
868 * RETURNS
869 * Success: S_OK
870 * Failure: Status
872 HRESULT WINAPI UnRegisterTypeLib(
873 REFGUID libid, /* [in] Guid of the library */
874 WORD wVerMajor, /* [in] major version */
875 WORD wVerMinor, /* [in] minor version */
876 LCID lcid, /* [in] locale id */
877 SYSKIND syskind)
879 BSTR tlibPath = NULL;
880 DWORD tmpLength;
881 WCHAR keyName[60];
882 WCHAR subKeyName[50];
883 int result = S_OK;
884 DWORD i = 0;
885 BOOL deleteOtherStuff;
886 HKEY key = NULL;
887 TYPEATTR* typeAttr = NULL;
888 TYPEKIND kind;
889 ITypeInfo* typeInfo = NULL;
890 ITypeLib* typeLib = NULL;
891 int numTypes;
893 TRACE("(IID: %s)\n",debugstr_guid(libid));
895 /* Create the path to the key */
896 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
898 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
900 TRACE("Unsupported syskind %i\n", syskind);
901 result = E_INVALIDARG;
902 goto end;
905 /* get the path to the typelib on disk */
906 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
907 result = E_INVALIDARG;
908 goto end;
911 /* Try and open the key to the type library. */
912 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
913 result = E_INVALIDARG;
914 goto end;
917 /* Try and load the type library */
918 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
919 result = TYPE_E_INVALIDSTATE;
920 goto end;
923 /* remove any types registered with this typelib */
924 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
925 for (i=0; i<numTypes; i++) {
926 /* get the kind of type */
927 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
928 goto enddeleteloop;
931 /* skip non-interfaces, and get type info for the type */
932 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
933 goto enddeleteloop;
935 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
936 goto enddeleteloop;
938 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
939 goto enddeleteloop;
942 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
943 kind == TKIND_DISPATCH)
945 BOOL is_wow64;
946 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
948 TLB_unregister_interface(&typeAttr->guid, 0);
950 /* unregister TLBs into the opposite registry view, too */
951 if(opposite == KEY_WOW64_32KEY ||
952 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
953 TLB_unregister_interface(&typeAttr->guid, opposite);
957 enddeleteloop:
958 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
959 typeAttr = NULL;
960 if (typeInfo) ITypeInfo_Release(typeInfo);
961 typeInfo = NULL;
964 /* Now, delete the type library path subkey */
965 get_lcid_subkey( lcid, syskind, subKeyName );
966 RegDeleteKeyW(key, subKeyName);
967 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
968 RegDeleteKeyW(key, subKeyName);
970 /* check if there is anything besides the FLAGS/HELPDIR keys.
971 If there is, we don't delete them */
972 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
973 deleteOtherStuff = TRUE;
974 i = 0;
975 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
976 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
978 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
979 if (!strcmpW(subKeyName, FLAGSW)) continue;
980 if (!strcmpW(subKeyName, HELPDIRW)) continue;
981 deleteOtherStuff = FALSE;
982 break;
985 /* only delete the other parts of the key if we're absolutely sure */
986 if (deleteOtherStuff) {
987 RegDeleteKeyW(key, FLAGSW);
988 RegDeleteKeyW(key, HELPDIRW);
989 RegCloseKey(key);
990 key = NULL;
992 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
993 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
994 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
997 end:
998 SysFreeString(tlibPath);
999 if (typeLib) ITypeLib_Release(typeLib);
1000 if (key) RegCloseKey(key);
1001 return result;
1004 /******************************************************************************
1005 * RegisterTypeLibForUser [OLEAUT32.442]
1006 * Adds information about a type library to the user registry
1007 * NOTES
1008 * Docs: ITypeLib FAR * ptlib
1009 * Docs: OLECHAR FAR* szFullPath
1010 * Docs: OLECHAR FAR* szHelpDir
1012 * RETURNS
1013 * Success: S_OK
1014 * Failure: Status
1016 HRESULT WINAPI RegisterTypeLibForUser(
1017 ITypeLib * ptlib, /* [in] Pointer to the library*/
1018 OLECHAR * szFullPath, /* [in] full Path of the library*/
1019 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1020 may be NULL*/
1022 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1023 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1024 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1027 /******************************************************************************
1028 * UnRegisterTypeLibForUser [OLEAUT32.443]
1029 * Removes information about a type library from the user registry
1031 * RETURNS
1032 * Success: S_OK
1033 * Failure: Status
1035 HRESULT WINAPI UnRegisterTypeLibForUser(
1036 REFGUID libid, /* [in] GUID of the library */
1037 WORD wVerMajor, /* [in] major version */
1038 WORD wVerMinor, /* [in] minor version */
1039 LCID lcid, /* [in] locale id */
1040 SYSKIND syskind)
1042 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1043 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1044 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1047 /*======================= ITypeLib implementation =======================*/
1049 typedef struct tagTLBGuid {
1050 GUID guid;
1051 INT hreftype;
1052 UINT offset;
1053 struct list entry;
1054 } TLBGuid;
1056 typedef struct tagTLBCustData
1058 TLBGuid *guid;
1059 VARIANT data;
1060 struct list entry;
1061 } TLBCustData;
1063 /* data structure for import typelibs */
1064 typedef struct tagTLBImpLib
1066 int offset; /* offset in the file (MSFT)
1067 offset in nametable (SLTG)
1068 just used to identify library while reading
1069 data from file */
1070 TLBGuid *guid; /* libid */
1071 BSTR name; /* name */
1073 LCID lcid; /* lcid of imported typelib */
1075 WORD wVersionMajor; /* major version number */
1076 WORD wVersionMinor; /* minor version number */
1078 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1079 NULL if not yet loaded */
1080 struct list entry;
1081 } TLBImpLib;
1083 typedef struct tagTLBString {
1084 BSTR str;
1085 UINT offset;
1086 struct list entry;
1087 } TLBString;
1089 /* internal ITypeLib data */
1090 typedef struct tagITypeLibImpl
1092 ITypeLib2 ITypeLib2_iface;
1093 ITypeComp ITypeComp_iface;
1094 ICreateTypeLib2 ICreateTypeLib2_iface;
1095 LONG ref;
1096 TLBGuid *guid;
1097 LCID lcid;
1098 SYSKIND syskind;
1099 int ptr_size;
1100 WORD ver_major;
1101 WORD ver_minor;
1102 WORD libflags;
1103 LCID set_lcid;
1105 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1106 * exported to the application as a UNICODE string.
1108 struct list string_list;
1109 struct list name_list;
1110 struct list guid_list;
1112 const TLBString *Name;
1113 const TLBString *DocString;
1114 const TLBString *HelpFile;
1115 const TLBString *HelpStringDll;
1116 DWORD dwHelpContext;
1117 int TypeInfoCount; /* nr of typeinfo's in librarry */
1118 struct tagITypeInfoImpl **typeinfos;
1119 struct list custdata_list;
1120 struct list implib_list;
1121 int ctTypeDesc; /* number of items in type desc array */
1122 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1123 library. Only used while reading MSFT
1124 typelibs */
1125 struct list ref_list; /* list of ref types in this typelib */
1126 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1129 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1130 struct list entry;
1131 WCHAR *path;
1132 INT index;
1133 } ITypeLibImpl;
1135 static const ITypeLib2Vtbl tlbvt;
1136 static const ITypeCompVtbl tlbtcvt;
1137 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1139 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1141 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1144 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1146 return impl_from_ITypeLib2((ITypeLib2*)iface);
1149 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1151 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1154 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1156 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1159 /* ITypeLib methods */
1160 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1161 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1163 /*======================= ITypeInfo implementation =======================*/
1165 /* data for referenced types */
1166 typedef struct tagTLBRefType
1168 INT index; /* Type index for internal ref or for external ref
1169 it the format is SLTG. -2 indicates to
1170 use guid */
1172 TYPEKIND tkind;
1173 TLBGuid *guid; /* guid of the referenced type */
1174 /* if index == TLB_REF_USE_GUID */
1176 HREFTYPE reference; /* The href of this ref */
1177 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1178 TLB_REF_INTERNAL for internal refs
1179 TLB_REF_NOT_FOUND for broken refs */
1181 struct list entry;
1182 } TLBRefType;
1184 #define TLB_REF_USE_GUID -2
1186 #define TLB_REF_INTERNAL (void*)-2
1187 #define TLB_REF_NOT_FOUND (void*)-1
1189 /* internal Parameter data */
1190 typedef struct tagTLBParDesc
1192 const TLBString *Name;
1193 struct list custdata_list;
1194 } TLBParDesc;
1196 /* internal Function data */
1197 typedef struct tagTLBFuncDesc
1199 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1200 const TLBString *Name; /* the name of this function */
1201 TLBParDesc *pParamDesc; /* array with param names and custom data */
1202 int helpcontext;
1203 int HelpStringContext;
1204 const TLBString *HelpString;
1205 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1206 struct list custdata_list;
1207 } TLBFuncDesc;
1209 /* internal Variable data */
1210 typedef struct tagTLBVarDesc
1212 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1213 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1214 const TLBString *Name; /* the name of this variable */
1215 int HelpContext;
1216 int HelpStringContext;
1217 const TLBString *HelpString;
1218 struct list custdata_list;
1219 } TLBVarDesc;
1221 /* internal implemented interface data */
1222 typedef struct tagTLBImplType
1224 HREFTYPE hRef; /* hRef of interface */
1225 int implflags; /* IMPLFLAG_*s */
1226 struct list custdata_list;
1227 } TLBImplType;
1229 /* internal TypeInfo data */
1230 typedef struct tagITypeInfoImpl
1232 ITypeInfo2 ITypeInfo2_iface;
1233 ITypeComp ITypeComp_iface;
1234 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1235 LONG ref;
1236 BOOL not_attached_to_typelib;
1237 BOOL needs_layout;
1239 TLBGuid *guid;
1240 TYPEATTR typeattr;
1241 TYPEDESC *tdescAlias;
1243 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1244 int index; /* index in this typelib; */
1245 HREFTYPE hreftype; /* hreftype for app object binding */
1246 /* type libs seem to store the doc strings in ascii
1247 * so why should we do it in unicode?
1249 const TLBString *Name;
1250 const TLBString *DocString;
1251 const TLBString *DllName;
1252 const TLBString *Schema;
1253 DWORD dwHelpContext;
1254 DWORD dwHelpStringContext;
1256 /* functions */
1257 TLBFuncDesc *funcdescs;
1259 /* variables */
1260 TLBVarDesc *vardescs;
1262 /* Implemented Interfaces */
1263 TLBImplType *impltypes;
1265 struct list *pcustdata_list;
1266 struct list custdata_list;
1267 } ITypeInfoImpl;
1269 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1271 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1274 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1276 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1279 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1281 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1284 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1286 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1289 static const ITypeInfo2Vtbl tinfvt;
1290 static const ITypeCompVtbl tcompvt;
1291 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1293 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1294 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1296 typedef struct tagTLBContext
1298 unsigned int oStart; /* start of TLB in file */
1299 unsigned int pos; /* current pos */
1300 unsigned int length; /* total length */
1301 void *mapping; /* memory mapping */
1302 MSFT_SegDir * pTblDir;
1303 ITypeLibImpl* pLibInfo;
1304 } TLBContext;
1307 static inline BSTR TLB_get_bstr(const TLBString *str)
1309 return str != NULL ? str->str : NULL;
1312 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1314 if(!str)
1315 return 1;
1316 return memcmp(left, str->str, len);
1319 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1321 return guid != NULL ? &guid->guid : NULL;
1324 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1326 return guid != NULL ? &guid->guid : &GUID_NULL;
1329 static int get_ptr_size(SYSKIND syskind)
1331 switch(syskind){
1332 case SYS_WIN64:
1333 return 8;
1334 case SYS_WIN32:
1335 case SYS_MAC:
1336 case SYS_WIN16:
1337 return 4;
1339 WARN("Unhandled syskind: 0x%x\n", syskind);
1340 return 4;
1344 debug
1346 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1347 if (pTD->vt & VT_RESERVED)
1348 szVarType += strlen(strcpy(szVarType, "reserved | "));
1349 if (pTD->vt & VT_BYREF)
1350 szVarType += strlen(strcpy(szVarType, "ref to "));
1351 if (pTD->vt & VT_ARRAY)
1352 szVarType += strlen(strcpy(szVarType, "array of "));
1353 if (pTD->vt & VT_VECTOR)
1354 szVarType += strlen(strcpy(szVarType, "vector of "));
1355 switch(pTD->vt & VT_TYPEMASK) {
1356 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1357 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1358 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1359 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1360 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1361 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1362 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1363 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1364 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1365 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1366 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1367 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1368 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1369 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1370 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1371 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1372 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1373 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1374 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1375 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1376 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1377 pTD->u.hreftype); break;
1378 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1379 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1380 case VT_PTR: sprintf(szVarType, "ptr to ");
1381 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1382 break;
1383 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1384 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1385 break;
1386 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1387 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1388 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1389 break;
1391 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1395 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1396 char buf[200];
1397 USHORT flags = edesc->u.paramdesc.wParamFlags;
1398 dump_TypeDesc(&edesc->tdesc,buf);
1399 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1400 MESSAGE("\t\tu.paramdesc.wParamFlags");
1401 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1402 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1403 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1404 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1405 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1406 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1407 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1408 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1409 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1411 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1412 int i;
1413 MESSAGE("memid is %08x\n",funcdesc->memid);
1414 for (i=0;i<funcdesc->cParams;i++) {
1415 MESSAGE("Param %d:\n",i);
1416 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1418 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1419 switch (funcdesc->funckind) {
1420 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1421 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1422 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1423 case FUNC_STATIC: MESSAGE("static");break;
1424 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1425 default: MESSAGE("unknown");break;
1427 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1428 switch (funcdesc->invkind) {
1429 case INVOKE_FUNC: MESSAGE("func");break;
1430 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1431 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1432 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1434 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1435 switch (funcdesc->callconv) {
1436 case CC_CDECL: MESSAGE("cdecl");break;
1437 case CC_PASCAL: MESSAGE("pascal");break;
1438 case CC_STDCALL: MESSAGE("stdcall");break;
1439 case CC_SYSCALL: MESSAGE("syscall");break;
1440 default:break;
1442 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1443 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1444 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1446 MESSAGE("\telemdescFunc (return value type):\n");
1447 dump_ELEMDESC(&funcdesc->elemdescFunc);
1450 static const char * const typekind_desc[] =
1452 "TKIND_ENUM",
1453 "TKIND_RECORD",
1454 "TKIND_MODULE",
1455 "TKIND_INTERFACE",
1456 "TKIND_DISPATCH",
1457 "TKIND_COCLASS",
1458 "TKIND_ALIAS",
1459 "TKIND_UNION",
1460 "TKIND_MAX"
1463 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1465 int i;
1466 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1467 for (i=0;i<pfd->funcdesc.cParams;i++)
1468 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1471 dump_FUNCDESC(&(pfd->funcdesc));
1473 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1474 if(pfd->Entry == NULL)
1475 MESSAGE("\tentry: (null)\n");
1476 else if(pfd->Entry == (void*)-1)
1477 MESSAGE("\tentry: invalid\n");
1478 else if(IS_INTRESOURCE(pfd->Entry))
1479 MESSAGE("\tentry: %p\n", pfd->Entry);
1480 else
1481 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1483 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1485 while (n)
1487 dump_TLBFuncDescOne(pfd);
1488 ++pfd;
1489 --n;
1492 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1494 while (n)
1496 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1497 ++pvd;
1498 --n;
1502 static void dump_TLBImpLib(const TLBImpLib *import)
1504 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1505 debugstr_w(import->name));
1506 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1507 import->wVersionMinor, import->lcid, import->offset);
1510 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1512 TLBRefType *ref;
1514 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1516 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1517 if(ref->index == -1)
1518 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1519 else
1520 TRACE_(typelib)("type no: %d\n", ref->index);
1522 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1524 TRACE_(typelib)("in lib\n");
1525 dump_TLBImpLib(ref->pImpTLInfo);
1530 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1532 if(!impl)
1533 return;
1534 while (n) {
1535 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1536 impl->hRef, impl->implflags);
1537 ++impl;
1538 --n;
1542 static void dump_DispParms(const DISPPARAMS * pdp)
1544 unsigned int index;
1546 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1548 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1550 TRACE("named args:\n");
1551 for (index = 0; index < pdp->cNamedArgs; index++)
1552 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1555 if (pdp->cArgs && pdp->rgvarg)
1557 TRACE("args:\n");
1558 for (index = 0; index < pdp->cArgs; index++)
1559 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1563 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1565 TRACE("%p ref=%u\n", pty, pty->ref);
1566 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1567 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1568 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1569 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1570 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1571 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1572 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1573 if (TRACE_ON(ole))
1574 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1575 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1576 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1579 static void dump_VARDESC(const VARDESC *v)
1581 MESSAGE("memid %d\n",v->memid);
1582 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1583 MESSAGE("oInst %d\n",v->u.oInst);
1584 dump_ELEMDESC(&(v->elemdescVar));
1585 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1586 MESSAGE("varkind %d\n",v->varkind);
1589 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1591 /* VT_LPWSTR is largest type that, may appear in type description */
1592 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1593 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1594 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1595 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1596 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1597 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1598 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1599 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1602 static void TLB_abort(void)
1604 DebugBreak();
1607 /* returns the size required for a deep copy of a typedesc into a
1608 * flat buffer */
1609 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1611 SIZE_T size = 0;
1613 if (alloc_initial_space)
1614 size += sizeof(TYPEDESC);
1616 switch (tdesc->vt)
1618 case VT_PTR:
1619 case VT_SAFEARRAY:
1620 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1621 break;
1622 case VT_CARRAY:
1623 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1624 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1625 break;
1627 return size;
1630 /* deep copy a typedesc into a flat buffer */
1631 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1633 if (!dest)
1635 dest = buffer;
1636 buffer = (char *)buffer + sizeof(TYPEDESC);
1639 *dest = *src;
1641 switch (src->vt)
1643 case VT_PTR:
1644 case VT_SAFEARRAY:
1645 dest->u.lptdesc = buffer;
1646 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1647 break;
1648 case VT_CARRAY:
1649 dest->u.lpadesc = buffer;
1650 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1651 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1652 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1653 break;
1655 return buffer;
1658 /* free custom data allocated by MSFT_CustData */
1659 static inline void TLB_FreeCustData(struct list *custdata_list)
1661 TLBCustData *cd, *cdn;
1662 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1664 list_remove(&cd->entry);
1665 VariantClear(&cd->data);
1666 heap_free(cd);
1670 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1672 DWORD len;
1673 BSTR ret;
1675 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1676 ret = SysAllocStringLen(NULL, len - 1);
1677 if (!ret) return ret;
1678 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1679 return ret;
1682 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1683 UINT n, MEMBERID memid)
1685 while(n){
1686 if(funcdescs->funcdesc.memid == memid)
1687 return funcdescs;
1688 ++funcdescs;
1689 --n;
1691 return NULL;
1694 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1695 UINT n, MEMBERID memid)
1697 while(n){
1698 if(vardescs->vardesc.memid == memid)
1699 return vardescs;
1700 ++vardescs;
1701 --n;
1703 return NULL;
1706 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1707 UINT n, const OLECHAR *name)
1709 while(n){
1710 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1711 return vardescs;
1712 ++vardescs;
1713 --n;
1715 return NULL;
1718 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1720 TLBCustData *cust_data;
1721 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1722 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1723 return cust_data;
1724 return NULL;
1727 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1728 UINT n, const OLECHAR *name)
1730 while(n){
1731 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1732 return *typeinfos;
1733 ++typeinfos;
1734 --n;
1736 return NULL;
1739 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1741 list_init(&var_desc->custdata_list);
1744 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1746 TLBVarDesc *ret;
1748 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1749 if(!ret)
1750 return NULL;
1752 while(n){
1753 TLBVarDesc_Constructor(&ret[n-1]);
1754 --n;
1757 return ret;
1760 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1762 TLBParDesc *ret;
1764 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1765 if(!ret)
1766 return NULL;
1768 while(n){
1769 list_init(&ret[n-1].custdata_list);
1770 --n;
1773 return ret;
1776 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1778 list_init(&func_desc->custdata_list);
1781 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1783 TLBFuncDesc *ret;
1785 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1786 if(!ret)
1787 return NULL;
1789 while(n){
1790 TLBFuncDesc_Constructor(&ret[n-1]);
1791 --n;
1794 return ret;
1797 static void TLBImplType_Constructor(TLBImplType *impl)
1799 list_init(&impl->custdata_list);
1802 static TLBImplType *TLBImplType_Alloc(UINT n)
1804 TLBImplType *ret;
1806 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1807 if(!ret)
1808 return NULL;
1810 while(n){
1811 TLBImplType_Constructor(&ret[n-1]);
1812 --n;
1815 return ret;
1818 static TLBGuid *TLB_append_guid(struct list *guid_list,
1819 const GUID *new_guid, HREFTYPE hreftype)
1821 TLBGuid *guid;
1823 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1824 if (IsEqualGUID(&guid->guid, new_guid))
1825 return guid;
1828 guid = heap_alloc(sizeof(TLBGuid));
1829 if (!guid)
1830 return NULL;
1832 memcpy(&guid->guid, new_guid, sizeof(GUID));
1833 guid->hreftype = hreftype;
1835 list_add_tail(guid_list, &guid->entry);
1837 return guid;
1840 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1842 TLBCustData *cust_data;
1844 switch(V_VT(var)){
1845 case VT_I4:
1846 case VT_R4:
1847 case VT_UI4:
1848 case VT_INT:
1849 case VT_UINT:
1850 case VT_HRESULT:
1851 case VT_BSTR:
1852 break;
1853 default:
1854 return DISP_E_BADVARTYPE;
1857 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1859 if (!cust_data) {
1860 cust_data = heap_alloc(sizeof(TLBCustData));
1861 if (!cust_data)
1862 return E_OUTOFMEMORY;
1864 cust_data->guid = tlbguid;
1865 VariantInit(&cust_data->data);
1867 list_add_tail(custdata_list, &cust_data->entry);
1868 }else
1869 VariantClear(&cust_data->data);
1871 return VariantCopy(&cust_data->data, var);
1874 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1876 TLBString *str;
1878 if(!new_str)
1879 return NULL;
1881 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1882 if (strcmpW(str->str, new_str) == 0)
1883 return str;
1886 str = heap_alloc(sizeof(TLBString));
1887 if (!str)
1888 return NULL;
1890 str->str = SysAllocString(new_str);
1891 if (!str->str) {
1892 heap_free(str);
1893 return NULL;
1896 list_add_tail(string_list, &str->entry);
1898 return str;
1901 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1902 ULONG *size, WORD *align)
1904 ITypeInfo *other;
1905 TYPEATTR *attr;
1906 HRESULT hr;
1908 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1909 if(FAILED(hr))
1910 return hr;
1912 hr = ITypeInfo_GetTypeAttr(other, &attr);
1913 if(FAILED(hr)){
1914 ITypeInfo_Release(other);
1915 return hr;
1918 if(size)
1919 *size = attr->cbSizeInstance;
1920 if(align)
1921 *align = attr->cbAlignment;
1923 ITypeInfo_ReleaseTypeAttr(other, attr);
1924 ITypeInfo_Release(other);
1926 return S_OK;
1929 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1930 TYPEDESC *tdesc, ULONG *size, WORD *align)
1932 ULONG i, sub, ptr_size;
1933 HRESULT hr;
1935 ptr_size = get_ptr_size(sys);
1937 switch(tdesc->vt){
1938 case VT_VOID:
1939 *size = 0;
1940 break;
1941 case VT_I1:
1942 case VT_UI1:
1943 *size = 1;
1944 break;
1945 case VT_I2:
1946 case VT_BOOL:
1947 case VT_UI2:
1948 *size = 2;
1949 break;
1950 case VT_I4:
1951 case VT_R4:
1952 case VT_ERROR:
1953 case VT_UI4:
1954 case VT_INT:
1955 case VT_UINT:
1956 case VT_HRESULT:
1957 *size = 4;
1958 break;
1959 case VT_R8:
1960 case VT_I8:
1961 case VT_UI8:
1962 *size = 8;
1963 break;
1964 case VT_BSTR:
1965 case VT_DISPATCH:
1966 case VT_UNKNOWN:
1967 case VT_PTR:
1968 case VT_SAFEARRAY:
1969 case VT_LPSTR:
1970 case VT_LPWSTR:
1971 *size = ptr_size;
1972 break;
1973 case VT_DATE:
1974 *size = sizeof(DATE);
1975 break;
1976 case VT_VARIANT:
1977 *size = sizeof(VARIANT);
1978 #ifdef _WIN64
1979 if(sys == SYS_WIN32)
1980 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1981 #endif
1982 break;
1983 case VT_DECIMAL:
1984 *size = sizeof(DECIMAL);
1985 break;
1986 case VT_CY:
1987 *size = sizeof(CY);
1988 break;
1989 case VT_CARRAY:
1990 *size = 0;
1991 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
1992 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
1993 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
1994 if(FAILED(hr))
1995 return hr;
1996 *size *= sub;
1997 return S_OK;
1998 case VT_USERDEFINED:
1999 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2000 default:
2001 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2002 return E_FAIL;
2005 if(align){
2006 if(*size < 4)
2007 *align = *size;
2008 else
2009 *align = 4;
2012 return S_OK;
2015 /**********************************************************************
2017 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2020 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2022 if (where != DO_NOT_SEEK)
2024 where += pcx->oStart;
2025 if (where > pcx->length)
2027 /* FIXME */
2028 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2029 TLB_abort();
2031 pcx->pos = where;
2035 /* read function */
2036 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2038 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2039 pcx->pos, count, pcx->oStart, pcx->length, where);
2041 MSFT_Seek(pcx, where);
2042 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2043 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2044 pcx->pos += count;
2045 return count;
2048 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2049 LONG where )
2051 DWORD ret;
2053 ret = MSFT_Read(buffer, count, pcx, where);
2054 FromLEDWords(buffer, ret);
2056 return ret;
2059 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2060 LONG where )
2062 DWORD ret;
2064 ret = MSFT_Read(buffer, count, pcx, where);
2065 FromLEWords(buffer, ret);
2067 return ret;
2070 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2072 TLBGuid *guid;
2073 MSFT_GuidEntry entry;
2074 int offs = 0;
2076 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2077 while (1) {
2078 if (offs >= pcx->pTblDir->pGuidTab.length)
2079 return S_OK;
2081 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2083 guid = heap_alloc(sizeof(TLBGuid));
2085 guid->offset = offs;
2086 guid->guid = entry.guid;
2087 guid->hreftype = entry.hreftype;
2089 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2091 offs += sizeof(MSFT_GuidEntry);
2095 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2097 TLBGuid *ret;
2099 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2100 if(ret->offset == offset){
2101 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2102 return ret;
2106 return NULL;
2109 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2111 MSFT_NameIntro niName;
2113 if (offset < 0)
2115 ERR_(typelib)("bad offset %d\n", offset);
2116 return -1;
2119 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2120 pcx->pTblDir->pNametab.offset+offset);
2122 return niName.hreftype;
2125 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2127 char *string;
2128 MSFT_NameIntro intro;
2129 INT16 len_piece;
2130 int offs = 0, lengthInChars;
2132 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2133 while (1) {
2134 TLBString *tlbstr;
2136 if (offs >= pcx->pTblDir->pNametab.length)
2137 return S_OK;
2139 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2140 intro.namelen &= 0xFF;
2141 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2142 if(len_piece % 4)
2143 len_piece = (len_piece + 4) & ~0x3;
2144 if(len_piece < 8)
2145 len_piece = 8;
2147 string = heap_alloc(len_piece + 1);
2148 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2149 string[intro.namelen] = '\0';
2151 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2152 string, -1, NULL, 0);
2153 if (!lengthInChars) {
2154 heap_free(string);
2155 return E_UNEXPECTED;
2158 tlbstr = heap_alloc(sizeof(TLBString));
2160 tlbstr->offset = offs;
2161 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2162 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2164 heap_free(string);
2166 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2168 offs += len_piece;
2172 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2174 TLBString *tlbstr;
2176 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2177 if (tlbstr->offset == offset) {
2178 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2179 return tlbstr;
2183 return NULL;
2186 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2188 TLBString *tlbstr;
2190 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2191 if (tlbstr->offset == offset) {
2192 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2193 return tlbstr;
2197 return NULL;
2201 * read a value and fill a VARIANT structure
2203 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2205 int size;
2207 TRACE_(typelib)("\n");
2209 if(offset <0) { /* data are packed in here */
2210 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2211 V_I4(pVar) = offset & 0x3ffffff;
2212 return;
2214 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2215 pcx->pTblDir->pCustData.offset + offset );
2216 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2217 switch (V_VT(pVar)){
2218 case VT_EMPTY: /* FIXME: is this right? */
2219 case VT_NULL: /* FIXME: is this right? */
2220 case VT_I2 : /* this should not happen */
2221 case VT_I4 :
2222 case VT_R4 :
2223 case VT_ERROR :
2224 case VT_BOOL :
2225 case VT_I1 :
2226 case VT_UI1 :
2227 case VT_UI2 :
2228 case VT_UI4 :
2229 case VT_INT :
2230 case VT_UINT :
2231 case VT_VOID : /* FIXME: is this right? */
2232 case VT_HRESULT :
2233 size=4; break;
2234 case VT_R8 :
2235 case VT_CY :
2236 case VT_DATE :
2237 case VT_I8 :
2238 case VT_UI8 :
2239 case VT_DECIMAL : /* FIXME: is this right? */
2240 case VT_FILETIME :
2241 size=8;break;
2242 /* pointer types with known behaviour */
2243 case VT_BSTR :{
2244 char * ptr;
2245 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2246 if(size == -1){
2247 V_BSTR(pVar) = NULL;
2248 }else{
2249 ptr = heap_alloc_zero(size);
2250 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2251 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2252 /* FIXME: do we need a AtoW conversion here? */
2253 V_UNION(pVar, bstrVal[size])='\0';
2254 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2255 heap_free(ptr);
2258 size=-4; break;
2259 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2260 case VT_DISPATCH :
2261 case VT_VARIANT :
2262 case VT_UNKNOWN :
2263 case VT_PTR :
2264 case VT_SAFEARRAY :
2265 case VT_CARRAY :
2266 case VT_USERDEFINED :
2267 case VT_LPSTR :
2268 case VT_LPWSTR :
2269 case VT_BLOB :
2270 case VT_STREAM :
2271 case VT_STORAGE :
2272 case VT_STREAMED_OBJECT :
2273 case VT_STORED_OBJECT :
2274 case VT_BLOB_OBJECT :
2275 case VT_CF :
2276 case VT_CLSID :
2277 default:
2278 size=0;
2279 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2280 V_VT(pVar));
2283 if(size>0) /* (big|small) endian correct? */
2284 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2285 return;
2288 * create a linked list with custom data
2290 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2292 MSFT_CDGuid entry;
2293 TLBCustData* pNew;
2294 int count=0;
2296 TRACE_(typelib)("\n");
2298 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2300 while(offset >=0){
2301 count++;
2302 pNew=heap_alloc_zero(sizeof(TLBCustData));
2303 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2304 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2305 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2306 list_add_head(custdata_list, &pNew->entry);
2307 offset = entry.next;
2309 return count;
2312 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2314 if(type <0)
2315 pTd->vt=type & VT_TYPEMASK;
2316 else
2317 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2319 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2322 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2324 return (invkind == INVOKE_PROPERTYGET ||
2325 invkind == INVOKE_PROPERTYPUT ||
2326 invkind == INVOKE_PROPERTYPUTREF);
2329 static void
2330 MSFT_DoFuncs(TLBContext* pcx,
2331 ITypeInfoImpl* pTI,
2332 int cFuncs,
2333 int cVars,
2334 int offset,
2335 TLBFuncDesc** pptfd)
2338 * member information is stored in a data structure at offset
2339 * indicated by the memoffset field of the typeinfo structure
2340 * There are several distinctive parts.
2341 * The first part starts with a field that holds the total length
2342 * of this (first) part excluding this field. Then follow the records,
2343 * for each member there is one record.
2345 * The first entry is always the length of the record (including this
2346 * length word).
2347 * The rest of the record depends on the type of the member. If there is
2348 * a field indicating the member type (function, variable, interface, etc)
2349 * I have not found it yet. At this time we depend on the information
2350 * in the type info and the usual order how things are stored.
2352 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2353 * for each member;
2355 * Third is an equal sized array with file offsets to the name entry
2356 * of each member.
2358 * The fourth and last (?) part is an array with offsets to the records
2359 * in the first part of this file segment.
2362 int infolen, nameoffset, reclength, i;
2363 int recoffset = offset + sizeof(INT);
2365 char *recbuf = heap_alloc(0xffff);
2366 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2367 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2369 TRACE_(typelib)("\n");
2371 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2373 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2374 ptfd = *pptfd;
2375 for ( i = 0; i < cFuncs ; i++ )
2377 int optional;
2379 /* name, eventually add to a hash table */
2380 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2381 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2383 /* read the function information record */
2384 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2386 reclength &= 0xffff;
2388 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2390 /* size without argument data */
2391 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2392 if (pFuncRec->FKCCIC & 0x1000)
2393 optional -= pFuncRec->nrargs * sizeof(INT);
2395 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2396 ptfd->helpcontext = pFuncRec->HelpContext;
2398 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2399 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2401 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2403 if (pFuncRec->FKCCIC & 0x2000 )
2405 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2406 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2407 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2409 else
2410 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2412 else
2413 ptfd->Entry = (TLBString*)-1;
2415 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2416 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2418 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2419 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2421 /* fill the FuncDesc Structure */
2422 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2423 offset + infolen + ( i + 1) * sizeof(INT));
2425 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2426 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2427 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2428 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2429 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2430 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2431 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2433 /* nameoffset is sometimes -1 on the second half of a propget/propput
2434 * pair of functions */
2435 if ((nameoffset == -1) && (i > 0) &&
2436 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2437 TLB_is_propgetput(ptfd->funcdesc.invkind))
2438 ptfd->Name = ptfd_prev->Name;
2439 else
2440 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2442 MSFT_GetTdesc(pcx,
2443 pFuncRec->DataType,
2444 &ptfd->funcdesc.elemdescFunc.tdesc);
2446 /* do the parameters/arguments */
2447 if(pFuncRec->nrargs)
2449 int j = 0;
2450 MSFT_ParameterInfo paraminfo;
2452 ptfd->funcdesc.lprgelemdescParam =
2453 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2455 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2457 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2458 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2460 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2462 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2464 MSFT_GetTdesc(pcx,
2465 paraminfo.DataType,
2466 &elemdesc->tdesc);
2468 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2470 /* name */
2471 if (paraminfo.oName != -1)
2472 ptfd->pParamDesc[j].Name =
2473 MSFT_ReadName( pcx, paraminfo.oName );
2474 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2476 /* default value */
2477 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2478 (pFuncRec->FKCCIC & 0x1000) )
2480 INT* pInt = (INT *)((char *)pFuncRec +
2481 reclength -
2482 (pFuncRec->nrargs * 4) * sizeof(INT) );
2484 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2486 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2487 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2489 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2490 pInt[j], pcx);
2492 else
2493 elemdesc->u.paramdesc.pparamdescex = NULL;
2495 /* custom info */
2496 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2497 j*sizeof(pFuncRec->oArgCustData[0])) &&
2498 pFuncRec->FKCCIC & 0x80 )
2500 MSFT_CustData(pcx,
2501 pFuncRec->oArgCustData[j],
2502 &ptfd->pParamDesc[j].custdata_list);
2505 /* SEEK value = jump to offset,
2506 * from there jump to the end of record,
2507 * go back by (j-1) arguments
2509 MSFT_ReadLEDWords( &paraminfo ,
2510 sizeof(MSFT_ParameterInfo), pcx,
2511 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2512 * sizeof(MSFT_ParameterInfo)));
2516 /* scode is not used: archaic win16 stuff FIXME: right? */
2517 ptfd->funcdesc.cScodes = 0 ;
2518 ptfd->funcdesc.lprgscode = NULL ;
2520 ptfd_prev = ptfd;
2521 ++ptfd;
2522 recoffset += reclength;
2524 heap_free(recbuf);
2527 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2528 int cVars, int offset, TLBVarDesc ** pptvd)
2530 int infolen, nameoffset, reclength;
2531 char recbuf[256];
2532 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2533 TLBVarDesc *ptvd;
2534 int i;
2535 int recoffset;
2537 TRACE_(typelib)("\n");
2539 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2540 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2541 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2542 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2543 recoffset += offset+sizeof(INT);
2544 for(i=0;i<cVars;i++, ++ptvd){
2545 /* name, eventually add to a hash table */
2546 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2547 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2548 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2549 /* read the variable information record */
2550 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2551 reclength &= 0xff;
2552 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2554 /* optional data */
2555 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2556 ptvd->HelpContext = pVarRec->HelpContext;
2558 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2559 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2561 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2562 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2564 /* fill the VarDesc Structure */
2565 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2566 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2567 ptvd->vardesc.varkind = pVarRec->VarKind;
2568 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2569 MSFT_GetTdesc(pcx, pVarRec->DataType,
2570 &ptvd->vardesc.elemdescVar.tdesc);
2571 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2572 if(pVarRec->VarKind == VAR_CONST ){
2573 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2574 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2575 pVarRec->OffsValue, pcx);
2576 } else
2577 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2578 recoffset += reclength;
2582 /* process Implemented Interfaces of a com class */
2583 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2584 int offset)
2586 int i;
2587 MSFT_RefRecord refrec;
2588 TLBImplType *pImpl;
2590 TRACE_(typelib)("\n");
2592 pTI->impltypes = TLBImplType_Alloc(count);
2593 pImpl = pTI->impltypes;
2594 for(i=0;i<count;i++){
2595 if(offset<0) break; /* paranoia */
2596 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2597 pImpl->hRef = refrec.reftype;
2598 pImpl->implflags=refrec.flags;
2599 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2600 offset=refrec.onext;
2601 ++pImpl;
2605 #ifdef _WIN64
2606 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2607 * and some structures, and fix the alignment */
2608 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2610 if(info->typeattr.typekind == TKIND_ALIAS){
2611 switch(info->tdescAlias->vt){
2612 case VT_BSTR:
2613 case VT_DISPATCH:
2614 case VT_UNKNOWN:
2615 case VT_PTR:
2616 case VT_SAFEARRAY:
2617 case VT_LPSTR:
2618 case VT_LPWSTR:
2619 info->typeattr.cbSizeInstance = sizeof(void*);
2620 info->typeattr.cbAlignment = sizeof(void*);
2621 break;
2622 case VT_CARRAY:
2623 case VT_USERDEFINED:
2624 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2625 break;
2626 case VT_VARIANT:
2627 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2628 info->typeattr.cbAlignment = 8;
2629 default:
2630 if(info->typeattr.cbSizeInstance < sizeof(void*))
2631 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2632 else
2633 info->typeattr.cbAlignment = sizeof(void*);
2634 break;
2636 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2637 info->typeattr.typekind == TKIND_DISPATCH ||
2638 info->typeattr.typekind == TKIND_COCLASS){
2639 info->typeattr.cbSizeInstance = sizeof(void*);
2640 info->typeattr.cbAlignment = sizeof(void*);
2643 #endif
2646 * process a typeinfo record
2648 static ITypeInfoImpl * MSFT_DoTypeInfo(
2649 TLBContext *pcx,
2650 int count,
2651 ITypeLibImpl * pLibInfo)
2653 MSFT_TypeInfoBase tiBase;
2654 ITypeInfoImpl *ptiRet;
2656 TRACE_(typelib)("count=%u\n", count);
2658 ptiRet = ITypeInfoImpl_Constructor();
2659 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2660 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2662 /* this is where we are coming from */
2663 ptiRet->pTypeLib = pLibInfo;
2664 ptiRet->index=count;
2666 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2667 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2668 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2669 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2670 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2671 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2672 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2673 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2674 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2675 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2676 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2677 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2678 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2679 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2680 TYPEDESC tmp;
2681 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2682 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2683 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2686 /* FIXME: */
2687 /* IDLDESC idldescType; *//* never saw this one != zero */
2689 /* name, eventually add to a hash table */
2690 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2691 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2692 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2693 /* help info */
2694 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2695 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2696 ptiRet->dwHelpContext=tiBase.helpcontext;
2698 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2699 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2701 /* note: InfoType's Help file and HelpStringDll come from the containing
2702 * library. Further HelpString and Docstring appear to be the same thing :(
2704 /* functions */
2705 if(ptiRet->typeattr.cFuncs >0 )
2706 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2707 ptiRet->typeattr.cVars,
2708 tiBase.memoffset, &ptiRet->funcdescs);
2709 /* variables */
2710 if(ptiRet->typeattr.cVars >0 )
2711 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2712 ptiRet->typeattr.cVars,
2713 tiBase.memoffset, &ptiRet->vardescs);
2714 if(ptiRet->typeattr.cImplTypes >0 ) {
2715 switch(ptiRet->typeattr.typekind)
2717 case TKIND_COCLASS:
2718 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2719 tiBase.datatype1);
2720 break;
2721 case TKIND_DISPATCH:
2722 /* This is not -1 when the interface is a non-base dual interface or
2723 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2724 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2725 not this interface.
2728 if (tiBase.datatype1 != -1)
2730 ptiRet->impltypes = TLBImplType_Alloc(1);
2731 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2733 break;
2734 default:
2735 ptiRet->impltypes = TLBImplType_Alloc(1);
2736 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2737 break;
2740 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2742 TRACE_(typelib)("%s guid: %s kind:%s\n",
2743 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2744 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2745 typekind_desc[ptiRet->typeattr.typekind]);
2746 if (TRACE_ON(typelib))
2747 dump_TypeInfo(ptiRet);
2749 return ptiRet;
2752 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2754 char *string;
2755 INT16 len_str, len_piece;
2756 int offs = 0, lengthInChars;
2758 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2759 while (1) {
2760 TLBString *tlbstr;
2762 if (offs >= pcx->pTblDir->pStringtab.length)
2763 return S_OK;
2765 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2766 len_piece = len_str + sizeof(INT16);
2767 if(len_piece % 4)
2768 len_piece = (len_piece + 4) & ~0x3;
2769 if(len_piece < 8)
2770 len_piece = 8;
2772 string = heap_alloc(len_piece + 1);
2773 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2774 string[len_str] = '\0';
2776 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2777 string, -1, NULL, 0);
2778 if (!lengthInChars) {
2779 heap_free(string);
2780 return E_UNEXPECTED;
2783 tlbstr = heap_alloc(sizeof(TLBString));
2785 tlbstr->offset = offs;
2786 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2787 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2789 heap_free(string);
2791 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2793 offs += len_piece;
2797 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2799 TLBRefType *ref;
2800 int offs = 0;
2802 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2803 while (offs < pcx->pTblDir->pImpInfo.length) {
2804 MSFT_ImpInfo impinfo;
2805 TLBImpLib *pImpLib;
2807 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2809 ref = heap_alloc_zero(sizeof(TLBRefType));
2810 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2812 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2813 if(pImpLib->offset==impinfo.oImpFile)
2814 break;
2816 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2817 ref->reference = offs;
2818 ref->pImpTLInfo = pImpLib;
2819 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2820 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2821 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2822 ref->index = TLB_REF_USE_GUID;
2823 } else
2824 ref->index = impinfo.oGuid;
2825 }else{
2826 ERR("Cannot find a reference\n");
2827 ref->reference = -1;
2828 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2831 offs += sizeof(impinfo);
2834 return S_OK;
2837 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2838 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2839 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2840 * tradeoff here.
2842 static struct list tlb_cache = LIST_INIT(tlb_cache);
2843 static CRITICAL_SECTION cache_section;
2844 static CRITICAL_SECTION_DEBUG cache_section_debug =
2846 0, 0, &cache_section,
2847 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2848 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2850 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2853 typedef struct TLB_PEFile
2855 IUnknown IUnknown_iface;
2856 LONG refs;
2857 HMODULE dll;
2858 HRSRC typelib_resource;
2859 HGLOBAL typelib_global;
2860 LPVOID typelib_base;
2861 } TLB_PEFile;
2863 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2865 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2868 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2870 if (IsEqualIID(riid, &IID_IUnknown))
2872 *ppv = iface;
2873 IUnknown_AddRef(iface);
2874 return S_OK;
2876 *ppv = NULL;
2877 return E_NOINTERFACE;
2880 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2882 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2883 return InterlockedIncrement(&This->refs);
2886 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2888 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2889 ULONG refs = InterlockedDecrement(&This->refs);
2890 if (!refs)
2892 if (This->typelib_global)
2893 FreeResource(This->typelib_global);
2894 if (This->dll)
2895 FreeLibrary(This->dll);
2896 heap_free(This);
2898 return refs;
2901 static const IUnknownVtbl TLB_PEFile_Vtable =
2903 TLB_PEFile_QueryInterface,
2904 TLB_PEFile_AddRef,
2905 TLB_PEFile_Release
2908 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2910 TLB_PEFile *This;
2911 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2913 This = heap_alloc(sizeof(TLB_PEFile));
2914 if (!This)
2915 return E_OUTOFMEMORY;
2917 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2918 This->refs = 1;
2919 This->dll = NULL;
2920 This->typelib_resource = NULL;
2921 This->typelib_global = NULL;
2922 This->typelib_base = NULL;
2924 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2925 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2927 if (This->dll)
2929 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2930 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2931 if (This->typelib_resource)
2933 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2934 if (This->typelib_global)
2936 This->typelib_base = LockResource(This->typelib_global);
2938 if (This->typelib_base)
2940 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2941 *ppBase = This->typelib_base;
2942 *ppFile = &This->IUnknown_iface;
2943 return S_OK;
2948 TRACE("No TYPELIB resource found\n");
2949 hr = E_FAIL;
2952 TLB_PEFile_Release(&This->IUnknown_iface);
2953 return hr;
2956 typedef struct TLB_NEFile
2958 IUnknown IUnknown_iface;
2959 LONG refs;
2960 LPVOID typelib_base;
2961 } TLB_NEFile;
2963 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2965 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2968 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2970 if (IsEqualIID(riid, &IID_IUnknown))
2972 *ppv = iface;
2973 IUnknown_AddRef(iface);
2974 return S_OK;
2976 *ppv = NULL;
2977 return E_NOINTERFACE;
2980 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2982 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2983 return InterlockedIncrement(&This->refs);
2986 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2988 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2989 ULONG refs = InterlockedDecrement(&This->refs);
2990 if (!refs)
2992 heap_free(This->typelib_base);
2993 heap_free(This);
2995 return refs;
2998 static const IUnknownVtbl TLB_NEFile_Vtable =
3000 TLB_NEFile_QueryInterface,
3001 TLB_NEFile_AddRef,
3002 TLB_NEFile_Release
3005 /***********************************************************************
3006 * read_xx_header [internal]
3008 static int read_xx_header( HFILE lzfd )
3010 IMAGE_DOS_HEADER mzh;
3011 char magic[3];
3013 LZSeek( lzfd, 0, SEEK_SET );
3014 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3015 return 0;
3016 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3017 return 0;
3019 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3020 if ( 2 != LZRead( lzfd, magic, 2 ) )
3021 return 0;
3023 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3025 if ( magic[0] == 'N' && magic[1] == 'E' )
3026 return IMAGE_OS2_SIGNATURE;
3027 if ( magic[0] == 'P' && magic[1] == 'E' )
3028 return IMAGE_NT_SIGNATURE;
3030 magic[2] = '\0';
3031 WARN("Can't handle %s files.\n", magic );
3032 return 0;
3036 /***********************************************************************
3037 * find_ne_resource [internal]
3039 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3040 DWORD *resLen, DWORD *resOff )
3042 IMAGE_OS2_HEADER nehd;
3043 NE_TYPEINFO *typeInfo;
3044 NE_NAMEINFO *nameInfo;
3045 DWORD nehdoffset;
3046 LPBYTE resTab;
3047 DWORD resTabSize;
3048 int count;
3050 /* Read in NE header */
3051 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3052 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3054 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3055 if ( !resTabSize )
3057 TRACE("No resources in NE dll\n" );
3058 return FALSE;
3061 /* Read in resource table */
3062 resTab = heap_alloc( resTabSize );
3063 if ( !resTab ) return FALSE;
3065 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3066 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3068 heap_free( resTab );
3069 return FALSE;
3072 /* Find resource */
3073 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3075 if (!IS_INTRESOURCE(typeid)) /* named type */
3077 BYTE len = strlen( typeid );
3078 while (typeInfo->type_id)
3080 if (!(typeInfo->type_id & 0x8000))
3082 BYTE *p = resTab + typeInfo->type_id;
3083 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3085 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3086 typeInfo->count * sizeof(NE_NAMEINFO));
3089 else /* numeric type id */
3091 WORD id = LOWORD(typeid) | 0x8000;
3092 while (typeInfo->type_id)
3094 if (typeInfo->type_id == id) goto found_type;
3095 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3096 typeInfo->count * sizeof(NE_NAMEINFO));
3099 TRACE("No typeid entry found for %p\n", typeid );
3100 heap_free( resTab );
3101 return FALSE;
3103 found_type:
3104 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3106 if (!IS_INTRESOURCE(resid)) /* named resource */
3108 BYTE len = strlen( resid );
3109 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3111 BYTE *p = resTab + nameInfo->id;
3112 if (nameInfo->id & 0x8000) continue;
3113 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3116 else /* numeric resource id */
3118 WORD id = LOWORD(resid) | 0x8000;
3119 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3120 if (nameInfo->id == id) goto found_name;
3122 TRACE("No resid entry found for %p\n", typeid );
3123 heap_free( resTab );
3124 return FALSE;
3126 found_name:
3127 /* Return resource data */
3128 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3129 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3131 heap_free( resTab );
3132 return TRUE;
3135 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3137 HFILE lzfd = -1;
3138 OFSTRUCT ofs;
3139 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3140 TLB_NEFile *This;
3142 This = heap_alloc(sizeof(TLB_NEFile));
3143 if (!This) return E_OUTOFMEMORY;
3145 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3146 This->refs = 1;
3147 This->typelib_base = NULL;
3149 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3150 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3152 DWORD reslen, offset;
3153 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3155 This->typelib_base = heap_alloc(reslen);
3156 if( !This->typelib_base )
3157 hr = E_OUTOFMEMORY;
3158 else
3160 LZSeek( lzfd, offset, SEEK_SET );
3161 reslen = LZRead( lzfd, This->typelib_base, reslen );
3162 LZClose( lzfd );
3163 *ppBase = This->typelib_base;
3164 *pdwTLBLength = reslen;
3165 *ppFile = &This->IUnknown_iface;
3166 return S_OK;
3171 if( lzfd >= 0) LZClose( lzfd );
3172 TLB_NEFile_Release(&This->IUnknown_iface);
3173 return hr;
3176 typedef struct TLB_Mapping
3178 IUnknown IUnknown_iface;
3179 LONG refs;
3180 HANDLE file;
3181 HANDLE mapping;
3182 LPVOID typelib_base;
3183 } TLB_Mapping;
3185 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3187 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3190 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3192 if (IsEqualIID(riid, &IID_IUnknown))
3194 *ppv = iface;
3195 IUnknown_AddRef(iface);
3196 return S_OK;
3198 *ppv = NULL;
3199 return E_NOINTERFACE;
3202 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3204 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3205 return InterlockedIncrement(&This->refs);
3208 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3210 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3211 ULONG refs = InterlockedDecrement(&This->refs);
3212 if (!refs)
3214 if (This->typelib_base)
3215 UnmapViewOfFile(This->typelib_base);
3216 if (This->mapping)
3217 CloseHandle(This->mapping);
3218 if (This->file != INVALID_HANDLE_VALUE)
3219 CloseHandle(This->file);
3220 heap_free(This);
3222 return refs;
3225 static const IUnknownVtbl TLB_Mapping_Vtable =
3227 TLB_Mapping_QueryInterface,
3228 TLB_Mapping_AddRef,
3229 TLB_Mapping_Release
3232 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3234 TLB_Mapping *This;
3236 This = heap_alloc(sizeof(TLB_Mapping));
3237 if (!This)
3238 return E_OUTOFMEMORY;
3240 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3241 This->refs = 1;
3242 This->file = INVALID_HANDLE_VALUE;
3243 This->mapping = NULL;
3244 This->typelib_base = NULL;
3246 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3247 if (INVALID_HANDLE_VALUE != This->file)
3249 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3250 if (This->mapping)
3252 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3253 if(This->typelib_base)
3255 /* retrieve file size */
3256 *pdwTLBLength = GetFileSize(This->file, NULL);
3257 *ppBase = This->typelib_base;
3258 *ppFile = &This->IUnknown_iface;
3259 return S_OK;
3264 IUnknown_Release(&This->IUnknown_iface);
3265 return TYPE_E_CANTLOADLIBRARY;
3268 /****************************************************************************
3269 * TLB_ReadTypeLib
3271 * find the type of the typelib file and map the typelib resource into
3272 * the memory
3275 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3276 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3278 ITypeLibImpl *entry;
3279 HRESULT ret;
3280 INT index = 1;
3281 LPWSTR index_str, file = (LPWSTR)pszFileName;
3282 LPVOID pBase = NULL;
3283 DWORD dwTLBLength = 0;
3284 IUnknown *pFile = NULL;
3285 HANDLE h;
3287 *ppTypeLib = NULL;
3289 index_str = strrchrW(pszFileName, '\\');
3290 if(index_str && *++index_str != '\0')
3292 LPWSTR end_ptr;
3293 LONG idx = strtolW(index_str, &end_ptr, 10);
3294 if(*end_ptr == '\0')
3296 int str_len = index_str - pszFileName - 1;
3297 index = idx;
3298 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3299 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3300 file[str_len] = 0;
3304 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3306 if(strchrW(file, '\\'))
3308 lstrcpyW(pszPath, file);
3310 else
3312 int len = GetSystemDirectoryW(pszPath, cchPath);
3313 pszPath[len] = '\\';
3314 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3318 if(file != pszFileName) heap_free(file);
3320 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3321 if(h != INVALID_HANDLE_VALUE){
3322 FILE_NAME_INFORMATION size_info;
3323 BOOL br;
3325 /* GetFileInformationByHandleEx returns the path of the file without
3326 * WOW64 redirection */
3327 br = GetFileInformationByHandleEx(h, FileNameInfo, &size_info, sizeof(size_info));
3328 if(br || GetLastError() == ERROR_MORE_DATA){
3329 FILE_NAME_INFORMATION *info;
3330 DWORD size = sizeof(*info) + size_info.FileNameLength + sizeof(WCHAR);
3332 info = HeapAlloc(GetProcessHeap(), 0, size);
3334 br = GetFileInformationByHandleEx(h, FileNameInfo, info, size);
3335 if(br){
3336 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3337 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3340 HeapFree(GetProcessHeap(), 0, info);
3343 CloseHandle(h);
3346 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3348 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3349 EnterCriticalSection(&cache_section);
3350 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3352 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3354 TRACE("cache hit\n");
3355 *ppTypeLib = &entry->ITypeLib2_iface;
3356 ITypeLib2_AddRef(*ppTypeLib);
3357 LeaveCriticalSection(&cache_section);
3358 return S_OK;
3361 LeaveCriticalSection(&cache_section);
3363 /* now actually load and parse the typelib */
3365 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3366 if (ret == TYPE_E_CANTLOADLIBRARY)
3367 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3368 if (ret == TYPE_E_CANTLOADLIBRARY)
3369 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3370 if (SUCCEEDED(ret))
3372 if (dwTLBLength >= 4)
3374 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3375 if (dwSignature == MSFT_SIGNATURE)
3376 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3377 else if (dwSignature == SLTG_SIGNATURE)
3378 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3379 else
3381 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3382 ret = TYPE_E_CANTLOADLIBRARY;
3385 else
3386 ret = TYPE_E_CANTLOADLIBRARY;
3387 IUnknown_Release(pFile);
3390 if(*ppTypeLib) {
3391 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3393 TRACE("adding to cache\n");
3394 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3395 lstrcpyW(impl->path, pszPath);
3396 /* We should really canonicalise the path here. */
3397 impl->index = index;
3399 /* FIXME: check if it has added already in the meantime */
3400 EnterCriticalSection(&cache_section);
3401 list_add_head(&tlb_cache, &impl->entry);
3402 LeaveCriticalSection(&cache_section);
3403 ret = S_OK;
3405 else
3407 if(ret != E_FAIL)
3408 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3410 ret = TYPE_E_CANTLOADLIBRARY;
3414 return ret;
3417 /*================== ITypeLib(2) Methods ===================================*/
3419 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3421 ITypeLibImpl* pTypeLibImpl;
3423 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3424 if (!pTypeLibImpl) return NULL;
3426 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3427 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3428 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3429 pTypeLibImpl->ref = 1;
3431 list_init(&pTypeLibImpl->implib_list);
3432 list_init(&pTypeLibImpl->custdata_list);
3433 list_init(&pTypeLibImpl->name_list);
3434 list_init(&pTypeLibImpl->string_list);
3435 list_init(&pTypeLibImpl->guid_list);
3436 list_init(&pTypeLibImpl->ref_list);
3437 pTypeLibImpl->dispatch_href = -1;
3439 return pTypeLibImpl;
3442 /****************************************************************************
3443 * ITypeLib2_Constructor_MSFT
3445 * loading an MSFT typelib from an in-memory image
3447 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3449 TLBContext cx;
3450 LONG lPSegDir;
3451 MSFT_Header tlbHeader;
3452 MSFT_SegDir tlbSegDir;
3453 ITypeLibImpl * pTypeLibImpl;
3454 int i;
3456 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3458 pTypeLibImpl = TypeLibImpl_Constructor();
3459 if (!pTypeLibImpl) return NULL;
3461 /* get pointer to beginning of typelib data */
3462 cx.pos = 0;
3463 cx.oStart=0;
3464 cx.mapping = pLib;
3465 cx.pLibInfo = pTypeLibImpl;
3466 cx.length = dwTLBLength;
3468 /* read header */
3469 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3470 TRACE_(typelib)("header:\n");
3471 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3472 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3473 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3474 return NULL;
3476 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3478 /* there is a small amount of information here until the next important
3479 * part:
3480 * the segment directory . Try to calculate the amount of data */
3481 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3483 /* now read the segment directory */
3484 TRACE("read segment directory (at %d)\n",lPSegDir);
3485 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3486 cx.pTblDir = &tlbSegDir;
3488 /* just check two entries */
3489 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3491 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3492 heap_free(pTypeLibImpl);
3493 return NULL;
3496 MSFT_ReadAllNames(&cx);
3497 MSFT_ReadAllStrings(&cx);
3498 MSFT_ReadAllGuids(&cx);
3500 /* now fill our internal data */
3501 /* TLIBATTR fields */
3502 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3504 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3505 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3506 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3507 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3508 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3510 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3511 pTypeLibImpl->lcid = tlbHeader.lcid;
3513 /* name, eventually add to a hash table */
3514 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3516 /* help info */
3517 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3518 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3520 if( tlbHeader.varflags & HELPDLLFLAG)
3522 int offset;
3523 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3524 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3527 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3529 /* custom data */
3530 if(tlbHeader.CustomDataOffset >= 0)
3532 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3535 /* fill in type descriptions */
3536 if(tlbSegDir.pTypdescTab.length > 0)
3538 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3539 INT16 td[4];
3540 pTypeLibImpl->ctTypeDesc = cTD;
3541 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3542 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3543 for(i=0; i<cTD; )
3545 /* FIXME: add several sanity checks here */
3546 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3547 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3549 /* FIXME: check safearray */
3550 if(td[3] < 0)
3551 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3552 else
3553 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3555 else if(td[0] == VT_CARRAY)
3557 /* array descr table here */
3558 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3560 else if(td[0] == VT_USERDEFINED)
3562 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3564 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3567 /* second time around to fill the array subscript info */
3568 for(i=0;i<cTD;i++)
3570 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3571 if(tlbSegDir.pArrayDescriptions.offset>0)
3573 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3574 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3576 if(td[1]<0)
3577 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3578 else
3579 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3581 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3583 for(j = 0; j<td[2]; j++)
3585 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3586 sizeof(INT), &cx, DO_NOT_SEEK);
3587 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3588 sizeof(INT), &cx, DO_NOT_SEEK);
3591 else
3593 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3594 ERR("didn't find array description data\n");
3599 /* imported type libs */
3600 if(tlbSegDir.pImpFiles.offset>0)
3602 TLBImpLib *pImpLib;
3603 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3604 UINT16 size;
3606 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3608 char *name;
3610 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3611 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3612 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3614 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3615 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3616 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3617 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3619 size >>= 2;
3620 name = heap_alloc_zero(size+1);
3621 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3622 pImpLib->name = TLB_MultiByteToBSTR(name);
3623 heap_free(name);
3625 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3626 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3628 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3632 MSFT_ReadAllRefs(&cx);
3634 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3636 /* type infos */
3637 if(tlbHeader.nrtypeinfos >= 0 )
3639 ITypeInfoImpl **ppTI;
3641 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3643 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3645 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3647 ++ppTI;
3648 (pTypeLibImpl->TypeInfoCount)++;
3652 #ifdef _WIN64
3653 if(pTypeLibImpl->syskind == SYS_WIN32){
3654 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3655 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3657 #endif
3659 TRACE("(%p)\n", pTypeLibImpl);
3660 return &pTypeLibImpl->ITypeLib2_iface;
3664 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3666 char b[3];
3667 int i;
3668 short s;
3670 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3671 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3672 return FALSE;
3675 guid->Data4[0] = s >> 8;
3676 guid->Data4[1] = s & 0xff;
3678 b[2] = '\0';
3679 for(i = 0; i < 6; i++) {
3680 memcpy(b, str + 24 + 2 * i, 2);
3681 guid->Data4[i + 2] = strtol(b, NULL, 16);
3683 return TRUE;
3686 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3688 WORD bytelen;
3689 DWORD len;
3690 BSTR tmp_str;
3692 *pStr = NULL;
3693 bytelen = *(const WORD*)ptr;
3694 if(bytelen == 0xffff) return 2;
3696 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3697 tmp_str = SysAllocStringLen(NULL, len);
3698 if (tmp_str) {
3699 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3700 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3701 SysFreeString(tmp_str);
3703 return bytelen + 2;
3706 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3708 WORD bytelen;
3710 *str = NULL;
3711 bytelen = *(const WORD*)ptr;
3712 if(bytelen == 0xffff) return 2;
3713 *str = heap_alloc(bytelen + 1);
3714 memcpy(*str, ptr + 2, bytelen);
3715 (*str)[bytelen] = '\0';
3716 return bytelen + 2;
3719 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3721 BSTR tmp_str;
3722 TLBString *tlbstr;
3724 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3725 if (tlbstr->offset == offset)
3726 return tlbstr;
3729 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3730 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3731 SysFreeString(tmp_str);
3733 return tlbstr;
3736 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3738 char *ptr = pLibBlk;
3739 WORD w;
3741 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3742 FIXME("libblk magic = %04x\n", w);
3743 return 0;
3746 ptr += 6;
3747 if((w = *(WORD*)ptr) != 0xffff) {
3748 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3749 ptr += w;
3751 ptr += 2;
3753 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3755 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3757 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3758 ptr += 4;
3760 pTypeLibImpl->syskind = *(WORD*)ptr;
3761 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3762 ptr += 2;
3764 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3765 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3766 else
3767 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3768 ptr += 2;
3770 ptr += 4; /* skip res12 */
3772 pTypeLibImpl->libflags = *(WORD*)ptr;
3773 ptr += 2;
3775 pTypeLibImpl->ver_major = *(WORD*)ptr;
3776 ptr += 2;
3778 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3779 ptr += 2;
3781 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3782 ptr += sizeof(GUID);
3784 return ptr - (char*)pLibBlk;
3787 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3788 typedef struct
3790 unsigned int num;
3791 HREFTYPE refs[1];
3792 } sltg_ref_lookup_t;
3794 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3795 HREFTYPE *typelib_ref)
3797 if(table && typeinfo_ref < table->num)
3799 *typelib_ref = table->refs[typeinfo_ref];
3800 return S_OK;
3803 ERR_(typelib)("Unable to find reference\n");
3804 *typelib_ref = -1;
3805 return E_FAIL;
3808 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3810 BOOL done = FALSE;
3812 while(!done) {
3813 if((*pType & 0xe00) == 0xe00) {
3814 pTD->vt = VT_PTR;
3815 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3816 pTD = pTD->u.lptdesc;
3818 switch(*pType & 0x3f) {
3819 case VT_PTR:
3820 pTD->vt = VT_PTR;
3821 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3822 pTD = pTD->u.lptdesc;
3823 break;
3825 case VT_USERDEFINED:
3826 pTD->vt = VT_USERDEFINED;
3827 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3828 done = TRUE;
3829 break;
3831 case VT_CARRAY:
3833 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3834 array */
3836 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3838 pTD->vt = VT_CARRAY;
3839 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3840 pTD->u.lpadesc->cDims = pSA->cDims;
3841 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3842 pSA->cDims * sizeof(SAFEARRAYBOUND));
3844 pTD = &pTD->u.lpadesc->tdescElem;
3845 break;
3848 case VT_SAFEARRAY:
3850 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3851 useful? */
3853 pType++;
3854 pTD->vt = VT_SAFEARRAY;
3855 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3856 pTD = pTD->u.lptdesc;
3857 break;
3859 default:
3860 pTD->vt = *pType & 0x3f;
3861 done = TRUE;
3862 break;
3864 pType++;
3866 return pType;
3869 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3870 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3872 /* Handle [in/out] first */
3873 if((*pType & 0xc000) == 0xc000)
3874 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3875 else if(*pType & 0x8000)
3876 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3877 else if(*pType & 0x4000)
3878 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3879 else
3880 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3882 if(*pType & 0x2000)
3883 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3885 if(*pType & 0x80)
3886 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3888 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3892 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3893 char *pNameTable)
3895 unsigned int ref;
3896 char *name;
3897 TLBRefType *ref_type;
3898 sltg_ref_lookup_t *table;
3899 HREFTYPE typelib_ref;
3901 if(pRef->magic != SLTG_REF_MAGIC) {
3902 FIXME("Ref magic = %x\n", pRef->magic);
3903 return NULL;
3905 name = ( (char*)pRef->names + pRef->number);
3907 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3908 table->num = pRef->number >> 3;
3910 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3912 /* We don't want the first href to be 0 */
3913 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3915 for(ref = 0; ref < pRef->number >> 3; ref++) {
3916 char *refname;
3917 unsigned int lib_offs, type_num;
3919 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3921 name += SLTG_ReadStringA(name, &refname);
3922 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3923 FIXME_(typelib)("Can't sscanf ref\n");
3924 if(lib_offs != 0xffff) {
3925 TLBImpLib *import;
3927 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3928 if(import->offset == lib_offs)
3929 break;
3931 if(&import->entry == &pTL->implib_list) {
3932 char fname[MAX_PATH+1];
3933 int len;
3934 GUID tmpguid;
3936 import = heap_alloc_zero(sizeof(*import));
3937 import->offset = lib_offs;
3938 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3939 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3940 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3941 &import->wVersionMajor,
3942 &import->wVersionMinor,
3943 &import->lcid, fname) != 4) {
3944 FIXME_(typelib)("can't sscanf ref %s\n",
3945 pNameTable + lib_offs + 40);
3947 len = strlen(fname);
3948 if(fname[len-1] != '#')
3949 FIXME("fname = %s\n", fname);
3950 fname[len-1] = '\0';
3951 import->name = TLB_MultiByteToBSTR(fname);
3952 list_add_tail(&pTL->implib_list, &import->entry);
3954 ref_type->pImpTLInfo = import;
3956 /* Store a reference to IDispatch */
3957 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3958 pTL->dispatch_href = typelib_ref;
3960 } else { /* internal ref */
3961 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3963 ref_type->reference = typelib_ref;
3964 ref_type->index = type_num;
3966 heap_free(refname);
3967 list_add_tail(&pTL->ref_list, &ref_type->entry);
3969 table->refs[ref] = typelib_ref;
3970 typelib_ref += 4;
3972 if((BYTE)*name != SLTG_REF_MAGIC)
3973 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3974 dump_TLBRefType(pTL);
3975 return table;
3978 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3979 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3981 SLTG_ImplInfo *info;
3982 TLBImplType *pImplType;
3983 /* I don't really get this structure, usually it's 0x16 bytes
3984 long, but iuser.tlb contains some that are 0x18 bytes long.
3985 That's ok because we can use the next ptr to jump to the next
3986 one. But how do we know the length of the last one? The WORD
3987 at offs 0x8 might be the clue. For now I'm just assuming that
3988 the last one is the regular 0x16 bytes. */
3990 info = (SLTG_ImplInfo*)pBlk;
3991 while(1){
3992 pTI->typeattr.cImplTypes++;
3993 if(info->next == 0xffff)
3994 break;
3995 info = (SLTG_ImplInfo*)(pBlk + info->next);
3998 info = (SLTG_ImplInfo*)pBlk;
3999 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
4000 pImplType = pTI->impltypes;
4001 while(1) {
4002 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4003 pImplType->implflags = info->impltypeflags;
4004 ++pImplType;
4006 if(info->next == 0xffff)
4007 break;
4008 if(OneOnly)
4009 FIXME_(typelib)("Interface inheriting more than one interface\n");
4010 info = (SLTG_ImplInfo*)(pBlk + info->next);
4012 info++; /* see comment at top of function */
4013 return (char*)info;
4016 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4017 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4019 TLBVarDesc *pVarDesc;
4020 const TLBString *prevName = NULL;
4021 SLTG_Variable *pItem;
4022 unsigned short i;
4023 WORD *pType;
4025 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4027 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4028 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4030 pVarDesc->vardesc.memid = pItem->memid;
4032 if (pItem->magic != SLTG_VAR_MAGIC &&
4033 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4034 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4035 return;
4038 if (pItem->name == 0xfffe)
4039 pVarDesc->Name = prevName;
4040 else
4041 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4043 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4044 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4045 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4047 if(pItem->flags & 0x02)
4048 pType = &pItem->type;
4049 else
4050 pType = (WORD*)(pBlk + pItem->type);
4052 if (pItem->flags & ~0xda)
4053 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4055 SLTG_DoElem(pType, pBlk,
4056 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4058 if (TRACE_ON(typelib)) {
4059 char buf[300];
4060 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4061 TRACE_(typelib)("elemdescVar: %s\n", buf);
4064 if (pItem->flags & 0x40) {
4065 TRACE_(typelib)("VAR_DISPATCH\n");
4066 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4068 else if (pItem->flags & 0x10) {
4069 TRACE_(typelib)("VAR_CONST\n");
4070 pVarDesc->vardesc.varkind = VAR_CONST;
4071 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4072 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4073 if (pItem->flags & 0x08)
4074 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4075 else {
4076 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4078 case VT_LPSTR:
4079 case VT_LPWSTR:
4080 case VT_BSTR:
4082 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4083 BSTR str;
4084 TRACE_(typelib)("len = %u\n", len);
4085 if (len == 0xffff) {
4086 str = NULL;
4087 } else {
4088 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4089 str = SysAllocStringLen(NULL, alloc_len);
4090 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4092 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4093 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4094 break;
4096 case VT_I2:
4097 case VT_UI2:
4098 case VT_I4:
4099 case VT_UI4:
4100 case VT_INT:
4101 case VT_UINT:
4102 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4103 *(INT*)(pBlk + pItem->byte_offs);
4104 break;
4105 default:
4106 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4110 else {
4111 TRACE_(typelib)("VAR_PERINSTANCE\n");
4112 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4113 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4116 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4117 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4119 if (pItem->flags & 0x80)
4120 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4122 prevName = pVarDesc->Name;
4124 pTI->typeattr.cVars = cVars;
4127 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4128 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4130 SLTG_Function *pFunc;
4131 unsigned short i;
4132 TLBFuncDesc *pFuncDesc;
4134 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4136 pFuncDesc = pTI->funcdescs;
4137 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4138 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4140 int param;
4141 WORD *pType, *pArg;
4143 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4144 case SLTG_FUNCTION_MAGIC:
4145 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4146 break;
4147 case SLTG_DISPATCH_FUNCTION_MAGIC:
4148 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4149 break;
4150 case SLTG_STATIC_FUNCTION_MAGIC:
4151 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4152 break;
4153 default:
4154 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4155 continue;
4157 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4159 pFuncDesc->funcdesc.memid = pFunc->dispid;
4160 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4161 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4162 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4163 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4164 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4166 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4167 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4169 if(pFunc->retnextopt & 0x80)
4170 pType = &pFunc->rettype;
4171 else
4172 pType = (WORD*)(pBlk + pFunc->rettype);
4174 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4176 pFuncDesc->funcdesc.lprgelemdescParam =
4177 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4178 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4180 pArg = (WORD*)(pBlk + pFunc->arg_off);
4182 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4183 char *paramName = pNameTable + *pArg;
4184 BOOL HaveOffs;
4185 /* If arg type follows then paramName points to the 2nd
4186 letter of the name, else the next WORD is an offset to
4187 the arg type and paramName points to the first letter.
4188 So let's take one char off paramName and see if we're
4189 pointing at an alpha-numeric char. However if *pArg is
4190 0xffff or 0xfffe then the param has no name, the former
4191 meaning that the next WORD is the type, the latter
4192 meaning that the next WORD is an offset to the type. */
4194 HaveOffs = FALSE;
4195 if(*pArg == 0xffff)
4196 paramName = NULL;
4197 else if(*pArg == 0xfffe) {
4198 paramName = NULL;
4199 HaveOffs = TRUE;
4201 else if(paramName[-1] && !isalnum(paramName[-1]))
4202 HaveOffs = TRUE;
4204 pArg++;
4206 if(HaveOffs) { /* the next word is an offset to type */
4207 pType = (WORD*)(pBlk + *pArg);
4208 SLTG_DoElem(pType, pBlk,
4209 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4210 pArg++;
4211 } else {
4212 if(paramName)
4213 paramName--;
4214 pArg = SLTG_DoElem(pArg, pBlk,
4215 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4218 /* Are we an optional param ? */
4219 if(pFuncDesc->funcdesc.cParams - param <=
4220 pFuncDesc->funcdesc.cParamsOpt)
4221 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4223 if(paramName) {
4224 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4225 paramName - pNameTable, pTI->pTypeLib);
4226 } else {
4227 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4231 pTI->typeattr.cFuncs = cFuncs;
4234 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4235 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4236 SLTG_TypeInfoTail *pTITail)
4238 char *pFirstItem;
4239 sltg_ref_lookup_t *ref_lookup = NULL;
4241 if(pTIHeader->href_table != 0xffffffff) {
4242 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4243 pNameTable);
4246 pFirstItem = pBlk;
4248 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4249 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4251 heap_free(ref_lookup);
4255 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4256 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4257 const SLTG_TypeInfoTail *pTITail)
4259 char *pFirstItem;
4260 sltg_ref_lookup_t *ref_lookup = NULL;
4262 if(pTIHeader->href_table != 0xffffffff) {
4263 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4264 pNameTable);
4267 pFirstItem = pBlk;
4269 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4270 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4273 if (pTITail->funcs_off != 0xffff)
4274 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4276 heap_free(ref_lookup);
4278 if (TRACE_ON(typelib))
4279 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4282 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4283 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4284 const SLTG_TypeInfoTail *pTITail)
4286 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4289 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4290 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4291 const SLTG_TypeInfoTail *pTITail)
4293 WORD *pType;
4294 sltg_ref_lookup_t *ref_lookup = NULL;
4296 if (pTITail->simple_alias) {
4297 /* if simple alias, no more processing required */
4298 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4299 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4300 return;
4303 if(pTIHeader->href_table != 0xffffffff) {
4304 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4305 pNameTable);
4308 /* otherwise it is an offset to a type */
4309 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4311 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4312 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4314 heap_free(ref_lookup);
4317 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4318 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4319 const SLTG_TypeInfoTail *pTITail)
4321 sltg_ref_lookup_t *ref_lookup = NULL;
4322 if (pTIHeader->href_table != 0xffffffff)
4323 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4324 pNameTable);
4326 if (pTITail->vars_off != 0xffff)
4327 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4329 if (pTITail->funcs_off != 0xffff)
4330 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4332 if (pTITail->impls_off != 0xffff)
4333 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4335 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4336 * of dispinterface functions including the IDispatch ones, so
4337 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4338 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4340 heap_free(ref_lookup);
4341 if (TRACE_ON(typelib))
4342 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4345 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4346 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4347 const SLTG_TypeInfoTail *pTITail)
4349 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4352 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4353 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4354 const SLTG_TypeInfoTail *pTITail)
4356 sltg_ref_lookup_t *ref_lookup = NULL;
4357 if (pTIHeader->href_table != 0xffffffff)
4358 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4359 pNameTable);
4361 if (pTITail->vars_off != 0xffff)
4362 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4364 if (pTITail->funcs_off != 0xffff)
4365 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4366 heap_free(ref_lookup);
4367 if (TRACE_ON(typelib))
4368 dump_TypeInfo(pTI);
4371 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4372 manageable copy of it into this */
4373 typedef struct {
4374 WORD small_no;
4375 char *index_name;
4376 char *other_name;
4377 WORD res1a;
4378 WORD name_offs;
4379 WORD more_bytes;
4380 char *extra;
4381 WORD res20;
4382 DWORD helpcontext;
4383 WORD res26;
4384 GUID uuid;
4385 } SLTG_InternalOtherTypeInfo;
4387 /****************************************************************************
4388 * ITypeLib2_Constructor_SLTG
4390 * loading a SLTG typelib from an in-memory image
4392 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4394 ITypeLibImpl *pTypeLibImpl;
4395 SLTG_Header *pHeader;
4396 SLTG_BlkEntry *pBlkEntry;
4397 SLTG_Magic *pMagic;
4398 SLTG_Index *pIndex;
4399 SLTG_Pad9 *pPad9;
4400 LPVOID pBlk, pFirstBlk;
4401 SLTG_LibBlk *pLibBlk;
4402 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4403 char *pAfterOTIBlks = NULL;
4404 char *pNameTable, *ptr;
4405 int i;
4406 DWORD len, order;
4407 ITypeInfoImpl **ppTypeInfoImpl;
4409 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4412 pTypeLibImpl = TypeLibImpl_Constructor();
4413 if (!pTypeLibImpl) return NULL;
4415 pHeader = pLib;
4417 TRACE_(typelib)("header:\n");
4418 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4419 pHeader->nrOfFileBlks );
4420 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4421 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4422 pHeader->SLTG_magic);
4423 return NULL;
4426 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4427 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4429 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4430 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4432 /* Next we have a magic block */
4433 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4435 /* Let's see if we're still in sync */
4436 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4437 sizeof(SLTG_COMPOBJ_MAGIC))) {
4438 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4439 return NULL;
4441 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4442 sizeof(SLTG_DIR_MAGIC))) {
4443 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4444 return NULL;
4447 pIndex = (SLTG_Index*)(pMagic+1);
4449 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4451 pFirstBlk = pPad9 + 1;
4453 /* We'll set up a ptr to the main library block, which is the last one. */
4455 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4456 pBlkEntry[order].next != 0;
4457 order = pBlkEntry[order].next - 1) {
4458 pBlk = (char*)pBlk + pBlkEntry[order].len;
4460 pLibBlk = pBlk;
4462 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4464 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4465 interspersed */
4467 len += 0x40;
4469 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4471 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4474 ptr = (char*)pLibBlk + len;
4476 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4477 WORD w, extra;
4478 len = 0;
4480 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4482 w = *(WORD*)(ptr + 2);
4483 if(w != 0xffff) {
4484 len += w;
4485 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4486 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4487 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4489 w = *(WORD*)(ptr + 4 + len);
4490 if(w != 0xffff) {
4491 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4492 len += w;
4493 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4494 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4495 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4497 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4498 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4499 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4500 if(extra) {
4501 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4502 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4503 len += extra;
4505 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4506 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4507 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4508 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4509 len += sizeof(SLTG_OtherTypeInfo);
4510 ptr += len;
4513 pAfterOTIBlks = ptr;
4515 /* Skip this WORD and get the next DWORD */
4516 len = *(DWORD*)(pAfterOTIBlks + 2);
4518 /* Now add this to pLibBLk look at what we're pointing at and
4519 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4520 dust and we should be pointing at the beginning of the name
4521 table */
4523 pNameTable = (char*)pLibBlk + len;
4525 switch(*(WORD*)pNameTable) {
4526 case 0xffff:
4527 break;
4528 case 0x0200:
4529 pNameTable += 0x20;
4530 break;
4531 default:
4532 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4533 break;
4536 pNameTable += 0x216;
4538 pNameTable += 2;
4540 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4542 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4545 /* Hopefully we now have enough ptrs set up to actually read in
4546 some TypeInfos. It's not clear which order to do them in, so
4547 I'll just follow the links along the BlkEntry chain and read
4548 them in the order in which they are in the file */
4550 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4551 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4553 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4554 pBlkEntry[order].next != 0;
4555 order = pBlkEntry[order].next - 1, i++) {
4557 SLTG_TypeInfoHeader *pTIHeader;
4558 SLTG_TypeInfoTail *pTITail;
4559 SLTG_MemberHeader *pMemHeader;
4561 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4562 FIXME_(typelib)("Index strings don't match\n");
4563 heap_free(pOtherTypeInfoBlks);
4564 return NULL;
4567 pTIHeader = pBlk;
4568 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4569 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4570 heap_free(pOtherTypeInfoBlks);
4571 return NULL;
4573 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4574 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4575 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4577 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4578 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4579 (*ppTypeInfoImpl)->index = i;
4580 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4581 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4582 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4583 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4584 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4585 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4586 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4587 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4589 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4590 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4592 if((pTIHeader->typeflags1 & 7) != 2)
4593 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4594 if(pTIHeader->typeflags3 != 2)
4595 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4597 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4598 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4599 typekind_desc[pTIHeader->typekind],
4600 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4601 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4603 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4605 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4607 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4608 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4609 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4611 switch(pTIHeader->typekind) {
4612 case TKIND_ENUM:
4613 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4614 pTIHeader, pTITail);
4615 break;
4617 case TKIND_RECORD:
4618 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4619 pTIHeader, pTITail);
4620 break;
4622 case TKIND_INTERFACE:
4623 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4624 pTIHeader, pTITail);
4625 break;
4627 case TKIND_COCLASS:
4628 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4629 pTIHeader, pTITail);
4630 break;
4632 case TKIND_ALIAS:
4633 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4634 pTIHeader, pTITail);
4635 break;
4637 case TKIND_DISPATCH:
4638 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4639 pTIHeader, pTITail);
4640 break;
4642 case TKIND_MODULE:
4643 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4644 pTIHeader, pTITail);
4645 break;
4647 default:
4648 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4649 break;
4653 /* could get cFuncs, cVars and cImplTypes from here
4654 but we've already set those */
4655 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4656 X(06);
4657 X(16);
4658 X(18);
4659 X(1a);
4660 X(1e);
4661 X(24);
4662 X(26);
4663 X(2a);
4664 X(2c);
4665 X(2e);
4666 X(30);
4667 X(32);
4668 X(34);
4669 #undef X
4670 ++ppTypeInfoImpl;
4671 pBlk = (char*)pBlk + pBlkEntry[order].len;
4674 if(i != pTypeLibImpl->TypeInfoCount) {
4675 FIXME("Somehow processed %d TypeInfos\n", i);
4676 heap_free(pOtherTypeInfoBlks);
4677 return NULL;
4680 heap_free(pOtherTypeInfoBlks);
4681 return &pTypeLibImpl->ITypeLib2_iface;
4684 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4686 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4688 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4690 if(IsEqualIID(riid, &IID_IUnknown) ||
4691 IsEqualIID(riid,&IID_ITypeLib)||
4692 IsEqualIID(riid,&IID_ITypeLib2))
4694 *ppv = &This->ITypeLib2_iface;
4696 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4697 IsEqualIID(riid, &IID_ICreateTypeLib2))
4699 *ppv = &This->ICreateTypeLib2_iface;
4701 else
4703 *ppv = NULL;
4704 TRACE("-- Interface: E_NOINTERFACE\n");
4705 return E_NOINTERFACE;
4708 IUnknown_AddRef((IUnknown*)*ppv);
4709 return S_OK;
4712 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4714 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4715 ULONG ref = InterlockedIncrement(&This->ref);
4717 TRACE("(%p) ref=%u\n", This, ref);
4719 return ref;
4722 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4724 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4725 ULONG ref = InterlockedDecrement(&This->ref);
4727 TRACE("(%p) ref=%u\n",This, ref);
4729 if (!ref)
4731 TLBImpLib *pImpLib, *pImpLibNext;
4732 TLBRefType *ref_type, *ref_type_next;
4733 TLBString *tlbstr, *tlbstr_next;
4734 TLBGuid *tlbguid, *tlbguid_next;
4735 int i;
4737 /* remove cache entry */
4738 if(This->path)
4740 TRACE("removing from cache list\n");
4741 EnterCriticalSection(&cache_section);
4742 if(This->entry.next)
4743 list_remove(&This->entry);
4744 LeaveCriticalSection(&cache_section);
4745 heap_free(This->path);
4747 TRACE(" destroying ITypeLib(%p)\n",This);
4749 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4750 list_remove(&tlbstr->entry);
4751 SysFreeString(tlbstr->str);
4752 heap_free(tlbstr);
4755 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4756 list_remove(&tlbstr->entry);
4757 SysFreeString(tlbstr->str);
4758 heap_free(tlbstr);
4761 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4762 list_remove(&tlbguid->entry);
4763 heap_free(tlbguid);
4766 TLB_FreeCustData(&This->custdata_list);
4768 for (i = 0; i < This->ctTypeDesc; i++)
4769 if (This->pTypeDesc[i].vt == VT_CARRAY)
4770 heap_free(This->pTypeDesc[i].u.lpadesc);
4772 heap_free(This->pTypeDesc);
4774 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4776 if (pImpLib->pImpTypeLib)
4777 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4778 SysFreeString(pImpLib->name);
4780 list_remove(&pImpLib->entry);
4781 heap_free(pImpLib);
4784 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4786 list_remove(&ref_type->entry);
4787 heap_free(ref_type);
4790 for (i = 0; i < This->TypeInfoCount; ++i){
4791 heap_free(This->typeinfos[i]->tdescAlias);
4792 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4794 heap_free(This->typeinfos);
4795 heap_free(This);
4796 return 0;
4799 return ref;
4802 /* ITypeLib::GetTypeInfoCount
4804 * Returns the number of type descriptions in the type library
4806 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4808 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4809 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4810 return This->TypeInfoCount;
4813 /* ITypeLib::GetTypeInfo
4815 * retrieves the specified type description in the library.
4817 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4818 ITypeLib2 *iface,
4819 UINT index,
4820 ITypeInfo **ppTInfo)
4822 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4824 TRACE("%p %u %p\n", This, index, ppTInfo);
4826 if(!ppTInfo)
4827 return E_INVALIDARG;
4829 if(index >= This->TypeInfoCount)
4830 return TYPE_E_ELEMENTNOTFOUND;
4832 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4833 ITypeInfo_AddRef(*ppTInfo);
4835 return S_OK;
4839 /* ITypeLibs::GetTypeInfoType
4841 * Retrieves the type of a type description.
4843 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4844 ITypeLib2 *iface,
4845 UINT index,
4846 TYPEKIND *pTKind)
4848 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4850 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4852 if(!pTKind)
4853 return E_INVALIDARG;
4855 if(index >= This->TypeInfoCount)
4856 return TYPE_E_ELEMENTNOTFOUND;
4858 *pTKind = This->typeinfos[index]->typeattr.typekind;
4860 return S_OK;
4863 /* ITypeLib::GetTypeInfoOfGuid
4865 * Retrieves the type description that corresponds to the specified GUID.
4868 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4869 ITypeLib2 *iface,
4870 REFGUID guid,
4871 ITypeInfo **ppTInfo)
4873 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4874 int i;
4876 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4878 for(i = 0; i < This->TypeInfoCount; ++i){
4879 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4880 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4881 ITypeInfo_AddRef(*ppTInfo);
4882 return S_OK;
4886 return TYPE_E_ELEMENTNOTFOUND;
4889 /* ITypeLib::GetLibAttr
4891 * Retrieves the structure that contains the library's attributes.
4894 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4895 ITypeLib2 *iface,
4896 LPTLIBATTR *attr)
4898 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4900 TRACE("(%p, %p)\n", This, attr);
4902 if (!attr) return E_INVALIDARG;
4904 *attr = heap_alloc(sizeof(**attr));
4905 if (!*attr) return E_OUTOFMEMORY;
4907 (*attr)->guid = *TLB_get_guid_null(This->guid);
4908 (*attr)->lcid = This->set_lcid;
4909 (*attr)->syskind = This->syskind;
4910 (*attr)->wMajorVerNum = This->ver_major;
4911 (*attr)->wMinorVerNum = This->ver_minor;
4912 (*attr)->wLibFlags = This->libflags;
4914 return S_OK;
4917 /* ITypeLib::GetTypeComp
4919 * Enables a client compiler to bind to a library's types, variables,
4920 * constants, and global functions.
4923 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4924 ITypeLib2 *iface,
4925 ITypeComp **ppTComp)
4927 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4929 TRACE("(%p)->(%p)\n",This,ppTComp);
4930 *ppTComp = &This->ITypeComp_iface;
4931 ITypeComp_AddRef(*ppTComp);
4933 return S_OK;
4936 /* ITypeLib::GetDocumentation
4938 * Retrieves the library's documentation string, the complete Help file name
4939 * and path, and the context identifier for the library Help topic in the Help
4940 * file.
4942 * On a successful return all non-null BSTR pointers will have been set,
4943 * possibly to NULL.
4945 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4946 ITypeLib2 *iface,
4947 INT index,
4948 BSTR *pBstrName,
4949 BSTR *pBstrDocString,
4950 DWORD *pdwHelpContext,
4951 BSTR *pBstrHelpFile)
4953 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4954 HRESULT result = E_INVALIDARG;
4955 ITypeInfo *pTInfo;
4957 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4958 This, index,
4959 pBstrName, pBstrDocString,
4960 pdwHelpContext, pBstrHelpFile);
4962 if(index<0)
4964 /* documentation for the typelib */
4965 if(pBstrName)
4967 if (This->Name)
4969 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4970 goto memerr1;
4972 else
4973 *pBstrName = NULL;
4975 if(pBstrDocString)
4977 if (This->DocString)
4979 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4980 goto memerr2;
4982 else
4983 *pBstrDocString = NULL;
4985 if(pdwHelpContext)
4987 *pdwHelpContext = This->dwHelpContext;
4989 if(pBstrHelpFile)
4991 if (This->HelpFile)
4993 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4994 goto memerr3;
4996 else
4997 *pBstrHelpFile = NULL;
5000 result = S_OK;
5002 else
5004 /* for a typeinfo */
5005 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5007 if(SUCCEEDED(result))
5009 result = ITypeInfo_GetDocumentation(pTInfo,
5010 MEMBERID_NIL,
5011 pBstrName,
5012 pBstrDocString,
5013 pdwHelpContext, pBstrHelpFile);
5015 ITypeInfo_Release(pTInfo);
5018 return result;
5019 memerr3:
5020 if (pBstrDocString) SysFreeString (*pBstrDocString);
5021 memerr2:
5022 if (pBstrName) SysFreeString (*pBstrName);
5023 memerr1:
5024 return STG_E_INSUFFICIENTMEMORY;
5027 /* ITypeLib::IsName
5029 * Indicates whether a passed-in string contains the name of a type or member
5030 * described in the library.
5033 static HRESULT WINAPI ITypeLib2_fnIsName(
5034 ITypeLib2 *iface,
5035 LPOLESTR szNameBuf,
5036 ULONG lHashVal,
5037 BOOL *pfName)
5039 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5040 int tic;
5041 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5043 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5044 pfName);
5046 *pfName=TRUE;
5047 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5048 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5049 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5050 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5051 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5052 int pc;
5053 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5054 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5055 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5056 goto ITypeLib2_fnIsName_exit;
5059 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5060 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5061 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5065 *pfName=FALSE;
5067 ITypeLib2_fnIsName_exit:
5068 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5069 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5071 return S_OK;
5074 /* ITypeLib::FindName
5076 * Finds occurrences of a type description in a type library. This may be used
5077 * to quickly verify that a name exists in a type library.
5080 static HRESULT WINAPI ITypeLib2_fnFindName(
5081 ITypeLib2 *iface,
5082 LPOLESTR name,
5083 ULONG hash,
5084 ITypeInfo **ppTInfo,
5085 MEMBERID *memid,
5086 UINT16 *found)
5088 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5089 int tic;
5090 UINT count = 0;
5091 UINT len;
5093 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5095 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5096 return E_INVALIDARG;
5098 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5099 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5100 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5101 TLBVarDesc *var;
5102 UINT fdc;
5104 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5105 memid[count] = MEMBERID_NIL;
5106 goto ITypeLib2_fnFindName_exit;
5109 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5110 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5112 if(!TLB_str_memcmp(name, func->Name, len)) {
5113 memid[count] = func->funcdesc.memid;
5114 goto ITypeLib2_fnFindName_exit;
5118 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->typeattr.cVars, name);
5119 if (var) {
5120 memid[count] = var->vardesc.memid;
5121 goto ITypeLib2_fnFindName_exit;
5124 continue;
5125 ITypeLib2_fnFindName_exit:
5126 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5127 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5128 count++;
5130 TRACE("found %d typeinfos\n", count);
5132 *found = count;
5134 return S_OK;
5137 /* ITypeLib::ReleaseTLibAttr
5139 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5142 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5143 ITypeLib2 *iface,
5144 TLIBATTR *pTLibAttr)
5146 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5147 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5148 heap_free(pTLibAttr);
5151 /* ITypeLib2::GetCustData
5153 * gets the custom data
5155 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5156 ITypeLib2 * iface,
5157 REFGUID guid,
5158 VARIANT *pVarVal)
5160 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5161 TLBCustData *pCData;
5163 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5165 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5166 if(!pCData)
5167 return TYPE_E_ELEMENTNOTFOUND;
5169 VariantInit(pVarVal);
5170 VariantCopy(pVarVal, &pCData->data);
5172 return S_OK;
5175 /* ITypeLib2::GetLibStatistics
5177 * Returns statistics about a type library that are required for efficient
5178 * sizing of hash tables.
5181 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5182 ITypeLib2 * iface,
5183 ULONG *pcUniqueNames,
5184 ULONG *pcchUniqueNames)
5186 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5188 FIXME("(%p): stub!\n", This);
5190 if(pcUniqueNames) *pcUniqueNames=1;
5191 if(pcchUniqueNames) *pcchUniqueNames=1;
5192 return S_OK;
5195 /* ITypeLib2::GetDocumentation2
5197 * Retrieves the library's documentation string, the complete Help file name
5198 * and path, the localization context to use, and the context ID for the
5199 * library Help topic in the Help file.
5202 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5203 ITypeLib2 * iface,
5204 INT index,
5205 LCID lcid,
5206 BSTR *pbstrHelpString,
5207 DWORD *pdwHelpStringContext,
5208 BSTR *pbstrHelpStringDll)
5210 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5211 HRESULT result;
5212 ITypeInfo *pTInfo;
5214 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5216 /* the help string should be obtained from the helpstringdll,
5217 * using the _DLLGetDocumentation function, based on the supplied
5218 * lcid. Nice to do sometime...
5220 if(index<0)
5222 /* documentation for the typelib */
5223 if(pbstrHelpString)
5224 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5225 if(pdwHelpStringContext)
5226 *pdwHelpStringContext=This->dwHelpContext;
5227 if(pbstrHelpStringDll)
5228 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5230 result = S_OK;
5232 else
5234 /* for a typeinfo */
5235 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5237 if(SUCCEEDED(result))
5239 ITypeInfo2 * pTInfo2;
5240 result = ITypeInfo_QueryInterface(pTInfo,
5241 &IID_ITypeInfo2,
5242 (LPVOID*) &pTInfo2);
5244 if(SUCCEEDED(result))
5246 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5247 MEMBERID_NIL,
5248 lcid,
5249 pbstrHelpString,
5250 pdwHelpStringContext,
5251 pbstrHelpStringDll);
5253 ITypeInfo2_Release(pTInfo2);
5256 ITypeInfo_Release(pTInfo);
5259 return result;
5262 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5264 TLBCustData *pCData;
5265 unsigned int ct;
5266 CUSTDATAITEM *cdi;
5268 ct = list_count(custdata_list);
5270 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5271 if(!pCustData->prgCustData)
5272 return E_OUTOFMEMORY;
5274 pCustData->cCustData = ct;
5276 cdi = pCustData->prgCustData;
5277 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5278 cdi->guid = *TLB_get_guid_null(pCData->guid);
5279 VariantCopy(&cdi->varValue, &pCData->data);
5280 ++cdi;
5283 return S_OK;
5287 /* ITypeLib2::GetAllCustData
5289 * Gets all custom data items for the library.
5292 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5293 ITypeLib2 * iface,
5294 CUSTDATA *pCustData)
5296 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5297 TRACE("(%p)->(%p)\n", This, pCustData);
5298 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5301 static const ITypeLib2Vtbl tlbvt = {
5302 ITypeLib2_fnQueryInterface,
5303 ITypeLib2_fnAddRef,
5304 ITypeLib2_fnRelease,
5305 ITypeLib2_fnGetTypeInfoCount,
5306 ITypeLib2_fnGetTypeInfo,
5307 ITypeLib2_fnGetTypeInfoType,
5308 ITypeLib2_fnGetTypeInfoOfGuid,
5309 ITypeLib2_fnGetLibAttr,
5310 ITypeLib2_fnGetTypeComp,
5311 ITypeLib2_fnGetDocumentation,
5312 ITypeLib2_fnIsName,
5313 ITypeLib2_fnFindName,
5314 ITypeLib2_fnReleaseTLibAttr,
5316 ITypeLib2_fnGetCustData,
5317 ITypeLib2_fnGetLibStatistics,
5318 ITypeLib2_fnGetDocumentation2,
5319 ITypeLib2_fnGetAllCustData
5323 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5325 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5327 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5330 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5332 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5334 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5337 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5339 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5341 return ITypeLib2_Release(&This->ITypeLib2_iface);
5344 static HRESULT WINAPI ITypeLibComp_fnBind(
5345 ITypeComp * iface,
5346 OLECHAR * szName,
5347 ULONG lHash,
5348 WORD wFlags,
5349 ITypeInfo ** ppTInfo,
5350 DESCKIND * pDescKind,
5351 BINDPTR * pBindPtr)
5353 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5354 BOOL typemismatch = FALSE;
5355 int i;
5357 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5359 *pDescKind = DESCKIND_NONE;
5360 pBindPtr->lptcomp = NULL;
5361 *ppTInfo = NULL;
5363 for(i = 0; i < This->TypeInfoCount; ++i){
5364 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5365 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5367 /* FIXME: check wFlags here? */
5368 /* FIXME: we should use a hash table to look this info up using lHash
5369 * instead of an O(n) search */
5370 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5371 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5373 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5375 *pDescKind = DESCKIND_TYPECOMP;
5376 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5377 ITypeComp_AddRef(pBindPtr->lptcomp);
5378 TRACE("module or enum: %s\n", debugstr_w(szName));
5379 return S_OK;
5383 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5384 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5386 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5387 HRESULT hr;
5389 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5390 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5392 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5393 return S_OK;
5395 else if (hr == TYPE_E_TYPEMISMATCH)
5396 typemismatch = TRUE;
5399 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5400 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5402 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5403 HRESULT hr;
5404 ITypeInfo *subtypeinfo;
5405 BINDPTR subbindptr;
5406 DESCKIND subdesckind;
5408 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5409 &subtypeinfo, &subdesckind, &subbindptr);
5410 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5412 TYPEDESC tdesc_appobject;
5413 const VARDESC vardesc_appobject =
5415 -2, /* memid */
5416 NULL, /* lpstrSchema */
5418 0 /* oInst */
5421 /* ELEMDESC */
5423 /* TYPEDESC */
5425 &tdesc_appobject
5427 VT_PTR
5430 0, /* wVarFlags */
5431 VAR_STATIC /* varkind */
5434 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5435 tdesc_appobject.vt = VT_USERDEFINED;
5437 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5439 /* cleanup things filled in by Bind call so we can put our
5440 * application object data in there instead */
5441 switch (subdesckind)
5443 case DESCKIND_FUNCDESC:
5444 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5445 break;
5446 case DESCKIND_VARDESC:
5447 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5448 break;
5449 default:
5450 break;
5452 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5454 if (pTypeInfo->hreftype == -1)
5455 FIXME("no hreftype for interface %p\n", pTypeInfo);
5457 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5458 if (FAILED(hr))
5459 return hr;
5461 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5462 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5463 ITypeInfo_AddRef(*ppTInfo);
5464 return S_OK;
5466 else if (hr == TYPE_E_TYPEMISMATCH)
5467 typemismatch = TRUE;
5471 if (typemismatch)
5473 TRACE("type mismatch %s\n", debugstr_w(szName));
5474 return TYPE_E_TYPEMISMATCH;
5476 else
5478 TRACE("name not found %s\n", debugstr_w(szName));
5479 return S_OK;
5483 static HRESULT WINAPI ITypeLibComp_fnBindType(
5484 ITypeComp * iface,
5485 OLECHAR * szName,
5486 ULONG lHash,
5487 ITypeInfo ** ppTInfo,
5488 ITypeComp ** ppTComp)
5490 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5491 ITypeInfoImpl *info;
5493 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5495 if(!szName || !ppTInfo || !ppTComp)
5496 return E_INVALIDARG;
5498 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5499 if(!info){
5500 *ppTInfo = NULL;
5501 *ppTComp = NULL;
5502 return S_OK;
5505 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5506 ITypeInfo_AddRef(*ppTInfo);
5507 *ppTComp = &info->ITypeComp_iface;
5508 ITypeComp_AddRef(*ppTComp);
5510 return S_OK;
5513 static const ITypeCompVtbl tlbtcvt =
5516 ITypeLibComp_fnQueryInterface,
5517 ITypeLibComp_fnAddRef,
5518 ITypeLibComp_fnRelease,
5520 ITypeLibComp_fnBind,
5521 ITypeLibComp_fnBindType
5524 /*================== ITypeInfo(2) Methods ===================================*/
5525 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5527 ITypeInfoImpl *pTypeInfoImpl;
5529 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5530 if (pTypeInfoImpl)
5532 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5533 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5534 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5535 pTypeInfoImpl->ref = 0;
5536 pTypeInfoImpl->hreftype = -1;
5537 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5538 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5539 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5540 list_init(pTypeInfoImpl->pcustdata_list);
5542 TRACE("(%p)\n", pTypeInfoImpl);
5543 return pTypeInfoImpl;
5546 /* ITypeInfo::QueryInterface
5548 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5549 ITypeInfo2 *iface,
5550 REFIID riid,
5551 VOID **ppvObject)
5553 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5555 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5557 *ppvObject=NULL;
5558 if(IsEqualIID(riid, &IID_IUnknown) ||
5559 IsEqualIID(riid,&IID_ITypeInfo)||
5560 IsEqualIID(riid,&IID_ITypeInfo2))
5561 *ppvObject = &This->ITypeInfo2_iface;
5562 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5563 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5564 *ppvObject = &This->ICreateTypeInfo2_iface;
5565 else if(IsEqualIID(riid, &IID_ITypeComp))
5566 *ppvObject = &This->ITypeComp_iface;
5568 if(*ppvObject){
5569 IUnknown_AddRef((IUnknown*)*ppvObject);
5570 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5571 return S_OK;
5573 TRACE("-- Interface: E_NOINTERFACE\n");
5574 return E_NOINTERFACE;
5577 /* ITypeInfo::AddRef
5579 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5581 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5582 ULONG ref = InterlockedIncrement(&This->ref);
5584 TRACE("(%p)->ref is %u\n",This, ref);
5586 if (ref == 1 /* incremented from 0 */)
5587 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5589 return ref;
5592 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5594 UINT i;
5596 TRACE("destroying ITypeInfo(%p)\n",This);
5598 for (i = 0; i < This->typeattr.cFuncs; ++i)
5600 int j;
5601 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5602 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5604 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5605 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5606 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5607 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5609 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5610 heap_free(pFInfo->pParamDesc);
5611 TLB_FreeCustData(&pFInfo->custdata_list);
5613 heap_free(This->funcdescs);
5615 for(i = 0; i < This->typeattr.cVars; ++i)
5617 TLBVarDesc *pVInfo = &This->vardescs[i];
5618 if (pVInfo->vardesc_create) {
5619 TLB_FreeVarDesc(pVInfo->vardesc_create);
5620 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5621 VariantClear(pVInfo->vardesc.u.lpvarValue);
5622 heap_free(pVInfo->vardesc.u.lpvarValue);
5624 TLB_FreeCustData(&pVInfo->custdata_list);
5626 heap_free(This->vardescs);
5628 if(This->impltypes){
5629 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5630 TLBImplType *pImpl = &This->impltypes[i];
5631 TLB_FreeCustData(&pImpl->custdata_list);
5633 heap_free(This->impltypes);
5636 TLB_FreeCustData(&This->custdata_list);
5638 heap_free(This);
5641 /* ITypeInfo::Release
5643 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5645 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5646 ULONG ref = InterlockedDecrement(&This->ref);
5648 TRACE("(%p)->(%u)\n",This, ref);
5650 if (!ref)
5652 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5653 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5654 if (not_attached_to_typelib)
5655 heap_free(This);
5656 /* otherwise This will be freed when typelib is freed */
5659 return ref;
5662 /* ITypeInfo::GetTypeAttr
5664 * Retrieves a TYPEATTR structure that contains the attributes of the type
5665 * description.
5668 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5669 LPTYPEATTR *ppTypeAttr)
5671 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5672 SIZE_T size;
5674 TRACE("(%p)\n",This);
5676 size = sizeof(**ppTypeAttr);
5677 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5678 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5680 *ppTypeAttr = heap_alloc(size);
5681 if (!*ppTypeAttr)
5682 return E_OUTOFMEMORY;
5684 **ppTypeAttr = This->typeattr;
5685 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5687 if (This->tdescAlias)
5688 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5690 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5691 /* This should include all the inherited funcs */
5692 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5693 /* This is always the size of IDispatch's vtbl */
5694 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5695 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5697 return S_OK;
5700 /* ITypeInfo::GetTypeComp
5702 * Retrieves the ITypeComp interface for the type description, which enables a
5703 * client compiler to bind to the type description's members.
5706 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5707 ITypeComp * *ppTComp)
5709 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5711 TRACE("(%p)->(%p)\n", This, ppTComp);
5713 *ppTComp = &This->ITypeComp_iface;
5714 ITypeComp_AddRef(*ppTComp);
5715 return S_OK;
5718 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5720 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5721 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5722 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5723 return size;
5726 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5728 *dest = *src;
5729 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5730 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5732 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5733 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5734 *buffer += sizeof(PARAMDESCEX);
5735 *pparamdescex_dest = *pparamdescex_src;
5736 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5737 VariantInit(&pparamdescex_dest->varDefaultValue);
5738 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5739 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5741 else
5742 dest->u.paramdesc.pparamdescex = NULL;
5743 return S_OK;
5746 static HRESULT TLB_SanitizeBSTR(BSTR str)
5748 UINT len = SysStringLen(str), i;
5749 for (i = 0; i < len; ++i)
5750 if (str[i] > 0x7f)
5751 str[i] = '?';
5752 return S_OK;
5755 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5757 if (V_VT(var) == VT_INT)
5758 return VariantChangeType(var, var, 0, VT_I4);
5759 else if (V_VT(var) == VT_UINT)
5760 return VariantChangeType(var, var, 0, VT_UI4);
5761 else if (V_VT(var) == VT_BSTR)
5762 return TLB_SanitizeBSTR(V_BSTR(var));
5764 return S_OK;
5767 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5769 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5770 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5773 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5775 FUNCDESC *dest;
5776 char *buffer;
5777 SIZE_T size = sizeof(*src);
5778 SHORT i;
5779 HRESULT hr;
5781 size += sizeof(*src->lprgscode) * src->cScodes;
5782 size += TLB_SizeElemDesc(&src->elemdescFunc);
5783 for (i = 0; i < src->cParams; i++)
5785 size += sizeof(ELEMDESC);
5786 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5789 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5790 if (!dest) return E_OUTOFMEMORY;
5792 *dest = *src;
5793 if (dispinterface) /* overwrite funckind */
5794 dest->funckind = FUNC_DISPATCH;
5795 buffer = (char *)(dest + 1);
5797 dest->oVft = dest->oVft & 0xFFFC;
5799 if (dest->cScodes) {
5800 dest->lprgscode = (SCODE *)buffer;
5801 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5802 buffer += sizeof(*src->lprgscode) * src->cScodes;
5803 } else
5804 dest->lprgscode = NULL;
5806 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5807 if (FAILED(hr))
5809 SysFreeString((BSTR)dest);
5810 return hr;
5813 if (dest->cParams) {
5814 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5815 buffer += sizeof(ELEMDESC) * src->cParams;
5816 for (i = 0; i < src->cParams; i++)
5818 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5819 if (FAILED(hr))
5820 break;
5822 if (FAILED(hr))
5824 /* undo the above actions */
5825 for (i = i - 1; i >= 0; i--)
5826 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5827 TLB_FreeElemDesc(&dest->elemdescFunc);
5828 SysFreeString((BSTR)dest);
5829 return hr;
5831 } else
5832 dest->lprgelemdescParam = NULL;
5834 /* special treatment for dispinterfaces: this makes functions appear
5835 * to return their [retval] value when it is really returning an
5836 * HRESULT */
5837 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5839 if (dest->cParams &&
5840 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5842 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5843 if (elemdesc->tdesc.vt != VT_PTR)
5845 ERR("elemdesc should have started with VT_PTR instead of:\n");
5846 if (ERR_ON(ole))
5847 dump_ELEMDESC(elemdesc);
5848 return E_UNEXPECTED;
5851 /* copy last parameter to the return value. we are using a flat
5852 * buffer so there is no danger of leaking memory in
5853 * elemdescFunc */
5854 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5856 /* remove the last parameter */
5857 dest->cParams--;
5859 else
5860 /* otherwise this function is made to appear to have no return
5861 * value */
5862 dest->elemdescFunc.tdesc.vt = VT_VOID;
5866 *dest_ptr = dest;
5867 return S_OK;
5870 static void TLB_FreeVarDesc(VARDESC *var_desc)
5872 TLB_FreeElemDesc(&var_desc->elemdescVar);
5873 if (var_desc->varkind == VAR_CONST)
5874 VariantClear(var_desc->u.lpvarValue);
5875 SysFreeString((BSTR)var_desc);
5878 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5880 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5882 if (index >= This->typeattr.cFuncs)
5883 return TYPE_E_ELEMENTNOTFOUND;
5885 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5886 return S_OK;
5889 /* internal function to make the inherited interfaces' methods appear
5890 * part of the interface */
5891 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5892 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5894 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5895 HRESULT hr;
5896 UINT implemented_funcs = 0;
5898 if (funcs)
5899 *funcs = 0;
5900 else
5901 *hrefoffset = DISPATCH_HREF_OFFSET;
5903 if(This->impltypes)
5905 ITypeInfo *pSubTypeInfo;
5906 UINT sub_funcs;
5908 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5909 if (FAILED(hr))
5910 return hr;
5912 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5913 index,
5914 ppFuncDesc,
5915 &sub_funcs, hrefoffset);
5916 implemented_funcs += sub_funcs;
5917 ITypeInfo_Release(pSubTypeInfo);
5918 if (SUCCEEDED(hr))
5919 return hr;
5920 *hrefoffset += DISPATCH_HREF_OFFSET;
5923 if (funcs)
5924 *funcs = implemented_funcs + This->typeattr.cFuncs;
5925 else
5926 *hrefoffset = 0;
5928 if (index < implemented_funcs)
5929 return E_INVALIDARG;
5930 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5931 ppFuncDesc);
5934 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5936 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5937 while (TRUE)
5939 switch (pTypeDesc->vt)
5941 case VT_USERDEFINED:
5942 pTypeDesc->u.hreftype += hrefoffset;
5943 return;
5944 case VT_PTR:
5945 case VT_SAFEARRAY:
5946 pTypeDesc = pTypeDesc->u.lptdesc;
5947 break;
5948 case VT_CARRAY:
5949 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5950 break;
5951 default:
5952 return;
5957 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5959 SHORT i;
5960 for (i = 0; i < pFuncDesc->cParams; i++)
5961 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5962 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5965 /* ITypeInfo::GetFuncDesc
5967 * Retrieves the FUNCDESC structure that contains information about a
5968 * specified function.
5971 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5972 LPFUNCDESC *ppFuncDesc)
5974 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5975 const FUNCDESC *internal_funcdesc;
5976 HRESULT hr;
5977 UINT hrefoffset = 0;
5979 TRACE("(%p) index %d\n", This, index);
5981 if (!ppFuncDesc)
5982 return E_INVALIDARG;
5984 if (This->needs_layout)
5985 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5987 if (This->typeattr.typekind == TKIND_DISPATCH)
5988 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5989 &internal_funcdesc, NULL,
5990 &hrefoffset);
5991 else
5992 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5993 &internal_funcdesc);
5994 if (FAILED(hr))
5996 WARN("description for function %d not found\n", index);
5997 return hr;
6000 hr = TLB_AllocAndInitFuncDesc(
6001 internal_funcdesc,
6002 ppFuncDesc,
6003 This->typeattr.typekind == TKIND_DISPATCH);
6005 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6006 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6008 TRACE("-- 0x%08x\n", hr);
6009 return hr;
6012 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6014 VARDESC *dest;
6015 char *buffer;
6016 SIZE_T size = sizeof(*src);
6017 HRESULT hr;
6019 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6020 if (src->varkind == VAR_CONST)
6021 size += sizeof(VARIANT);
6022 size += TLB_SizeElemDesc(&src->elemdescVar);
6024 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6025 if (!dest) return E_OUTOFMEMORY;
6027 *dest = *src;
6028 buffer = (char *)(dest + 1);
6029 if (src->lpstrSchema)
6031 int len;
6032 dest->lpstrSchema = (LPOLESTR)buffer;
6033 len = strlenW(src->lpstrSchema);
6034 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6035 buffer += (len + 1) * sizeof(WCHAR);
6038 if (src->varkind == VAR_CONST)
6040 HRESULT hr;
6042 dest->u.lpvarValue = (VARIANT *)buffer;
6043 *dest->u.lpvarValue = *src->u.lpvarValue;
6044 buffer += sizeof(VARIANT);
6045 VariantInit(dest->u.lpvarValue);
6046 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6047 if (FAILED(hr))
6049 SysFreeString((BSTR)dest);
6050 return hr;
6053 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6054 if (FAILED(hr))
6056 if (src->varkind == VAR_CONST)
6057 VariantClear(dest->u.lpvarValue);
6058 SysFreeString((BSTR)dest);
6059 return hr;
6061 *dest_ptr = dest;
6062 return S_OK;
6065 /* ITypeInfo::GetVarDesc
6067 * Retrieves a VARDESC structure that describes the specified variable.
6070 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6071 LPVARDESC *ppVarDesc)
6073 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6074 const TLBVarDesc *pVDesc = &This->vardescs[index];
6076 TRACE("(%p) index %d\n", This, index);
6078 if(index >= This->typeattr.cVars)
6079 return TYPE_E_ELEMENTNOTFOUND;
6081 if (This->needs_layout)
6082 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6084 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6087 /* ITypeInfo_GetNames
6089 * Retrieves the variable with the specified member ID (or the name of the
6090 * property or method and its parameters) that correspond to the specified
6091 * function ID.
6093 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6094 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6096 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6097 const TLBFuncDesc *pFDesc;
6098 const TLBVarDesc *pVDesc;
6099 int i;
6100 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6102 if(!rgBstrNames)
6103 return E_INVALIDARG;
6105 *pcNames = 0;
6107 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
6108 if(pFDesc)
6110 if(!cMaxNames || !pFDesc->Name)
6111 return S_OK;
6113 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6114 ++(*pcNames);
6116 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6117 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6118 return S_OK;
6119 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6120 ++(*pcNames);
6122 return S_OK;
6125 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
6126 if(pVDesc)
6128 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6129 *pcNames=1;
6131 else
6133 if(This->impltypes &&
6134 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
6135 /* recursive search */
6136 ITypeInfo *pTInfo;
6137 HRESULT result;
6138 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6139 if(SUCCEEDED(result))
6141 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6142 ITypeInfo_Release(pTInfo);
6143 return result;
6145 WARN("Could not search inherited interface!\n");
6147 else
6149 WARN("no names found\n");
6151 *pcNames=0;
6152 return TYPE_E_ELEMENTNOTFOUND;
6154 return S_OK;
6158 /* ITypeInfo::GetRefTypeOfImplType
6160 * If a type description describes a COM class, it retrieves the type
6161 * description of the implemented interface types. For an interface,
6162 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6163 * if any exist.
6166 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6167 ITypeInfo2 *iface,
6168 UINT index,
6169 HREFTYPE *pRefType)
6171 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6172 HRESULT hr = S_OK;
6174 TRACE("(%p) index %d\n", This, index);
6175 if (TRACE_ON(ole)) dump_TypeInfo(This);
6177 if(index==(UINT)-1)
6179 /* only valid on dual interfaces;
6180 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6183 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6185 *pRefType = -2;
6187 else
6189 hr = TYPE_E_ELEMENTNOTFOUND;
6192 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6194 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6195 *pRefType = This->pTypeLib->dispatch_href;
6197 else
6199 if(index >= This->typeattr.cImplTypes)
6200 hr = TYPE_E_ELEMENTNOTFOUND;
6201 else{
6202 *pRefType = This->impltypes[index].hRef;
6203 if (This->typeattr.typekind == TKIND_INTERFACE)
6204 *pRefType |= 0x2;
6208 if(TRACE_ON(ole))
6210 if(SUCCEEDED(hr))
6211 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6212 else
6213 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6216 return hr;
6219 /* ITypeInfo::GetImplTypeFlags
6221 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6222 * or base interface in a type description.
6224 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6225 UINT index, INT *pImplTypeFlags)
6227 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6229 TRACE("(%p) index %d\n", This, index);
6231 if(!pImplTypeFlags)
6232 return E_INVALIDARG;
6234 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6235 *pImplTypeFlags = 0;
6236 return S_OK;
6239 if(index >= This->typeattr.cImplTypes)
6240 return TYPE_E_ELEMENTNOTFOUND;
6242 *pImplTypeFlags = This->impltypes[index].implflags;
6244 return S_OK;
6247 /* GetIDsOfNames
6248 * Maps between member names and member IDs, and parameter names and
6249 * parameter IDs.
6251 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6252 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6254 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6255 const TLBVarDesc *pVDesc;
6256 HRESULT ret=S_OK;
6257 UINT i, fdc;
6259 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6260 cNames);
6262 /* init out parameters in case of failure */
6263 for (i = 0; i < cNames; i++)
6264 pMemId[i] = MEMBERID_NIL;
6266 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6267 int j;
6268 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6269 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6270 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6271 for(i=1; i < cNames; i++){
6272 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6273 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6274 break;
6275 if( j<pFDesc->funcdesc.cParams)
6276 pMemId[i]=j;
6277 else
6278 ret=DISP_E_UNKNOWNNAME;
6280 TRACE("-- 0x%08x\n", ret);
6281 return ret;
6284 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, *rgszNames);
6285 if(pVDesc){
6286 if(cNames)
6287 *pMemId = pVDesc->vardesc.memid;
6288 return ret;
6290 /* not found, see if it can be found in an inherited interface */
6291 if(This->impltypes) {
6292 /* recursive search */
6293 ITypeInfo *pTInfo;
6294 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6295 if(SUCCEEDED(ret)){
6296 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6297 ITypeInfo_Release(pTInfo);
6298 return ret;
6300 WARN("Could not search inherited interface!\n");
6301 } else
6302 WARN("no names found\n");
6303 return DISP_E_UNKNOWNNAME;
6307 #ifdef __i386__
6309 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6310 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6311 __ASM_GLOBAL_FUNC( call_method,
6312 "pushl %ebp\n\t"
6313 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6314 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6315 "movl %esp,%ebp\n\t"
6316 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6317 "pushl %esi\n\t"
6318 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6319 "pushl %edi\n\t"
6320 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6321 "movl 12(%ebp),%edx\n\t"
6322 "movl %esp,%edi\n\t"
6323 "shll $2,%edx\n\t"
6324 "jz 1f\n\t"
6325 "subl %edx,%edi\n\t"
6326 "andl $~15,%edi\n\t"
6327 "movl %edi,%esp\n\t"
6328 "movl 12(%ebp),%ecx\n\t"
6329 "movl 16(%ebp),%esi\n\t"
6330 "cld\n\t"
6331 "rep; movsl\n"
6332 "1:\tcall *8(%ebp)\n\t"
6333 "subl %esp,%edi\n\t"
6334 "movl 20(%ebp),%ecx\n\t"
6335 "movl %edi,(%ecx)\n\t"
6336 "leal -8(%ebp),%esp\n\t"
6337 "popl %edi\n\t"
6338 __ASM_CFI(".cfi_same_value %edi\n\t")
6339 "popl %esi\n\t"
6340 __ASM_CFI(".cfi_same_value %esi\n\t")
6341 "popl %ebp\n\t"
6342 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6343 __ASM_CFI(".cfi_same_value %ebp\n\t")
6344 "ret" )
6345 __ASM_GLOBAL_FUNC( call_double_method,
6346 "jmp " __ASM_NAME("call_method") )
6348 /* ITypeInfo::Invoke
6350 * Invokes a method, or accesses a property of an object, that implements the
6351 * interface described by the type description.
6353 DWORD
6354 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6355 DWORD res;
6356 int stack_offset;
6358 if (TRACE_ON(ole)) {
6359 int i;
6360 TRACE("Calling %p(",func);
6361 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6362 if (nrargs > 30) TRACE("...");
6363 TRACE(")\n");
6366 switch (callconv) {
6367 case CC_STDCALL:
6368 case CC_CDECL:
6369 res = call_method( func, nrargs, args, &stack_offset );
6370 break;
6371 default:
6372 FIXME("unsupported calling convention %d\n",callconv);
6373 res = -1;
6374 break;
6376 TRACE("returns %08x\n",res);
6377 return res;
6380 #elif defined(__x86_64__)
6382 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6383 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6384 __ASM_GLOBAL_FUNC( call_method,
6385 "pushq %rbp\n\t"
6386 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6387 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6388 "movq %rsp,%rbp\n\t"
6389 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6390 "pushq %rsi\n\t"
6391 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6392 "pushq %rdi\n\t"
6393 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6394 "movq %rcx,%rax\n\t"
6395 "movq $4,%rcx\n\t"
6396 "cmp %rcx,%rdx\n\t"
6397 "cmovgq %rdx,%rcx\n\t"
6398 "leaq 0(,%rcx,8),%rdx\n\t"
6399 "subq %rdx,%rsp\n\t"
6400 "andq $~15,%rsp\n\t"
6401 "movq %rsp,%rdi\n\t"
6402 "movq %r8,%rsi\n\t"
6403 "rep; movsq\n\t"
6404 "movq 0(%rsp),%rcx\n\t"
6405 "movq 8(%rsp),%rdx\n\t"
6406 "movq 16(%rsp),%r8\n\t"
6407 "movq 24(%rsp),%r9\n\t"
6408 "movq 0(%rsp),%xmm0\n\t"
6409 "movq 8(%rsp),%xmm1\n\t"
6410 "movq 16(%rsp),%xmm2\n\t"
6411 "movq 24(%rsp),%xmm3\n\t"
6412 "callq *%rax\n\t"
6413 "leaq -16(%rbp),%rsp\n\t"
6414 "popq %rdi\n\t"
6415 __ASM_CFI(".cfi_same_value %rdi\n\t")
6416 "popq %rsi\n\t"
6417 __ASM_CFI(".cfi_same_value %rsi\n\t")
6418 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6419 "popq %rbp\n\t"
6420 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6421 __ASM_CFI(".cfi_same_value %rbp\n\t")
6422 "ret")
6423 __ASM_GLOBAL_FUNC( call_double_method,
6424 "jmp " __ASM_NAME("call_method") )
6426 #elif defined(__arm__)
6428 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6429 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6430 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6431 __ASM_GLOBAL_FUNC( call_method,
6432 /* r0 = *func
6433 * r1 = nb_stk_args
6434 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6435 * r3 = *reg_args (pointer to 8, 64-bit d0-d7 (double) values OR as 16, 32-bit s0-s15 (float) values, followed by 4, 32-bit (DWORD) r0-r3 values)
6438 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6439 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6441 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6442 "beq 1f\n\t" /* Skip allocation if no stack args */
6443 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6444 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6445 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6446 "subs r1, r1, #4\n\t" /* Decrement count */
6447 "bgt 2b\n\t" /* Loop till done */
6449 "1:\n\t"
6450 #ifndef __SOFTFP__
6451 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6452 #endif
6453 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6454 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6456 "blx ip\n\t" /* Call the target function */
6458 "mov sp, fp\n\t" /* Clean the stack using fp */
6459 "pop {fp, pc}\n\t" /* Restore fp and return */
6461 __ASM_GLOBAL_FUNC( call_float_method,
6462 "b " __ASM_NAME("call_method") )
6463 __ASM_GLOBAL_FUNC( call_double_method,
6464 "b " __ASM_NAME("call_method") )
6466 #endif /* __arm__ */
6468 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6470 HRESULT hr = S_OK;
6471 ITypeInfo *tinfo2 = NULL;
6472 TYPEATTR *tattr = NULL;
6474 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6475 if (hr)
6477 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6478 "hr = 0x%08x\n",
6479 tdesc->u.hreftype, hr);
6480 return hr;
6482 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6483 if (hr)
6485 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6486 ITypeInfo_Release(tinfo2);
6487 return hr;
6490 switch (tattr->typekind)
6492 case TKIND_ENUM:
6493 *vt |= VT_I4;
6494 break;
6496 case TKIND_ALIAS:
6497 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6498 break;
6500 case TKIND_INTERFACE:
6501 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6502 *vt |= VT_DISPATCH;
6503 else
6504 *vt |= VT_UNKNOWN;
6505 break;
6507 case TKIND_DISPATCH:
6508 *vt |= VT_DISPATCH;
6509 break;
6511 case TKIND_COCLASS:
6512 *vt |= VT_DISPATCH;
6513 break;
6515 case TKIND_RECORD:
6516 FIXME("TKIND_RECORD unhandled.\n");
6517 hr = E_NOTIMPL;
6518 break;
6520 case TKIND_UNION:
6521 FIXME("TKIND_UNION unhandled.\n");
6522 hr = E_NOTIMPL;
6523 break;
6525 default:
6526 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6527 hr = E_NOTIMPL;
6528 break;
6530 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6531 ITypeInfo_Release(tinfo2);
6532 return hr;
6535 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6537 HRESULT hr = S_OK;
6539 /* enforce only one level of pointer indirection */
6540 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6542 tdesc = tdesc->u.lptdesc;
6544 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6545 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6546 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6547 if ((tdesc->vt == VT_USERDEFINED) ||
6548 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6550 VARTYPE vt_userdefined = 0;
6551 const TYPEDESC *tdesc_userdefined = tdesc;
6552 if (tdesc->vt == VT_PTR)
6554 vt_userdefined = VT_BYREF;
6555 tdesc_userdefined = tdesc->u.lptdesc;
6557 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6558 if ((hr == S_OK) &&
6559 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6560 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6562 *vt |= vt_userdefined;
6563 return S_OK;
6566 *vt = VT_BYREF;
6569 switch (tdesc->vt)
6571 case VT_HRESULT:
6572 *vt |= VT_ERROR;
6573 break;
6574 case VT_USERDEFINED:
6575 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6576 break;
6577 case VT_VOID:
6578 case VT_CARRAY:
6579 case VT_PTR:
6580 case VT_LPSTR:
6581 case VT_LPWSTR:
6582 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6583 hr = DISP_E_BADVARTYPE;
6584 break;
6585 case VT_SAFEARRAY:
6586 *vt |= VT_ARRAY;
6587 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6588 break;
6589 case VT_INT:
6590 *vt |= VT_I4;
6591 break;
6592 case VT_UINT:
6593 *vt |= VT_UI4;
6594 break;
6595 default:
6596 *vt |= tdesc->vt;
6597 break;
6599 return hr;
6602 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6604 ITypeInfo *tinfo2;
6605 TYPEATTR *tattr;
6606 HRESULT hres;
6608 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6609 if(FAILED(hres))
6610 return hres;
6612 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6613 if(FAILED(hres)) {
6614 ITypeInfo_Release(tinfo2);
6615 return hres;
6618 switch(tattr->typekind) {
6619 case TKIND_ALIAS:
6620 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6621 break;
6623 case TKIND_INTERFACE:
6624 case TKIND_DISPATCH:
6625 *guid = tattr->guid;
6626 break;
6628 default:
6629 ERR("Unexpected typekind %d\n", tattr->typekind);
6630 hres = E_UNEXPECTED;
6633 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6634 ITypeInfo_Release(tinfo2);
6635 return hres;
6638 /***********************************************************************
6639 * DispCallFunc (OLEAUT32.@)
6641 * Invokes a function of the specified calling convention, passing the
6642 * specified arguments and returns the result.
6644 * PARAMS
6645 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6646 * oVft [I] The offset in the vtable. See notes.
6647 * cc [I] Calling convention of the function to call.
6648 * vtReturn [I] The return type of the function.
6649 * cActuals [I] Number of parameters.
6650 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6651 * prgpvarg [I] The arguments to pass.
6652 * pvargResult [O] The return value of the function. Can be NULL.
6654 * RETURNS
6655 * Success: S_OK.
6656 * Failure: HRESULT code.
6658 * NOTES
6659 * The HRESULT return value of this function is not affected by the return
6660 * value of the user supplied function, which is returned in pvargResult.
6662 * If pvInstance is NULL then a non-object function is to be called and oVft
6663 * is the address of the function to call.
6665 * The cc parameter can be one of the following values:
6666 *|CC_FASTCALL
6667 *|CC_CDECL
6668 *|CC_PASCAL
6669 *|CC_STDCALL
6670 *|CC_FPFASTCALL
6671 *|CC_SYSCALL
6672 *|CC_MPWCDECL
6673 *|CC_MPWPASCAL
6676 HRESULT WINAPI
6677 DispCallFunc(
6678 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6679 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6681 #ifdef __i386__
6682 int argspos, stack_offset;
6683 void *func;
6684 UINT i;
6685 DWORD *args;
6687 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6688 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6689 pvargResult, V_VT(pvargResult));
6691 if (cc != CC_STDCALL && cc != CC_CDECL)
6693 FIXME("unsupported calling convention %d\n",cc);
6694 return E_INVALIDARG;
6697 /* maximum size for an argument is sizeof(VARIANT) */
6698 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6700 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6701 argspos = 1;
6702 if (pvInstance)
6704 const FARPROC *vtable = *(FARPROC **)pvInstance;
6705 func = vtable[oVft/sizeof(void *)];
6706 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6708 else func = (void *)oVft;
6710 for (i = 0; i < cActuals; i++)
6712 VARIANT *arg = prgpvarg[i];
6714 switch (prgvt[i])
6716 case VT_EMPTY:
6717 break;
6718 case VT_I8:
6719 case VT_UI8:
6720 case VT_R8:
6721 case VT_DATE:
6722 case VT_CY:
6723 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6724 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6725 break;
6726 case VT_DECIMAL:
6727 case VT_VARIANT:
6728 memcpy( &args[argspos], arg, sizeof(*arg) );
6729 argspos += sizeof(*arg) / sizeof(DWORD);
6730 break;
6731 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6732 args[argspos++] = V_BOOL(arg);
6733 break;
6734 default:
6735 args[argspos++] = V_UI4(arg);
6736 break;
6738 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6741 switch (vtReturn)
6743 case VT_EMPTY:
6744 call_method( func, argspos - 1, args + 1, &stack_offset );
6745 break;
6746 case VT_R4:
6747 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6748 break;
6749 case VT_R8:
6750 case VT_DATE:
6751 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6752 break;
6753 case VT_DECIMAL:
6754 case VT_VARIANT:
6755 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6756 call_method( func, argspos, args, &stack_offset );
6757 break;
6758 case VT_I8:
6759 case VT_UI8:
6760 case VT_CY:
6761 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6762 break;
6763 case VT_HRESULT:
6764 WARN("invalid return type %u\n", vtReturn);
6765 heap_free( args );
6766 return E_INVALIDARG;
6767 default:
6768 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6769 break;
6771 heap_free( args );
6772 if (stack_offset && cc == CC_STDCALL)
6774 WARN( "stack pointer off by %d\n", stack_offset );
6775 return DISP_E_BADCALLEE;
6777 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6778 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6779 return S_OK;
6781 #elif defined(__x86_64__)
6782 int argspos;
6783 UINT i;
6784 DWORD_PTR *args;
6785 void *func;
6787 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6788 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6789 pvargResult, V_VT(pvargResult));
6791 if (cc != CC_STDCALL && cc != CC_CDECL)
6793 FIXME("unsupported calling convention %d\n",cc);
6794 return E_INVALIDARG;
6797 /* maximum size for an argument is sizeof(DWORD_PTR) */
6798 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6800 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6801 argspos = 1;
6802 if (pvInstance)
6804 const FARPROC *vtable = *(FARPROC **)pvInstance;
6805 func = vtable[oVft/sizeof(void *)];
6806 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6808 else func = (void *)oVft;
6810 for (i = 0; i < cActuals; i++)
6812 VARIANT *arg = prgpvarg[i];
6814 switch (prgvt[i])
6816 case VT_DECIMAL:
6817 case VT_VARIANT:
6818 args[argspos++] = (ULONG_PTR)arg;
6819 break;
6820 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6821 args[argspos++] = V_BOOL(arg);
6822 break;
6823 default:
6824 args[argspos++] = V_UI8(arg);
6825 break;
6827 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6830 switch (vtReturn)
6832 case VT_R4:
6833 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6834 break;
6835 case VT_R8:
6836 case VT_DATE:
6837 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6838 break;
6839 case VT_DECIMAL:
6840 case VT_VARIANT:
6841 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6842 call_method( func, argspos, args );
6843 break;
6844 case VT_HRESULT:
6845 WARN("invalid return type %u\n", vtReturn);
6846 heap_free( args );
6847 return E_INVALIDARG;
6848 default:
6849 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6850 break;
6852 heap_free( args );
6853 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6854 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6855 return S_OK;
6857 #elif defined(__arm__)
6858 int argspos;
6859 void *func;
6860 UINT i;
6861 DWORD *args;
6862 struct {
6863 #ifndef __SOFTFP__
6864 union {
6865 float s[16];
6866 double d[8];
6867 } sd;
6868 #endif
6869 DWORD r[4];
6870 } regs;
6871 int rcount; /* 32-bit register index count */
6872 #ifndef __SOFTFP__
6873 int scount = 0; /* single-precision float register index count */
6874 int dcount = 0; /* double-precision float register index count */
6875 #endif
6877 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6878 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6880 if (cc != CC_STDCALL && cc != CC_CDECL)
6882 FIXME("unsupported calling convention %d\n",cc);
6883 return E_INVALIDARG;
6886 argspos = 0;
6887 rcount = 0;
6889 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6890 /* first as it will need to be in the 'r' registers: */
6891 switch (vtReturn)
6893 case VT_DECIMAL:
6894 case VT_VARIANT:
6895 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6896 break;
6897 case VT_HRESULT:
6898 WARN("invalid return type %u\n", vtReturn);
6899 return E_INVALIDARG;
6900 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6901 break;
6904 if (pvInstance)
6906 const FARPROC *vtable = *(FARPROC **)pvInstance;
6907 func = vtable[oVft/sizeof(void *)];
6908 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6910 else func = (void *)oVft;
6912 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6913 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6915 for (i = 0; i < cActuals; i++)
6917 VARIANT *arg = prgpvarg[i];
6918 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6919 int ntemp; /* Used for counting words split between registers and stack */
6921 switch (prgvt[i])
6923 case VT_EMPTY:
6924 break;
6925 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6926 case VT_DATE:
6927 #ifndef __SOFTFP__
6928 dcount = max( (scount + 1) / 2, dcount );
6929 if (dcount < 8)
6931 regs.sd.d[dcount++] = V_R8(arg);
6933 else
6935 argspos += (argspos % 2); /* align argspos to 8-bytes */
6936 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6937 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6939 break;
6940 #endif
6941 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6942 case VT_UI8:
6943 case VT_CY:
6944 if (rcount < 3)
6946 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6947 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6948 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6950 else
6952 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6953 argspos += (argspos % 2); /* align argspos to 8-bytes */
6954 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6955 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6957 break;
6958 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6959 case VT_VARIANT:
6960 /* 8-byte align 'r' and/or stack: */
6961 if (rcount < 3)
6962 rcount += (rcount % 2);
6963 else
6965 rcount = 4;
6966 argspos += (argspos % 2);
6968 ntemp = sizeof(*arg) / sizeof(DWORD);
6969 while (ntemp > 0)
6971 if (rcount < 4)
6972 regs.r[rcount++] = *pdwarg++;
6973 else
6974 args[argspos++] = *pdwarg++;
6975 --ntemp;
6977 break;
6978 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6979 if (rcount < 4)
6980 regs.r[rcount++] = V_BOOL(arg);
6981 else
6982 args[argspos++] = V_BOOL(arg);
6983 break;
6984 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6985 #ifndef __SOFTFP__
6986 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6987 if (scount < 16)
6988 regs.sd.s[scount++] = V_R4(arg);
6989 else
6990 args[argspos++] = V_UI4(arg);
6991 break;
6992 #endif
6993 default:
6994 if (rcount < 4)
6995 regs.r[rcount++] = V_UI4(arg);
6996 else
6997 args[argspos++] = V_UI4(arg);
6998 break;
7000 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
7003 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
7005 switch (vtReturn)
7007 case VT_EMPTY: /* EMPTY = no return value */
7008 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
7009 case VT_VARIANT:
7010 call_method( func, argspos, args, (DWORD*)&regs );
7011 break;
7012 case VT_R4:
7013 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
7014 break;
7015 case VT_R8:
7016 case VT_DATE:
7017 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
7018 break;
7019 case VT_I8:
7020 case VT_UI8:
7021 case VT_CY:
7022 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
7023 break;
7024 default:
7025 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
7026 break;
7028 heap_free( args );
7029 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
7030 TRACE("retval: %s\n", debugstr_variant(pvargResult));
7031 return S_OK;
7033 #else
7034 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7035 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
7036 return E_NOTIMPL;
7037 #endif
7040 static inline BOOL func_restricted( const FUNCDESC *desc )
7042 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7045 #define INVBUF_ELEMENT_SIZE \
7046 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7047 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7048 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7049 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7050 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7051 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7052 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7053 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7055 static HRESULT WINAPI ITypeInfo_fnInvoke(
7056 ITypeInfo2 *iface,
7057 VOID *pIUnk,
7058 MEMBERID memid,
7059 UINT16 wFlags,
7060 DISPPARAMS *pDispParams,
7061 VARIANT *pVarResult,
7062 EXCEPINFO *pExcepInfo,
7063 UINT *pArgErr)
7065 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7066 int i;
7067 unsigned int var_index;
7068 TYPEKIND type_kind;
7069 HRESULT hres;
7070 const TLBFuncDesc *pFuncInfo;
7071 UINT fdc;
7073 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7074 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
7077 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7078 return DISP_E_MEMBERNOTFOUND;
7080 if (!pDispParams)
7082 ERR("NULL pDispParams not allowed\n");
7083 return E_INVALIDARG;
7086 dump_DispParms(pDispParams);
7088 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7090 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7091 pDispParams->cNamedArgs, pDispParams->cArgs);
7092 return E_INVALIDARG;
7095 /* we do this instead of using GetFuncDesc since it will return a fake
7096 * FUNCDESC for dispinterfaces and we want the real function description */
7097 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7098 pFuncInfo = &This->funcdescs[fdc];
7099 if ((memid == pFuncInfo->funcdesc.memid) &&
7100 (wFlags & pFuncInfo->funcdesc.invkind) &&
7101 !func_restricted( &pFuncInfo->funcdesc ))
7102 break;
7105 if (fdc < This->typeattr.cFuncs) {
7106 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7108 if (TRACE_ON(ole))
7110 TRACE("invoking:\n");
7111 dump_TLBFuncDescOne(pFuncInfo);
7114 switch (func_desc->funckind) {
7115 case FUNC_PUREVIRTUAL:
7116 case FUNC_VIRTUAL: {
7117 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7118 VARIANT varresult;
7119 VARIANT retval; /* pointer for storing byref retvals in */
7120 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7121 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7122 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7123 UINT cNamedArgs = pDispParams->cNamedArgs;
7124 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7125 UINT vargs_converted=0;
7127 hres = S_OK;
7129 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7131 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7133 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7134 hres = DISP_E_PARAMNOTFOUND;
7135 goto func_fail;
7139 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7141 ERR("functions with the vararg attribute do not support named arguments\n");
7142 hres = DISP_E_NONAMEDARGS;
7143 goto func_fail;
7146 for (i = 0; i < func_desc->cParams; i++)
7148 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7149 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7150 if (FAILED(hres))
7151 goto func_fail;
7154 TRACE("changing args\n");
7155 for (i = 0; i < func_desc->cParams; i++)
7157 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7158 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7159 VARIANTARG *src_arg;
7161 if (wParamFlags & PARAMFLAG_FLCID)
7163 VARIANTARG *arg;
7164 arg = prgpvarg[i] = &rgvarg[i];
7165 V_VT(arg) = VT_I4;
7166 V_I4(arg) = This->pTypeLib->lcid;
7167 continue;
7170 src_arg = NULL;
7172 if (cNamedArgs)
7174 USHORT j;
7175 for (j = 0; j < cNamedArgs; j++)
7176 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7178 src_arg = &pDispParams->rgvarg[j];
7179 break;
7183 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7185 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7186 vargs_converted++;
7189 if (wParamFlags & PARAMFLAG_FRETVAL)
7191 /* under most conditions the caller is not allowed to
7192 * pass in a dispparam arg in the index of what would be
7193 * the retval parameter. however, there is an exception
7194 * where the extra parameter is used in an extra
7195 * IDispatch::Invoke below */
7196 if ((i < pDispParams->cArgs) &&
7197 ((func_desc->cParams != 1) || !pVarResult ||
7198 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7200 hres = DISP_E_BADPARAMCOUNT;
7201 break;
7204 /* note: this check is placed so that if the caller passes
7205 * in a VARIANTARG for the retval we just ignore it, like
7206 * native does */
7207 if (i == func_desc->cParams - 1)
7209 VARIANTARG *arg;
7210 arg = prgpvarg[i] = &rgvarg[i];
7211 memset(arg, 0, sizeof(*arg));
7212 V_VT(arg) = rgvt[i];
7213 memset(&retval, 0, sizeof(retval));
7214 V_BYREF(arg) = &retval;
7216 else
7218 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7219 hres = E_UNEXPECTED;
7220 break;
7223 else if (src_arg)
7225 TRACE("%s\n", debugstr_variant(src_arg));
7227 if(rgvt[i]!=V_VT(src_arg))
7229 if (rgvt[i] == VT_VARIANT)
7230 hres = VariantCopy(&rgvarg[i], src_arg);
7231 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7233 if (rgvt[i] == V_VT(src_arg))
7234 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7235 else
7237 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7238 if (wParamFlags & PARAMFLAG_FIN)
7239 hres = VariantCopy(&missing_arg[i], src_arg);
7240 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7242 V_VT(&rgvarg[i]) = rgvt[i];
7244 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7246 SAFEARRAY *a;
7247 SAFEARRAYBOUND bound;
7248 VARIANT *v;
7249 LONG j;
7250 bound.lLbound = 0;
7251 bound.cElements = pDispParams->cArgs-i;
7252 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7254 ERR("SafeArrayCreate failed\n");
7255 break;
7257 hres = SafeArrayAccessData(a, (LPVOID)&v);
7258 if (hres != S_OK)
7260 ERR("SafeArrayAccessData failed with %x\n", hres);
7261 SafeArrayDestroy(a);
7262 break;
7264 for (j = 0; j < bound.cElements; j++)
7265 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7266 hres = SafeArrayUnaccessData(a);
7267 if (hres != S_OK)
7269 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7270 SafeArrayDestroy(a);
7271 break;
7273 if (rgvt[i] & VT_BYREF)
7274 V_BYREF(&rgvarg[i]) = &a;
7275 else
7276 V_ARRAY(&rgvarg[i]) = a;
7277 V_VT(&rgvarg[i]) = rgvt[i];
7279 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7281 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7282 if (wParamFlags & PARAMFLAG_FIN)
7283 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7284 else
7285 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7286 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7287 V_VT(&rgvarg[i]) = rgvt[i];
7289 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7291 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7292 V_VT(&rgvarg[i]) = rgvt[i];
7294 else
7296 /* FIXME: this doesn't work for VT_BYREF arguments if
7297 * they are not the same type as in the paramdesc */
7298 V_VT(&rgvarg[i]) = V_VT(src_arg);
7299 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7300 V_VT(&rgvarg[i]) = rgvt[i];
7303 if (FAILED(hres))
7305 ERR("failed to convert param %d to %s from %s\n", i,
7306 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7307 break;
7309 prgpvarg[i] = &rgvarg[i];
7311 else
7313 prgpvarg[i] = src_arg;
7316 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7317 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7318 && V_UNKNOWN(prgpvarg[i])) {
7319 IUnknown *userdefined_iface;
7320 GUID guid;
7322 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7323 if(FAILED(hres))
7324 break;
7326 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7327 if(FAILED(hres)) {
7328 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7329 break;
7332 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7333 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7336 else if (wParamFlags & PARAMFLAG_FOPT)
7338 VARIANTARG *arg;
7339 arg = prgpvarg[i] = &rgvarg[i];
7340 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7342 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7343 if (FAILED(hres))
7344 break;
7346 else
7348 VARIANTARG *missing_arg;
7349 /* if the function wants a pointer to a variant then
7350 * set that up, otherwise just pass the VT_ERROR in
7351 * the argument by value */
7352 if (rgvt[i] & VT_BYREF)
7354 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7355 V_VT(arg) = VT_VARIANT | VT_BYREF;
7356 V_VARIANTREF(arg) = missing_arg;
7358 else
7359 missing_arg = arg;
7360 V_VT(missing_arg) = VT_ERROR;
7361 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7364 else
7366 hres = DISP_E_BADPARAMCOUNT;
7367 break;
7370 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7372 /* VT_VOID is a special case for return types, so it is not
7373 * handled in the general function */
7374 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7375 V_VT(&varresult) = VT_EMPTY;
7376 else
7378 V_VT(&varresult) = 0;
7379 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7380 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7383 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7384 V_VT(&varresult), func_desc->cParams, rgvt,
7385 prgpvarg, &varresult);
7387 vargs_converted = 0;
7389 for (i = 0; i < func_desc->cParams; i++)
7391 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7392 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7394 if (wParamFlags & PARAMFLAG_FLCID)
7395 continue;
7396 else if (wParamFlags & PARAMFLAG_FRETVAL)
7398 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7400 if (pVarResult)
7402 VariantInit(pVarResult);
7403 /* deref return value */
7404 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7407 VARIANT_ClearInd(prgpvarg[i]);
7409 else if (vargs_converted < pDispParams->cArgs)
7411 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7412 if (wParamFlags & PARAMFLAG_FOUT)
7414 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7416 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7418 if (FAILED(hres))
7420 ERR("failed to convert param %d to vt %d\n", i,
7421 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7422 break;
7426 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7427 func_desc->cParamsOpt < 0 &&
7428 i == func_desc->cParams-1)
7430 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7431 LONG j, ubound;
7432 VARIANT *v;
7433 hres = SafeArrayGetUBound(a, 1, &ubound);
7434 if (hres != S_OK)
7436 ERR("SafeArrayGetUBound failed with %x\n", hres);
7437 break;
7439 hres = SafeArrayAccessData(a, (LPVOID)&v);
7440 if (hres != S_OK)
7442 ERR("SafeArrayAccessData failed with %x\n", hres);
7443 break;
7445 for (j = 0; j <= ubound; j++)
7446 VariantClear(&v[j]);
7447 hres = SafeArrayUnaccessData(a);
7448 if (hres != S_OK)
7450 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7451 break;
7454 VariantClear(&rgvarg[i]);
7455 vargs_converted++;
7457 else if (wParamFlags & PARAMFLAG_FOPT)
7459 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7460 VariantClear(&rgvarg[i]);
7463 VariantClear(&missing_arg[i]);
7466 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7468 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7469 hres = DISP_E_EXCEPTION;
7470 if (pExcepInfo)
7472 IErrorInfo *pErrorInfo;
7473 pExcepInfo->scode = V_ERROR(&varresult);
7474 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7476 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7477 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7478 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7479 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7481 IErrorInfo_Release(pErrorInfo);
7485 if (V_VT(&varresult) != VT_ERROR)
7487 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7489 if (pVarResult)
7491 VariantClear(pVarResult);
7492 *pVarResult = varresult;
7494 else
7495 VariantClear(&varresult);
7498 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7499 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7500 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7501 (pDispParams->cArgs != 0))
7503 if (V_VT(pVarResult) == VT_DISPATCH)
7505 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7506 /* Note: not VariantClear; we still need the dispatch
7507 * pointer to be valid */
7508 VariantInit(pVarResult);
7509 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7510 GetSystemDefaultLCID(), wFlags,
7511 pDispParams, pVarResult, pExcepInfo, pArgErr);
7512 IDispatch_Release(pDispatch);
7514 else
7516 VariantClear(pVarResult);
7517 hres = DISP_E_NOTACOLLECTION;
7521 func_fail:
7522 heap_free(buffer);
7523 break;
7525 case FUNC_DISPATCH: {
7526 IDispatch *disp;
7528 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7529 if (SUCCEEDED(hres)) {
7530 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7531 hres = IDispatch_Invoke(
7532 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7533 pVarResult,pExcepInfo,pArgErr
7535 if (FAILED(hres))
7536 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7537 IDispatch_Release(disp);
7538 } else
7539 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7540 break;
7542 default:
7543 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7544 hres = E_FAIL;
7545 break;
7548 TRACE("-- 0x%08x\n", hres);
7549 return hres;
7551 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7552 VARDESC *var_desc;
7554 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7555 if(FAILED(hres)) return hres;
7557 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7558 dump_VARDESC(var_desc);
7559 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7560 return E_NOTIMPL;
7563 /* not found, look for it in inherited interfaces */
7564 ITypeInfo2_GetTypeKind(iface, &type_kind);
7565 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7566 if(This->impltypes) {
7567 /* recursive search */
7568 ITypeInfo *pTInfo;
7569 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7570 if(SUCCEEDED(hres)){
7571 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7572 ITypeInfo_Release(pTInfo);
7573 return hres;
7575 WARN("Could not search inherited interface!\n");
7578 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7579 return DISP_E_MEMBERNOTFOUND;
7582 /* ITypeInfo::GetDocumentation
7584 * Retrieves the documentation string, the complete Help file name and path,
7585 * and the context ID for the Help topic for a specified type description.
7587 * (Can be tested by the Visual Basic Editor in Word for instance.)
7589 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7590 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7591 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7593 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7594 const TLBFuncDesc *pFDesc;
7595 const TLBVarDesc *pVDesc;
7596 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7597 " HelpContext(%p) HelpFile(%p)\n",
7598 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7599 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7600 if(pBstrName)
7601 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7602 if(pBstrDocString)
7603 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7604 if(pdwHelpContext)
7605 *pdwHelpContext=This->dwHelpContext;
7606 if(pBstrHelpFile)
7607 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7608 return S_OK;
7609 }else {/* for a member */
7610 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7611 if(pFDesc){
7612 if(pBstrName)
7613 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7614 if(pBstrDocString)
7615 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7616 if(pdwHelpContext)
7617 *pdwHelpContext=pFDesc->helpcontext;
7618 if(pBstrHelpFile)
7619 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7620 return S_OK;
7622 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
7623 if(pVDesc){
7624 if(pBstrName)
7625 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7626 if(pBstrDocString)
7627 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7628 if(pdwHelpContext)
7629 *pdwHelpContext=pVDesc->HelpContext;
7630 if(pBstrHelpFile)
7631 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7632 return S_OK;
7636 if(This->impltypes &&
7637 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7638 /* recursive search */
7639 ITypeInfo *pTInfo;
7640 HRESULT result;
7641 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7642 if(SUCCEEDED(result)) {
7643 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7644 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7645 ITypeInfo_Release(pTInfo);
7646 return result;
7648 WARN("Could not search inherited interface!\n");
7651 WARN("member %d not found\n", memid);
7652 return TYPE_E_ELEMENTNOTFOUND;
7655 /* ITypeInfo::GetDllEntry
7657 * Retrieves a description or specification of an entry point for a function
7658 * in a DLL.
7660 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7661 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7662 WORD *pwOrdinal)
7664 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7665 const TLBFuncDesc *pFDesc;
7667 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7669 if (pBstrDllName) *pBstrDllName = NULL;
7670 if (pBstrName) *pBstrName = NULL;
7671 if (pwOrdinal) *pwOrdinal = 0;
7673 if (This->typeattr.typekind != TKIND_MODULE)
7674 return TYPE_E_BADMODULEKIND;
7676 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7677 if(pFDesc){
7678 dump_TypeInfo(This);
7679 if (TRACE_ON(ole))
7680 dump_TLBFuncDescOne(pFDesc);
7682 if (pBstrDllName)
7683 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7685 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7686 if (pBstrName)
7687 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7688 if (pwOrdinal)
7689 *pwOrdinal = -1;
7690 return S_OK;
7692 if (pBstrName)
7693 *pBstrName = NULL;
7694 if (pwOrdinal)
7695 *pwOrdinal = LOWORD(pFDesc->Entry);
7696 return S_OK;
7698 return TYPE_E_ELEMENTNOTFOUND;
7701 /* internal function to make the inherited interfaces' methods appear
7702 * part of the interface */
7703 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7704 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7706 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7707 HRESULT hr;
7709 TRACE("%p, 0x%x\n", iface, *hRefType);
7711 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7713 ITypeInfo *pSubTypeInfo;
7715 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7716 if (FAILED(hr))
7717 return hr;
7719 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7720 hRefType, ppTInfo);
7721 ITypeInfo_Release(pSubTypeInfo);
7722 if (SUCCEEDED(hr))
7723 return hr;
7725 *hRefType -= DISPATCH_HREF_OFFSET;
7727 if (!(*hRefType & DISPATCH_HREF_MASK))
7728 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7729 else
7730 return E_FAIL;
7733 struct search_res_tlb_params
7735 const GUID *guid;
7736 ITypeLib *pTLib;
7739 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7741 struct search_res_tlb_params *params = (LPVOID)lParam;
7742 static const WCHAR formatW[] = {'\\','%','d',0};
7743 WCHAR szPath[MAX_PATH+1];
7744 ITypeLib *pTLib = NULL;
7745 HRESULT ret;
7746 DWORD len;
7748 if (IS_INTRESOURCE(lpszName) == FALSE)
7749 return TRUE;
7751 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7752 return TRUE;
7754 if (snprintfW(szPath + len, sizeof(szPath)/sizeof(WCHAR) - len, formatW, LOWORD(lpszName)) < 0)
7755 return TRUE;
7757 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7758 if (SUCCEEDED(ret))
7760 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7761 if (IsEqualGUID(params->guid, impl->guid))
7763 params->pTLib = pTLib;
7764 return FALSE; /* stop enumeration */
7766 ITypeLib_Release(pTLib);
7769 return TRUE;
7772 /* ITypeInfo::GetRefTypeInfo
7774 * If a type description references other type descriptions, it retrieves
7775 * the referenced type descriptions.
7777 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7778 ITypeInfo2 *iface,
7779 HREFTYPE hRefType,
7780 ITypeInfo **ppTInfo)
7782 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7783 HRESULT result = E_FAIL;
7785 if(!ppTInfo)
7786 return E_INVALIDARG;
7788 if ((INT)hRefType < 0) {
7789 ITypeInfoImpl *pTypeInfoImpl;
7791 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7792 !(This->typeattr.typekind == TKIND_INTERFACE ||
7793 This->typeattr.typekind == TKIND_DISPATCH))
7794 return TYPE_E_ELEMENTNOTFOUND;
7796 /* when we meet a DUAL typeinfo, we must create the alternate
7797 * version of it.
7799 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7801 *pTypeInfoImpl = *This;
7802 pTypeInfoImpl->ref = 0;
7803 list_init(&pTypeInfoImpl->custdata_list);
7805 if (This->typeattr.typekind == TKIND_INTERFACE)
7806 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7807 else
7808 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7810 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7811 /* the AddRef implicitly adds a reference to the parent typelib, which
7812 * stops the copied data from being destroyed until the new typeinfo's
7813 * refcount goes to zero, but we need to signal to the new instance to
7814 * not free its data structures when it is destroyed */
7815 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7817 ITypeInfo_AddRef(*ppTInfo);
7819 result = S_OK;
7820 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7821 (This->typeattr.typekind == TKIND_DISPATCH))
7823 HREFTYPE href_dispatch = hRefType;
7824 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7825 } else {
7826 TLBRefType *ref_type;
7827 ITypeLib *pTLib = NULL;
7828 UINT i;
7830 if(!(hRefType & 0x1)){
7831 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7833 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7835 result = S_OK;
7836 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7837 ITypeInfo_AddRef(*ppTInfo);
7838 goto end;
7843 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7845 if(ref_type->reference == (hRefType & (~0x3)))
7846 break;
7848 if(&ref_type->entry == &This->pTypeLib->ref_list)
7850 FIXME("Can't find pRefType for ref %x\n", hRefType);
7851 goto end;
7854 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7855 UINT Index;
7856 TRACE("internal reference\n");
7857 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7858 } else {
7859 if(ref_type->pImpTLInfo->pImpTypeLib) {
7860 TRACE("typeinfo in imported typelib that is already loaded\n");
7861 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7862 ITypeLib_AddRef(pTLib);
7863 result = S_OK;
7864 } else {
7865 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
7866 struct search_res_tlb_params params;
7867 BSTR libnam;
7869 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7871 /* Search in resource table */
7872 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
7873 params.pTLib = NULL;
7874 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
7875 pTLib = params.pTLib;
7876 result = S_OK;
7878 if (!pTLib)
7880 /* Search on disk */
7881 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7882 ref_type->pImpTLInfo->wVersionMajor,
7883 ref_type->pImpTLInfo->wVersionMinor,
7884 This->pTypeLib->syskind,
7885 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7886 if (FAILED(result))
7887 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7889 result = LoadTypeLib(libnam, &pTLib);
7890 SysFreeString(libnam);
7893 if(SUCCEEDED(result)) {
7894 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7895 ITypeLib_AddRef(pTLib);
7899 if(SUCCEEDED(result)) {
7900 if(ref_type->index == TLB_REF_USE_GUID)
7901 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7902 else
7903 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7905 if (pTLib != NULL)
7906 ITypeLib_Release(pTLib);
7909 end:
7910 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7911 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7912 return result;
7915 /* ITypeInfo::AddressOfMember
7917 * Retrieves the addresses of static functions or variables, such as those
7918 * defined in a DLL.
7920 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7921 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7923 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7924 HRESULT hr;
7925 BSTR dll, entry;
7926 WORD ordinal;
7927 HMODULE module;
7929 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7931 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7932 if (FAILED(hr))
7933 return hr;
7935 module = LoadLibraryW(dll);
7936 if (!module)
7938 ERR("couldn't load %s\n", debugstr_w(dll));
7939 SysFreeString(dll);
7940 SysFreeString(entry);
7941 return STG_E_FILENOTFOUND;
7943 /* FIXME: store library somewhere where we can free it */
7945 if (entry)
7947 LPSTR entryA;
7948 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7949 entryA = heap_alloc(len);
7950 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7952 *ppv = GetProcAddress(module, entryA);
7953 if (!*ppv)
7954 ERR("function not found %s\n", debugstr_a(entryA));
7956 heap_free(entryA);
7958 else
7960 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7961 if (!*ppv)
7962 ERR("function not found %d\n", ordinal);
7965 SysFreeString(dll);
7966 SysFreeString(entry);
7968 if (!*ppv)
7969 return TYPE_E_DLLFUNCTIONNOTFOUND;
7971 return S_OK;
7974 /* ITypeInfo::CreateInstance
7976 * Creates a new instance of a type that describes a component object class
7977 * (coclass).
7979 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7980 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7982 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7983 HRESULT hr;
7984 TYPEATTR *pTA;
7986 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7988 *ppvObj = NULL;
7990 if(pOuterUnk)
7992 WARN("Not able to aggregate\n");
7993 return CLASS_E_NOAGGREGATION;
7996 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7997 if(FAILED(hr)) return hr;
7999 if(pTA->typekind != TKIND_COCLASS)
8001 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8002 hr = E_INVALIDARG;
8003 goto end;
8006 hr = S_FALSE;
8007 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8009 IUnknown *pUnk;
8010 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8011 TRACE("GetActiveObject rets %08x\n", hr);
8012 if(hr == S_OK)
8014 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8015 IUnknown_Release(pUnk);
8019 if(hr != S_OK)
8020 hr = CoCreateInstance(&pTA->guid, NULL,
8021 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8022 riid, ppvObj);
8024 end:
8025 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8026 return hr;
8029 /* ITypeInfo::GetMops
8031 * Retrieves marshalling information.
8033 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
8034 BSTR *pBstrMops)
8036 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8037 FIXME("(%p %d) stub!\n", This, memid);
8038 *pBstrMops = NULL;
8039 return S_OK;
8042 /* ITypeInfo::GetContainingTypeLib
8044 * Retrieves the containing type library and the index of the type description
8045 * within that type library.
8047 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8048 ITypeLib * *ppTLib, UINT *pIndex)
8050 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8052 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8053 if (pIndex) {
8054 *pIndex=This->index;
8055 TRACE("returning pIndex=%d\n", *pIndex);
8058 if (ppTLib) {
8059 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8060 ITypeLib_AddRef(*ppTLib);
8061 TRACE("returning ppTLib=%p\n", *ppTLib);
8064 return S_OK;
8067 /* ITypeInfo::ReleaseTypeAttr
8069 * Releases a TYPEATTR previously returned by Get
8072 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8073 TYPEATTR* pTypeAttr)
8075 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8076 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8077 heap_free(pTypeAttr);
8080 /* ITypeInfo::ReleaseFuncDesc
8082 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8084 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8085 ITypeInfo2 *iface,
8086 FUNCDESC *pFuncDesc)
8088 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8089 SHORT i;
8091 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8093 for (i = 0; i < pFuncDesc->cParams; i++)
8094 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8095 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8097 SysFreeString((BSTR)pFuncDesc);
8100 /* ITypeInfo::ReleaseVarDesc
8102 * Releases a VARDESC previously returned by GetVarDesc.
8104 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8105 VARDESC *pVarDesc)
8107 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8108 TRACE("(%p)->(%p)\n", This, pVarDesc);
8110 TLB_FreeVarDesc(pVarDesc);
8113 /* ITypeInfo2::GetTypeKind
8115 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8118 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8119 TYPEKIND *pTypeKind)
8121 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8122 *pTypeKind = This->typeattr.typekind;
8123 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8124 return S_OK;
8127 /* ITypeInfo2::GetTypeFlags
8129 * Returns the type flags without any allocations. This returns a DWORD type
8130 * flag, which expands the type flags without growing the TYPEATTR (type
8131 * attribute).
8134 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8136 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8137 *pTypeFlags=This->typeattr.wTypeFlags;
8138 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
8139 return S_OK;
8142 /* ITypeInfo2::GetFuncIndexOfMemId
8143 * Binds to a specific member based on a known DISPID, where the member name
8144 * is not known (for example, when binding to a default member).
8147 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8148 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8150 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8151 UINT fdc;
8152 HRESULT result;
8154 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8155 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8156 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8157 break;
8159 if(fdc < This->typeattr.cFuncs) {
8160 *pFuncIndex = fdc;
8161 result = S_OK;
8162 } else
8163 result = TYPE_E_ELEMENTNOTFOUND;
8165 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8166 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8167 return result;
8170 /* TypeInfo2::GetVarIndexOfMemId
8172 * Binds to a specific member based on a known DISPID, where the member name
8173 * is not known (for example, when binding to a default member).
8176 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8177 MEMBERID memid, UINT *pVarIndex)
8179 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8180 TLBVarDesc *pVarInfo;
8182 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8184 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8185 if(!pVarInfo)
8186 return TYPE_E_ELEMENTNOTFOUND;
8188 *pVarIndex = (pVarInfo - This->vardescs);
8190 return S_OK;
8193 /* ITypeInfo2::GetCustData
8195 * Gets the custom data
8197 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8198 ITypeInfo2 * iface,
8199 REFGUID guid,
8200 VARIANT *pVarVal)
8202 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8203 TLBCustData *pCData;
8205 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8207 if(!guid || !pVarVal)
8208 return E_INVALIDARG;
8210 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8212 VariantInit( pVarVal);
8213 if (pCData)
8214 VariantCopy( pVarVal, &pCData->data);
8215 else
8216 VariantClear( pVarVal );
8217 return S_OK;
8220 /* ITypeInfo2::GetFuncCustData
8222 * Gets the custom data
8224 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8225 ITypeInfo2 * iface,
8226 UINT index,
8227 REFGUID guid,
8228 VARIANT *pVarVal)
8230 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8231 TLBCustData *pCData;
8232 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8234 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8236 if(index >= This->typeattr.cFuncs)
8237 return TYPE_E_ELEMENTNOTFOUND;
8239 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8240 if(!pCData)
8241 return TYPE_E_ELEMENTNOTFOUND;
8243 VariantInit(pVarVal);
8244 VariantCopy(pVarVal, &pCData->data);
8246 return S_OK;
8249 /* ITypeInfo2::GetParamCustData
8251 * Gets the custom data
8253 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8254 ITypeInfo2 * iface,
8255 UINT indexFunc,
8256 UINT indexParam,
8257 REFGUID guid,
8258 VARIANT *pVarVal)
8260 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8261 TLBCustData *pCData;
8262 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8264 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8265 debugstr_guid(guid), pVarVal);
8267 if(indexFunc >= This->typeattr.cFuncs)
8268 return TYPE_E_ELEMENTNOTFOUND;
8270 if(indexParam >= pFDesc->funcdesc.cParams)
8271 return TYPE_E_ELEMENTNOTFOUND;
8273 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8274 if(!pCData)
8275 return TYPE_E_ELEMENTNOTFOUND;
8277 VariantInit(pVarVal);
8278 VariantCopy(pVarVal, &pCData->data);
8280 return S_OK;
8283 /* ITypeInfo2::GetVarCustData
8285 * Gets the custom data
8287 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8288 ITypeInfo2 * iface,
8289 UINT index,
8290 REFGUID guid,
8291 VARIANT *pVarVal)
8293 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8294 TLBCustData *pCData;
8295 TLBVarDesc *pVDesc = &This->vardescs[index];
8297 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8299 if(index >= This->typeattr.cVars)
8300 return TYPE_E_ELEMENTNOTFOUND;
8302 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8303 if(!pCData)
8304 return TYPE_E_ELEMENTNOTFOUND;
8306 VariantInit(pVarVal);
8307 VariantCopy(pVarVal, &pCData->data);
8309 return S_OK;
8312 /* ITypeInfo2::GetImplCustData
8314 * Gets the custom data
8316 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8317 ITypeInfo2 * iface,
8318 UINT index,
8319 REFGUID guid,
8320 VARIANT *pVarVal)
8322 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8323 TLBCustData *pCData;
8324 TLBImplType *pRDesc = &This->impltypes[index];
8326 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8328 if(index >= This->typeattr.cImplTypes)
8329 return TYPE_E_ELEMENTNOTFOUND;
8331 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8332 if(!pCData)
8333 return TYPE_E_ELEMENTNOTFOUND;
8335 VariantInit(pVarVal);
8336 VariantCopy(pVarVal, &pCData->data);
8338 return S_OK;
8341 /* ITypeInfo2::GetDocumentation2
8343 * Retrieves the documentation string, the complete Help file name and path,
8344 * the localization context to use, and the context ID for the library Help
8345 * topic in the Help file.
8348 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8349 ITypeInfo2 * iface,
8350 MEMBERID memid,
8351 LCID lcid,
8352 BSTR *pbstrHelpString,
8353 DWORD *pdwHelpStringContext,
8354 BSTR *pbstrHelpStringDll)
8356 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8357 const TLBFuncDesc *pFDesc;
8358 const TLBVarDesc *pVDesc;
8359 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8360 "HelpStringContext(%p) HelpStringDll(%p)\n",
8361 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8362 pbstrHelpStringDll );
8363 /* the help string should be obtained from the helpstringdll,
8364 * using the _DLLGetDocumentation function, based on the supplied
8365 * lcid. Nice to do sometime...
8367 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8368 if(pbstrHelpString)
8369 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8370 if(pdwHelpStringContext)
8371 *pdwHelpStringContext=This->dwHelpStringContext;
8372 if(pbstrHelpStringDll)
8373 *pbstrHelpStringDll=
8374 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8375 return S_OK;
8376 }else {/* for a member */
8377 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
8378 if(pFDesc){
8379 if(pbstrHelpString)
8380 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8381 if(pdwHelpStringContext)
8382 *pdwHelpStringContext=pFDesc->HelpStringContext;
8383 if(pbstrHelpStringDll)
8384 *pbstrHelpStringDll=
8385 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8386 return S_OK;
8388 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8389 if(pVDesc){
8390 if(pbstrHelpString)
8391 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8392 if(pdwHelpStringContext)
8393 *pdwHelpStringContext=pVDesc->HelpStringContext;
8394 if(pbstrHelpStringDll)
8395 *pbstrHelpStringDll=
8396 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8397 return S_OK;
8400 return TYPE_E_ELEMENTNOTFOUND;
8403 /* ITypeInfo2::GetAllCustData
8405 * Gets all custom data items for the Type info.
8408 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8409 ITypeInfo2 * iface,
8410 CUSTDATA *pCustData)
8412 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8414 TRACE("%p %p\n", This, pCustData);
8416 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8419 /* ITypeInfo2::GetAllFuncCustData
8421 * Gets all custom data items for the specified Function
8424 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8425 ITypeInfo2 * iface,
8426 UINT index,
8427 CUSTDATA *pCustData)
8429 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8430 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8432 TRACE("%p %u %p\n", This, index, pCustData);
8434 if(index >= This->typeattr.cFuncs)
8435 return TYPE_E_ELEMENTNOTFOUND;
8437 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8440 /* ITypeInfo2::GetAllParamCustData
8442 * Gets all custom data items for the Functions
8445 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8446 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8448 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8449 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8451 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8453 if(indexFunc >= This->typeattr.cFuncs)
8454 return TYPE_E_ELEMENTNOTFOUND;
8456 if(indexParam >= pFDesc->funcdesc.cParams)
8457 return TYPE_E_ELEMENTNOTFOUND;
8459 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8462 /* ITypeInfo2::GetAllVarCustData
8464 * Gets all custom data items for the specified Variable
8467 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8468 UINT index, CUSTDATA *pCustData)
8470 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8471 TLBVarDesc * pVDesc = &This->vardescs[index];
8473 TRACE("%p %u %p\n", This, index, pCustData);
8475 if(index >= This->typeattr.cVars)
8476 return TYPE_E_ELEMENTNOTFOUND;
8478 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8481 /* ITypeInfo2::GetAllImplCustData
8483 * Gets all custom data items for the specified implementation type
8486 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8487 ITypeInfo2 * iface,
8488 UINT index,
8489 CUSTDATA *pCustData)
8491 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8492 TLBImplType *pRDesc = &This->impltypes[index];
8494 TRACE("%p %u %p\n", This, index, pCustData);
8496 if(index >= This->typeattr.cImplTypes)
8497 return TYPE_E_ELEMENTNOTFOUND;
8499 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8502 static const ITypeInfo2Vtbl tinfvt =
8505 ITypeInfo_fnQueryInterface,
8506 ITypeInfo_fnAddRef,
8507 ITypeInfo_fnRelease,
8509 ITypeInfo_fnGetTypeAttr,
8510 ITypeInfo_fnGetTypeComp,
8511 ITypeInfo_fnGetFuncDesc,
8512 ITypeInfo_fnGetVarDesc,
8513 ITypeInfo_fnGetNames,
8514 ITypeInfo_fnGetRefTypeOfImplType,
8515 ITypeInfo_fnGetImplTypeFlags,
8516 ITypeInfo_fnGetIDsOfNames,
8517 ITypeInfo_fnInvoke,
8518 ITypeInfo_fnGetDocumentation,
8519 ITypeInfo_fnGetDllEntry,
8520 ITypeInfo_fnGetRefTypeInfo,
8521 ITypeInfo_fnAddressOfMember,
8522 ITypeInfo_fnCreateInstance,
8523 ITypeInfo_fnGetMops,
8524 ITypeInfo_fnGetContainingTypeLib,
8525 ITypeInfo_fnReleaseTypeAttr,
8526 ITypeInfo_fnReleaseFuncDesc,
8527 ITypeInfo_fnReleaseVarDesc,
8529 ITypeInfo2_fnGetTypeKind,
8530 ITypeInfo2_fnGetTypeFlags,
8531 ITypeInfo2_fnGetFuncIndexOfMemId,
8532 ITypeInfo2_fnGetVarIndexOfMemId,
8533 ITypeInfo2_fnGetCustData,
8534 ITypeInfo2_fnGetFuncCustData,
8535 ITypeInfo2_fnGetParamCustData,
8536 ITypeInfo2_fnGetVarCustData,
8537 ITypeInfo2_fnGetImplTypeCustData,
8538 ITypeInfo2_fnGetDocumentation2,
8539 ITypeInfo2_fnGetAllCustData,
8540 ITypeInfo2_fnGetAllFuncCustData,
8541 ITypeInfo2_fnGetAllParamCustData,
8542 ITypeInfo2_fnGetAllVarCustData,
8543 ITypeInfo2_fnGetAllImplTypeCustData,
8546 /******************************************************************************
8547 * CreateDispTypeInfo [OLEAUT32.31]
8549 * Build type information for an object so it can be called through an
8550 * IDispatch interface.
8552 * RETURNS
8553 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8554 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8556 * NOTES
8557 * This call allows an objects methods to be accessed through IDispatch, by
8558 * building an ITypeInfo object that IDispatch can use to call through.
8560 HRESULT WINAPI CreateDispTypeInfo(
8561 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8562 LCID lcid, /* [I] Locale Id */
8563 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8565 ITypeInfoImpl *pTIClass, *pTIIface;
8566 ITypeLibImpl *pTypeLibImpl;
8567 unsigned int param, func;
8568 TLBFuncDesc *pFuncDesc;
8569 TLBRefType *ref;
8571 TRACE("\n");
8572 pTypeLibImpl = TypeLibImpl_Constructor();
8573 if (!pTypeLibImpl) return E_FAIL;
8575 pTypeLibImpl->TypeInfoCount = 2;
8576 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8578 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8579 pTIIface->pTypeLib = pTypeLibImpl;
8580 pTIIface->index = 0;
8581 pTIIface->Name = NULL;
8582 pTIIface->dwHelpContext = -1;
8583 pTIIface->guid = NULL;
8584 pTIIface->typeattr.lcid = lcid;
8585 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8586 pTIIface->typeattr.wMajorVerNum = 0;
8587 pTIIface->typeattr.wMinorVerNum = 0;
8588 pTIIface->typeattr.cbAlignment = 2;
8589 pTIIface->typeattr.cbSizeInstance = -1;
8590 pTIIface->typeattr.cbSizeVft = -1;
8591 pTIIface->typeattr.cFuncs = 0;
8592 pTIIface->typeattr.cImplTypes = 0;
8593 pTIIface->typeattr.cVars = 0;
8594 pTIIface->typeattr.wTypeFlags = 0;
8595 pTIIface->hreftype = 0;
8597 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8598 pFuncDesc = pTIIface->funcdescs;
8599 for(func = 0; func < pidata->cMembers; func++) {
8600 METHODDATA *md = pidata->pmethdata + func;
8601 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8602 pFuncDesc->funcdesc.memid = md->dispid;
8603 pFuncDesc->funcdesc.lprgscode = NULL;
8604 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8605 pFuncDesc->funcdesc.invkind = md->wFlags;
8606 pFuncDesc->funcdesc.callconv = md->cc;
8607 pFuncDesc->funcdesc.cParams = md->cArgs;
8608 pFuncDesc->funcdesc.cParamsOpt = 0;
8609 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8610 pFuncDesc->funcdesc.cScodes = 0;
8611 pFuncDesc->funcdesc.wFuncFlags = 0;
8612 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8613 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8614 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8615 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8616 md->cArgs * sizeof(ELEMDESC));
8617 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8618 for(param = 0; param < md->cArgs; param++) {
8619 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8620 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8622 pFuncDesc->helpcontext = 0;
8623 pFuncDesc->HelpStringContext = 0;
8624 pFuncDesc->HelpString = NULL;
8625 pFuncDesc->Entry = NULL;
8626 list_init(&pFuncDesc->custdata_list);
8627 pTIIface->typeattr.cFuncs++;
8628 ++pFuncDesc;
8631 dump_TypeInfo(pTIIface);
8633 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8634 pTIClass->pTypeLib = pTypeLibImpl;
8635 pTIClass->index = 1;
8636 pTIClass->Name = NULL;
8637 pTIClass->dwHelpContext = -1;
8638 pTIClass->guid = NULL;
8639 pTIClass->typeattr.lcid = lcid;
8640 pTIClass->typeattr.typekind = TKIND_COCLASS;
8641 pTIClass->typeattr.wMajorVerNum = 0;
8642 pTIClass->typeattr.wMinorVerNum = 0;
8643 pTIClass->typeattr.cbAlignment = 2;
8644 pTIClass->typeattr.cbSizeInstance = -1;
8645 pTIClass->typeattr.cbSizeVft = -1;
8646 pTIClass->typeattr.cFuncs = 0;
8647 pTIClass->typeattr.cImplTypes = 1;
8648 pTIClass->typeattr.cVars = 0;
8649 pTIClass->typeattr.wTypeFlags = 0;
8650 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8652 pTIClass->impltypes = TLBImplType_Alloc(1);
8654 ref = heap_alloc_zero(sizeof(*ref));
8655 ref->pImpTLInfo = TLB_REF_INTERNAL;
8656 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8658 dump_TypeInfo(pTIClass);
8660 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8662 ITypeInfo_AddRef(*pptinfo);
8663 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8665 return S_OK;
8669 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8671 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8673 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8676 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8678 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8680 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8683 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8685 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8687 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8690 static HRESULT WINAPI ITypeComp_fnBind(
8691 ITypeComp * iface,
8692 OLECHAR * szName,
8693 ULONG lHash,
8694 WORD wFlags,
8695 ITypeInfo ** ppTInfo,
8696 DESCKIND * pDescKind,
8697 BINDPTR * pBindPtr)
8699 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8700 const TLBFuncDesc *pFDesc;
8701 const TLBVarDesc *pVDesc;
8702 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8703 UINT fdc;
8705 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8707 *pDescKind = DESCKIND_NONE;
8708 pBindPtr->lpfuncdesc = NULL;
8709 *ppTInfo = NULL;
8711 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8712 pFDesc = &This->funcdescs[fdc];
8713 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8714 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8715 break;
8716 else
8717 /* name found, but wrong flags */
8718 hr = TYPE_E_TYPEMISMATCH;
8722 if (fdc < This->typeattr.cFuncs)
8724 HRESULT hr = TLB_AllocAndInitFuncDesc(
8725 &pFDesc->funcdesc,
8726 &pBindPtr->lpfuncdesc,
8727 This->typeattr.typekind == TKIND_DISPATCH);
8728 if (FAILED(hr))
8729 return hr;
8730 *pDescKind = DESCKIND_FUNCDESC;
8731 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8732 ITypeInfo_AddRef(*ppTInfo);
8733 return S_OK;
8734 } else {
8735 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, szName);
8736 if(pVDesc){
8737 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8738 if (FAILED(hr))
8739 return hr;
8740 *pDescKind = DESCKIND_VARDESC;
8741 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8742 ITypeInfo_AddRef(*ppTInfo);
8743 return S_OK;
8747 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8748 /* recursive search */
8749 ITypeInfo *pTInfo;
8750 ITypeComp *pTComp;
8751 HRESULT hr;
8752 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8753 if (SUCCEEDED(hr))
8755 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8756 ITypeInfo_Release(pTInfo);
8758 if (SUCCEEDED(hr))
8760 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8761 ITypeComp_Release(pTComp);
8762 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8763 This->typeattr.typekind == TKIND_DISPATCH)
8765 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8766 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8767 SysFreeString((BSTR)tmp);
8769 return hr;
8771 WARN("Could not search inherited interface!\n");
8773 if (hr == DISP_E_MEMBERNOTFOUND)
8774 hr = S_OK;
8775 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8776 return hr;
8779 static HRESULT WINAPI ITypeComp_fnBindType(
8780 ITypeComp * iface,
8781 OLECHAR * szName,
8782 ULONG lHash,
8783 ITypeInfo ** ppTInfo,
8784 ITypeComp ** ppTComp)
8786 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8788 /* strange behaviour (does nothing) but like the
8789 * original */
8791 if (!ppTInfo || !ppTComp)
8792 return E_POINTER;
8794 *ppTInfo = NULL;
8795 *ppTComp = NULL;
8797 return S_OK;
8800 static const ITypeCompVtbl tcompvt =
8803 ITypeComp_fnQueryInterface,
8804 ITypeComp_fnAddRef,
8805 ITypeComp_fnRelease,
8807 ITypeComp_fnBind,
8808 ITypeComp_fnBindType
8811 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8812 ICreateTypeLib2** ppctlib)
8814 ITypeLibImpl *This;
8815 HRESULT hres;
8817 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8819 if (!szFile) return E_INVALIDARG;
8821 This = TypeLibImpl_Constructor();
8822 if (!This)
8823 return E_OUTOFMEMORY;
8825 This->lcid = GetSystemDefaultLCID();
8826 This->syskind = syskind;
8827 This->ptr_size = get_ptr_size(syskind);
8829 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8830 if (!This->path) {
8831 ITypeLib2_Release(&This->ITypeLib2_iface);
8832 return E_OUTOFMEMORY;
8834 lstrcpyW(This->path, szFile);
8836 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8837 ITypeLib2_Release(&This->ITypeLib2_iface);
8838 return hres;
8841 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8842 REFIID riid, void **object)
8844 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8846 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8849 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8851 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8853 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8856 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8858 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8860 return ITypeLib2_Release(&This->ITypeLib2_iface);
8863 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8864 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8866 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8867 ITypeInfoImpl *info;
8868 HRESULT hres;
8870 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8872 if (!ctinfo || !name)
8873 return E_INVALIDARG;
8875 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8876 if (info)
8877 return TYPE_E_NAMECONFLICT;
8879 if (This->typeinfos)
8880 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8881 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8882 else
8883 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8885 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8887 info->pTypeLib = This;
8888 info->Name = TLB_append_str(&This->name_list, name);
8889 info->index = This->TypeInfoCount;
8890 info->typeattr.typekind = kind;
8891 info->typeattr.cbAlignment = 4;
8893 switch (info->typeattr.typekind) {
8894 case TKIND_ENUM:
8895 case TKIND_INTERFACE:
8896 case TKIND_DISPATCH:
8897 case TKIND_COCLASS:
8898 info->typeattr.cbSizeInstance = This->ptr_size;
8899 break;
8900 case TKIND_RECORD:
8901 case TKIND_UNION:
8902 info->typeattr.cbSizeInstance = 0;
8903 break;
8904 case TKIND_MODULE:
8905 info->typeattr.cbSizeInstance = 2;
8906 break;
8907 case TKIND_ALIAS:
8908 info->typeattr.cbSizeInstance = -0x75;
8909 break;
8910 default:
8911 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
8912 info->typeattr.cbSizeInstance = 0xdeadbeef;
8913 break;
8916 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8917 &IID_ICreateTypeInfo, (void **)ctinfo);
8918 if (FAILED(hres)) {
8919 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8920 return hres;
8923 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8925 ++This->TypeInfoCount;
8927 return S_OK;
8930 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8931 LPOLESTR name)
8933 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8935 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8937 if (!name)
8938 return E_INVALIDARG;
8940 This->Name = TLB_append_str(&This->name_list, name);
8942 return S_OK;
8945 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8946 WORD majorVerNum, WORD minorVerNum)
8948 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8950 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8952 This->ver_major = majorVerNum;
8953 This->ver_minor = minorVerNum;
8955 return S_OK;
8958 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8959 REFGUID guid)
8961 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8963 TRACE("%p %s\n", This, debugstr_guid(guid));
8965 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8967 return S_OK;
8970 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8971 LPOLESTR doc)
8973 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8975 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8977 if (!doc)
8978 return E_INVALIDARG;
8980 This->DocString = TLB_append_str(&This->string_list, doc);
8982 return S_OK;
8985 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8986 LPOLESTR helpFileName)
8988 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8990 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8992 if (!helpFileName)
8993 return E_INVALIDARG;
8995 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8997 return S_OK;
9000 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9001 DWORD helpContext)
9003 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9005 TRACE("%p %d\n", This, helpContext);
9007 This->dwHelpContext = helpContext;
9009 return S_OK;
9012 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9013 LCID lcid)
9015 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9017 TRACE("%p %x\n", This, lcid);
9019 This->set_lcid = lcid;
9021 return S_OK;
9024 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9025 UINT libFlags)
9027 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9029 TRACE("%p %x\n", This, libFlags);
9031 This->libflags = libFlags;
9033 return S_OK;
9036 typedef struct tagWMSFT_SegContents {
9037 DWORD len;
9038 void *data;
9039 } WMSFT_SegContents;
9041 typedef struct tagWMSFT_TLBFile {
9042 MSFT_Header header;
9043 WMSFT_SegContents typeinfo_seg;
9044 WMSFT_SegContents impfile_seg;
9045 WMSFT_SegContents impinfo_seg;
9046 WMSFT_SegContents ref_seg;
9047 WMSFT_SegContents guidhash_seg;
9048 WMSFT_SegContents guid_seg;
9049 WMSFT_SegContents namehash_seg;
9050 WMSFT_SegContents name_seg;
9051 WMSFT_SegContents string_seg;
9052 WMSFT_SegContents typdesc_seg;
9053 WMSFT_SegContents arraydesc_seg;
9054 WMSFT_SegContents custdata_seg;
9055 WMSFT_SegContents cdguids_seg;
9056 MSFT_SegDir segdir;
9057 WMSFT_SegContents aux_seg;
9058 } WMSFT_TLBFile;
9060 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9061 WMSFT_TLBFile *file)
9063 TLBString *str;
9064 UINT last_offs;
9065 char *data;
9067 file->string_seg.len = 0;
9068 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9069 int size;
9071 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
9072 if (size == 0)
9073 return E_UNEXPECTED;
9075 size += sizeof(INT16);
9076 if (size % 4)
9077 size = (size + 4) & ~0x3;
9078 if (size < 8)
9079 size = 8;
9081 file->string_seg.len += size;
9083 /* temporarily use str->offset to store the length of the aligned,
9084 * converted string */
9085 str->offset = size;
9088 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9090 last_offs = 0;
9091 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9092 int size;
9094 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
9095 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9096 if (size == 0) {
9097 heap_free(file->string_seg.data);
9098 return E_UNEXPECTED;
9101 *((INT16*)data) = size;
9103 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9105 size = str->offset;
9106 data += size;
9107 str->offset = last_offs;
9108 last_offs += size;
9111 return S_OK;
9114 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9115 WMSFT_TLBFile *file)
9117 TLBString *str;
9118 UINT last_offs;
9119 char *data;
9120 MSFT_NameIntro *last_intro = NULL;
9122 file->header.nametablecount = 0;
9123 file->header.nametablechars = 0;
9125 file->name_seg.len = 0;
9126 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9127 int size;
9129 size = strlenW(str->str);
9130 file->header.nametablechars += size;
9131 file->header.nametablecount++;
9133 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9134 if (size == 0)
9135 return E_UNEXPECTED;
9137 size += sizeof(MSFT_NameIntro);
9138 if (size % 4)
9139 size = (size + 4) & ~0x3;
9140 if (size < 8)
9141 size = 8;
9143 file->name_seg.len += size;
9145 /* temporarily use str->offset to store the length of the aligned,
9146 * converted string */
9147 str->offset = size;
9150 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9151 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9153 last_offs = 0;
9154 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9155 int size, hash;
9156 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9158 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
9159 data + sizeof(MSFT_NameIntro),
9160 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9161 if (size == 0) {
9162 heap_free(file->name_seg.data);
9163 return E_UNEXPECTED;
9165 data[sizeof(MSFT_NameIntro) + size] = '\0';
9167 intro->hreftype = -1; /* TODO? */
9168 intro->namelen = size & 0xFF;
9169 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9170 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9171 intro->namelen |= hash << 16;
9172 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9173 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9175 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9176 str->offset - size - sizeof(MSFT_NameIntro));
9178 /* update str->offset to actual value to use in other
9179 * compilation functions that require positions within
9180 * the string table */
9181 last_intro = intro;
9182 size = str->offset;
9183 data += size;
9184 str->offset = last_offs;
9185 last_offs += size;
9188 if(last_intro)
9189 last_intro->hreftype = 0; /* last one is 0? */
9191 return S_OK;
9194 static inline int hash_guid(GUID *guid)
9196 int i, hash = 0;
9198 for (i = 0; i < 8; i ++)
9199 hash ^= ((const short *)guid)[i];
9201 return hash & 0x1f;
9204 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9206 TLBGuid *guid;
9207 MSFT_GuidEntry *entry;
9208 DWORD offs;
9209 int hash_key, *guidhashtab;
9211 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9212 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9214 entry = file->guid_seg.data;
9215 offs = 0;
9216 guidhashtab = file->guidhash_seg.data;
9217 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9218 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9219 entry->hreftype = guid->hreftype;
9221 hash_key = hash_guid(&guid->guid);
9222 entry->next_hash = guidhashtab[hash_key];
9223 guidhashtab[hash_key] = offs;
9225 guid->offset = offs;
9226 offs += sizeof(MSFT_GuidEntry);
9227 ++entry;
9230 return S_OK;
9233 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9235 VARIANT v = *value;
9236 VARTYPE arg_type = V_VT(value);
9237 int mask = 0;
9238 HRESULT hres;
9239 DWORD ret = file->custdata_seg.len;
9241 if(arg_type == VT_INT)
9242 arg_type = VT_I4;
9243 if(arg_type == VT_UINT)
9244 arg_type = VT_UI4;
9246 v = *value;
9247 if(V_VT(value) != arg_type) {
9248 hres = VariantChangeType(&v, value, 0, arg_type);
9249 if(FAILED(hres)){
9250 ERR("VariantChangeType failed: %08x\n", hres);
9251 return -1;
9255 /* Check if default value can be stored in-place */
9256 switch(arg_type){
9257 case VT_I4:
9258 case VT_UI4:
9259 mask = 0x3ffffff;
9260 if(V_UI4(&v) > 0x3ffffff)
9261 break;
9262 /* fall through */
9263 case VT_I1:
9264 case VT_UI1:
9265 case VT_BOOL:
9266 if(!mask)
9267 mask = 0xff;
9268 /* fall through */
9269 case VT_I2:
9270 case VT_UI2:
9271 if(!mask)
9272 mask = 0xffff;
9273 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9276 /* have to allocate space in custdata_seg */
9277 switch(arg_type) {
9278 case VT_I4:
9279 case VT_R4:
9280 case VT_UI4:
9281 case VT_INT:
9282 case VT_UINT:
9283 case VT_HRESULT:
9284 case VT_PTR: {
9285 /* Construct the data to be allocated */
9286 int *data;
9288 if(file->custdata_seg.data){
9289 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9290 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9291 file->custdata_seg.len += sizeof(int) * 2;
9292 }else{
9293 file->custdata_seg.len = sizeof(int) * 2;
9294 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9297 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9298 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9300 /* TODO: Check if the encoded data is already present in custdata_seg */
9302 return ret;
9305 case VT_BSTR: {
9306 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9307 char *data;
9309 if(file->custdata_seg.data){
9310 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9311 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9312 file->custdata_seg.len += len;
9313 }else{
9314 file->custdata_seg.len = len;
9315 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9318 *((unsigned short *)data) = V_VT(value);
9319 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9320 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9321 if(V_BSTR(&v)[i] <= 0x7f)
9322 data[i+6] = V_BSTR(&v)[i];
9323 else
9324 data[i+6] = '?';
9326 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9327 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9328 data[i] = 0x57;
9330 /* TODO: Check if the encoded data is already present in custdata_seg */
9332 return ret;
9334 default:
9335 FIXME("Argument type not yet handled\n");
9336 return -1;
9340 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9342 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9344 DWORD offs = file->arraydesc_seg.len;
9345 DWORD *encoded;
9346 USHORT i;
9348 /* TODO: we should check for duplicates, but that's harder because each
9349 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9350 * at the library-level) */
9352 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9353 if(!file->arraydesc_seg.data)
9354 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9355 else
9356 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9357 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9359 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9360 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9361 for(i = 0; i < desc->cDims; ++i){
9362 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9363 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9366 return offs;
9369 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9371 DWORD junk;
9372 INT16 junk2;
9373 DWORD offs = 0;
9374 DWORD encoded[2];
9375 VARTYPE vt, subtype;
9376 char *data;
9378 if(!desc)
9379 return -1;
9381 if(!out_mix)
9382 out_mix = &junk;
9383 if(!out_size)
9384 out_size = &junk2;
9386 vt = desc->vt & VT_TYPEMASK;
9388 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9389 DWORD mix;
9390 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9391 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9392 *out_mix = 0x7FFF;
9393 *out_size += 2 * sizeof(DWORD);
9394 }else if(vt == VT_CARRAY){
9395 encoded[0] = desc->vt | (0x7FFE << 16);
9396 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9397 *out_mix = 0x7FFE;
9398 }else if(vt == VT_USERDEFINED){
9399 encoded[0] = desc->vt | (0x7FFF << 16);
9400 encoded[1] = desc->u.hreftype;
9401 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9402 }else{
9403 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9405 switch(vt){
9406 case VT_INT:
9407 subtype = VT_I4;
9408 break;
9409 case VT_UINT:
9410 subtype = VT_UI4;
9411 break;
9412 case VT_VOID:
9413 subtype = VT_EMPTY;
9414 break;
9415 default:
9416 subtype = vt;
9417 break;
9420 *out_mix = subtype;
9421 return 0x80000000 | (subtype << 16) | desc->vt;
9424 data = file->typdesc_seg.data;
9425 while(offs < file->typdesc_seg.len){
9426 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9427 return offs;
9428 offs += sizeof(encoded);
9431 file->typdesc_seg.len += sizeof(encoded);
9432 if(!file->typdesc_seg.data)
9433 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9434 else
9435 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9437 memcpy(&data[offs], encoded, sizeof(encoded));
9439 return offs;
9442 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9444 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9445 DWORD ret = cdguids_seg->len, offs;
9446 MSFT_CDGuid *cdguid;
9447 TLBCustData *cd;
9449 if(list_empty(custdata_list))
9450 return -1;
9452 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9453 if(!cdguids_seg->data){
9454 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9455 }else {
9456 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9457 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9460 offs = ret + sizeof(MSFT_CDGuid);
9461 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9462 cdguid->GuidOffset = cd->guid->offset;
9463 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9464 cdguid->next = offs;
9465 offs += sizeof(MSFT_CDGuid);
9466 ++cdguid;
9469 --cdguid;
9470 cdguid->next = -1;
9472 return ret;
9475 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9476 WMSFT_TLBFile *file)
9478 WMSFT_SegContents *aux_seg = &file->aux_seg;
9479 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9480 MSFT_VarRecord *varrecord;
9481 MSFT_FuncRecord *funcrecord;
9482 MEMBERID *memid;
9483 DWORD *name, *offsets, offs;
9485 for(i = 0; i < info->typeattr.cFuncs; ++i){
9486 TLBFuncDesc *desc = &info->funcdescs[i];
9488 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9490 /* optional fields */
9491 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9492 if(!list_empty(&desc->custdata_list))
9493 recorded_size += 7 * sizeof(INT);
9494 else if(desc->HelpStringContext != 0)
9495 recorded_size += 6 * sizeof(INT);
9496 /* res9? resA? */
9497 else if(desc->Entry)
9498 recorded_size += 3 * sizeof(INT);
9499 else if(desc->HelpString)
9500 recorded_size += 2 * sizeof(INT);
9501 else if(desc->helpcontext)
9502 recorded_size += sizeof(INT);
9504 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9506 for(j = 0; j < desc->funcdesc.cParams; ++j){
9507 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9508 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9509 break;
9513 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9516 for(i = 0; i < info->typeattr.cVars; ++i){
9517 TLBVarDesc *desc = &info->vardescs[i];
9519 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9521 /* optional fields */
9522 if(desc->HelpStringContext != 0)
9523 recorded_size += 5 * sizeof(INT);
9524 else if(!list_empty(&desc->custdata_list))
9525 recorded_size += 4 * sizeof(INT);
9526 /* res9? */
9527 else if(desc->HelpString)
9528 recorded_size += 2 * sizeof(INT);
9529 else if(desc->HelpContext != 0)
9530 recorded_size += sizeof(INT);
9532 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9535 if(!recorded_size && !extra_size)
9536 return ret;
9538 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9540 aux_seg->len += recorded_size + extra_size;
9542 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9544 if(aux_seg->data)
9545 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9546 else
9547 aux_seg->data = heap_alloc(aux_seg->len);
9549 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9551 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9552 offs = 0;
9554 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9555 for(i = 0; i < info->typeattr.cFuncs; ++i){
9556 TLBFuncDesc *desc = &info->funcdescs[i];
9557 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9559 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9560 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9561 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9562 funcrecord->VtableOffset = desc->funcdesc.oVft;
9564 /* FKCCIC:
9565 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9566 * ^^^funckind
9567 * ^^^ ^invkind
9568 * ^has_cust_data
9569 * ^^^^callconv
9570 * ^has_param_defaults
9571 * ^oEntry_is_intresource
9573 funcrecord->FKCCIC =
9574 desc->funcdesc.funckind |
9575 (desc->funcdesc.invkind << 3) |
9576 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9577 (desc->funcdesc.callconv << 8);
9579 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9580 funcrecord->FKCCIC |= 0x2000;
9582 for(j = 0; j < desc->funcdesc.cParams; ++j){
9583 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9584 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9585 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9588 if(paramdefault_size > 0)
9589 funcrecord->FKCCIC |= 0x1000;
9591 funcrecord->nrargs = desc->funcdesc.cParams;
9592 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9594 /* optional fields */
9595 /* res9? resA? */
9596 if(!list_empty(&desc->custdata_list)){
9597 size += 7 * sizeof(INT);
9598 funcrecord->HelpContext = desc->helpcontext;
9599 if(desc->HelpString)
9600 funcrecord->oHelpString = desc->HelpString->offset;
9601 else
9602 funcrecord->oHelpString = -1;
9603 if(!desc->Entry)
9604 funcrecord->oEntry = -1;
9605 else if(IS_INTRESOURCE(desc->Entry))
9606 funcrecord->oEntry = LOWORD(desc->Entry);
9607 else
9608 funcrecord->oEntry = desc->Entry->offset;
9609 funcrecord->res9 = -1;
9610 funcrecord->resA = -1;
9611 funcrecord->HelpStringContext = desc->HelpStringContext;
9612 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9613 }else if(desc->HelpStringContext != 0){
9614 size += 6 * sizeof(INT);
9615 funcrecord->HelpContext = desc->helpcontext;
9616 if(desc->HelpString)
9617 funcrecord->oHelpString = desc->HelpString->offset;
9618 else
9619 funcrecord->oHelpString = -1;
9620 if(!desc->Entry)
9621 funcrecord->oEntry = -1;
9622 else if(IS_INTRESOURCE(desc->Entry))
9623 funcrecord->oEntry = LOWORD(desc->Entry);
9624 else
9625 funcrecord->oEntry = desc->Entry->offset;
9626 funcrecord->res9 = -1;
9627 funcrecord->resA = -1;
9628 funcrecord->HelpStringContext = desc->HelpStringContext;
9629 }else if(desc->Entry){
9630 size += 3 * sizeof(INT);
9631 funcrecord->HelpContext = desc->helpcontext;
9632 if(desc->HelpString)
9633 funcrecord->oHelpString = desc->HelpString->offset;
9634 else
9635 funcrecord->oHelpString = -1;
9636 if(!desc->Entry)
9637 funcrecord->oEntry = -1;
9638 else if(IS_INTRESOURCE(desc->Entry))
9639 funcrecord->oEntry = LOWORD(desc->Entry);
9640 else
9641 funcrecord->oEntry = desc->Entry->offset;
9642 }else if(desc->HelpString){
9643 size += 2 * sizeof(INT);
9644 funcrecord->HelpContext = desc->helpcontext;
9645 funcrecord->oHelpString = desc->HelpString->offset;
9646 }else if(desc->helpcontext){
9647 size += sizeof(INT);
9648 funcrecord->HelpContext = desc->helpcontext;
9651 paramdefault = (DWORD*)((char *)funcrecord + size);
9652 size += paramdefault_size;
9654 for(j = 0; j < desc->funcdesc.cParams; ++j){
9655 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9657 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9658 if(desc->pParamDesc[j].Name)
9659 info->oName = desc->pParamDesc[j].Name->offset;
9660 else
9661 info->oName = -1;
9662 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9664 if(paramdefault_size){
9665 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9666 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9667 else if(paramdefault_size)
9668 *paramdefault = -1;
9669 ++paramdefault;
9672 size += sizeof(MSFT_ParameterInfo);
9675 funcrecord->Info = size | (i << 16); /* is it just the index? */
9677 *offsets = offs;
9678 offs += size;
9679 ++offsets;
9681 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9684 varrecord = (MSFT_VarRecord*)funcrecord;
9685 for(i = 0; i < info->typeattr.cVars; ++i){
9686 TLBVarDesc *desc = &info->vardescs[i];
9687 DWORD size = 5 * sizeof(INT);
9689 varrecord->vardescsize = sizeof(desc->vardesc);
9690 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9691 varrecord->Flags = desc->vardesc.wVarFlags;
9692 varrecord->VarKind = desc->vardesc.varkind;
9694 if(desc->vardesc.varkind == VAR_CONST){
9695 varrecord->vardescsize += sizeof(VARIANT);
9696 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9697 }else
9698 varrecord->OffsValue = desc->vardesc.u.oInst;
9700 /* res9? */
9701 if(desc->HelpStringContext != 0){
9702 size += 5 * sizeof(INT);
9703 varrecord->HelpContext = desc->HelpContext;
9704 if(desc->HelpString)
9705 varrecord->HelpString = desc->HelpString->offset;
9706 else
9707 varrecord->HelpString = -1;
9708 varrecord->res9 = -1;
9709 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9710 varrecord->HelpStringContext = desc->HelpStringContext;
9711 }else if(!list_empty(&desc->custdata_list)){
9712 size += 4 * sizeof(INT);
9713 varrecord->HelpContext = desc->HelpContext;
9714 if(desc->HelpString)
9715 varrecord->HelpString = desc->HelpString->offset;
9716 else
9717 varrecord->HelpString = -1;
9718 varrecord->res9 = -1;
9719 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9720 }else if(desc->HelpString){
9721 size += 2 * sizeof(INT);
9722 varrecord->HelpContext = desc->HelpContext;
9723 if(desc->HelpString)
9724 varrecord->HelpString = desc->HelpString->offset;
9725 else
9726 varrecord->HelpString = -1;
9727 }else if(desc->HelpContext != 0){
9728 size += sizeof(INT);
9729 varrecord->HelpContext = desc->HelpContext;
9732 varrecord->Info = size | (i << 16);
9734 *offsets = offs;
9735 offs += size;
9736 ++offsets;
9738 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9741 memid = (MEMBERID*)varrecord;
9742 for(i = 0; i < info->typeattr.cFuncs; ++i){
9743 TLBFuncDesc *desc = &info->funcdescs[i];
9744 *memid = desc->funcdesc.memid;
9745 ++memid;
9747 for(i = 0; i < info->typeattr.cVars; ++i){
9748 TLBVarDesc *desc = &info->vardescs[i];
9749 *memid = desc->vardesc.memid;
9750 ++memid;
9753 name = (UINT*)memid;
9754 for(i = 0; i < info->typeattr.cFuncs; ++i){
9755 TLBFuncDesc *desc = &info->funcdescs[i];
9756 if(desc->Name)
9757 *name = desc->Name->offset;
9758 else
9759 *name = -1;
9760 ++name;
9762 for(i = 0; i < info->typeattr.cVars; ++i){
9763 TLBVarDesc *desc = &info->vardescs[i];
9764 if(desc->Name)
9765 *name = desc->Name->offset;
9766 else
9767 *name = -1;
9768 ++name;
9771 return ret;
9774 typedef struct tagWMSFT_RefChunk {
9775 DWORD href;
9776 DWORD res04;
9777 DWORD res08;
9778 DWORD next;
9779 } WMSFT_RefChunk;
9781 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9783 DWORD offs = file->ref_seg.len, i;
9784 WMSFT_RefChunk *chunk;
9786 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9787 if(!file->ref_seg.data)
9788 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9789 else
9790 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9792 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9794 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9795 chunk->href = info->impltypes[i].hRef;
9796 chunk->res04 = info->impltypes[i].implflags;
9797 chunk->res08 = -1;
9798 if(i < info->typeattr.cImplTypes - 1)
9799 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9800 else
9801 chunk->next = -1;
9802 ++chunk;
9805 return offs;
9808 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9810 DWORD size;
9812 size = sizeof(MSFT_TypeInfoBase);
9814 if(data){
9815 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9816 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9817 base->typekind = TKIND_DISPATCH;
9818 else
9819 base->typekind = info->typeattr.typekind;
9820 base->typekind |= index << 16; /* TODO: There are some other flags here */
9821 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9822 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9823 base->res2 = 0;
9824 base->res3 = 0;
9825 base->res4 = 3;
9826 base->res5 = 0;
9827 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9828 base->res7 = 0;
9829 base->res8 = 0;
9830 base->res9 = 0;
9831 base->resA = 0;
9832 if(info->guid)
9833 base->posguid = info->guid->offset;
9834 else
9835 base->posguid = -1;
9836 base->flags = info->typeattr.wTypeFlags;
9837 if(info->Name) {
9838 base->NameOffset = info->Name->offset;
9840 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9841 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9842 }else {
9843 base->NameOffset = -1;
9845 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9846 if(info->DocString)
9847 base->docstringoffs = info->DocString->offset;
9848 else
9849 base->docstringoffs = -1;
9850 base->helpstringcontext = info->dwHelpStringContext;
9851 base->helpcontext = info->dwHelpContext;
9852 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9853 base->cImplTypes = info->typeattr.cImplTypes;
9854 base->cbSizeVft = info->typeattr.cbSizeVft;
9855 base->size = info->typeattr.cbSizeInstance;
9856 if(info->typeattr.typekind == TKIND_COCLASS){
9857 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9858 }else if(info->typeattr.typekind == TKIND_ALIAS){
9859 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9860 }else if(info->typeattr.typekind == TKIND_MODULE){
9861 if(info->DllName)
9862 base->datatype1 = info->DllName->offset;
9863 else
9864 base->datatype1 = -1;
9865 }else{
9866 if(info->typeattr.cImplTypes > 0)
9867 base->datatype1 = info->impltypes[0].hRef;
9868 else
9869 base->datatype1 = -1;
9871 base->datatype2 = index; /* FIXME: i think there's more here */
9872 base->res18 = 0;
9873 base->res19 = -1;
9876 return size;
9879 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9881 UINT i;
9883 file->typeinfo_seg.len = 0;
9884 for(i = 0; i < This->TypeInfoCount; ++i){
9885 ITypeInfoImpl *info = This->typeinfos[i];
9886 *junk = file->typeinfo_seg.len;
9887 ++junk;
9888 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9891 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9892 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9894 file->aux_seg.len = 0;
9895 file->aux_seg.data = NULL;
9897 file->typeinfo_seg.len = 0;
9898 for(i = 0; i < This->TypeInfoCount; ++i){
9899 ITypeInfoImpl *info = This->typeinfos[i];
9900 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9901 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9905 typedef struct tagWMSFT_ImpFile {
9906 INT guid_offs;
9907 LCID lcid;
9908 DWORD version;
9909 } WMSFT_ImpFile;
9911 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9913 TLBImpLib *implib;
9914 WMSFT_ImpFile *impfile;
9915 char *data;
9916 DWORD last_offs = 0;
9918 file->impfile_seg.len = 0;
9919 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9920 int size = 0;
9922 if(implib->name){
9923 WCHAR *path = strrchrW(implib->name, '\\');
9924 if(path)
9925 ++path;
9926 else
9927 path = implib->name;
9928 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9929 if (size == 0)
9930 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9933 size += sizeof(INT16);
9934 if (size % 4)
9935 size = (size + 4) & ~0x3;
9936 if (size < 8)
9937 size = 8;
9939 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9942 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9944 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9945 int strlen = 0, size;
9947 impfile = (WMSFT_ImpFile*)data;
9948 impfile->guid_offs = implib->guid->offset;
9949 impfile->lcid = implib->lcid;
9950 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9952 data += sizeof(WMSFT_ImpFile);
9954 if(implib->name){
9955 WCHAR *path= strrchrW(implib->name, '\\');
9956 if(path)
9957 ++path;
9958 else
9959 path = implib->name;
9960 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9961 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9962 if (strlen == 0)
9963 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9966 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9968 size = strlen + sizeof(INT16);
9969 if (size % 4)
9970 size = (size + 4) & ~0x3;
9971 if (size < 8)
9972 size = 8;
9973 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9975 data += size;
9976 implib->offset = last_offs;
9977 last_offs += size + sizeof(WMSFT_ImpFile);
9981 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9983 MSFT_ImpInfo *info;
9984 TLBRefType *ref_type;
9985 UINT i = 0;
9987 WMSFT_compile_impfile(This, file);
9989 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9990 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9992 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9993 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9994 if(ref_type->index == TLB_REF_USE_GUID){
9995 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9996 info->oGuid = ref_type->guid->offset;
9997 }else
9998 info->oGuid = ref_type->index;
9999 info->oImpFile = ref_type->pImpTLInfo->offset;
10000 ++i;
10001 ++info;
10005 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10007 file->guidhash_seg.len = 0x80;
10008 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
10009 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10012 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10014 file->namehash_seg.len = 0x200;
10015 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10016 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10019 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10021 if(contents && contents->len){
10022 segdir->offset = *running_offset;
10023 segdir->length = contents->len;
10024 *running_offset += segdir->length;
10025 }else{
10026 segdir->offset = -1;
10027 segdir->length = 0;
10030 /* TODO: do these ever change? */
10031 segdir->res08 = -1;
10032 segdir->res0c = 0xf;
10035 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10037 DWORD written;
10038 if(segment)
10039 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10042 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10043 DWORD file_len)
10045 DWORD i;
10046 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10048 for(i = 0; i < This->TypeInfoCount; ++i){
10049 base->memoffset += file_len;
10050 ++base;
10053 return S_OK;
10056 static void WMSFT_free_file(WMSFT_TLBFile *file)
10058 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10059 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10060 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10061 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10062 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10063 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10064 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10065 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10066 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10067 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10068 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10069 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10070 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10071 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10074 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10076 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10077 WMSFT_TLBFile file;
10078 DWORD written, junk_size, junk_offs, running_offset;
10079 BOOL br;
10080 HANDLE outfile;
10081 HRESULT hres;
10082 DWORD *junk;
10083 UINT i;
10085 TRACE("%p\n", This);
10087 for(i = 0; i < This->TypeInfoCount; ++i)
10088 if(This->typeinfos[i]->needs_layout)
10089 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10091 memset(&file, 0, sizeof(file));
10093 file.header.magic1 = 0x5446534D;
10094 file.header.magic2 = 0x00010002;
10095 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10096 file.header.lcid2 = This->set_lcid;
10097 file.header.varflags = 0x40 | This->syskind;
10098 if (This->HelpFile)
10099 file.header.varflags |= 0x10;
10100 if (This->HelpStringDll)
10101 file.header.varflags |= HELPDLLFLAG;
10102 file.header.version = (This->ver_minor << 16) | This->ver_major;
10103 file.header.flags = This->libflags;
10104 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10105 file.header.helpcontext = This->dwHelpContext;
10106 file.header.res44 = 0x20;
10107 file.header.res48 = 0x80;
10108 file.header.dispatchpos = This->dispatch_href;
10110 WMSFT_compile_namehash(This, &file);
10111 /* do name and string compilation to get offsets for other compilations */
10112 hres = WMSFT_compile_names(This, &file);
10113 if (FAILED(hres)){
10114 WMSFT_free_file(&file);
10115 return hres;
10118 hres = WMSFT_compile_strings(This, &file);
10119 if (FAILED(hres)){
10120 WMSFT_free_file(&file);
10121 return hres;
10124 WMSFT_compile_guidhash(This, &file);
10125 hres = WMSFT_compile_guids(This, &file);
10126 if (FAILED(hres)){
10127 WMSFT_free_file(&file);
10128 return hres;
10131 if(This->HelpFile)
10132 file.header.helpfile = This->HelpFile->offset;
10133 else
10134 file.header.helpfile = -1;
10136 if(This->DocString)
10137 file.header.helpstring = This->DocString->offset;
10138 else
10139 file.header.helpstring = -1;
10141 /* do some more segment compilation */
10142 file.header.nimpinfos = list_count(&This->ref_list);
10143 file.header.nrtypeinfos = This->TypeInfoCount;
10145 if(This->Name)
10146 file.header.NameOffset = This->Name->offset;
10147 else
10148 file.header.NameOffset = -1;
10150 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10152 if(This->guid)
10153 file.header.posguid = This->guid->offset;
10154 else
10155 file.header.posguid = -1;
10157 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10158 if(file.header.varflags & HELPDLLFLAG)
10159 junk_size += sizeof(DWORD);
10160 if(junk_size){
10161 junk = heap_alloc_zero(junk_size);
10162 if(file.header.varflags & HELPDLLFLAG){
10163 *junk = This->HelpStringDll->offset;
10164 junk_offs = 1;
10165 }else
10166 junk_offs = 0;
10167 }else{
10168 junk = NULL;
10169 junk_offs = 0;
10172 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10173 WMSFT_compile_impinfo(This, &file);
10175 running_offset = 0;
10177 TRACE("header at: 0x%x\n", running_offset);
10178 running_offset += sizeof(file.header);
10180 TRACE("junk at: 0x%x\n", running_offset);
10181 running_offset += junk_size;
10183 TRACE("segdir at: 0x%x\n", running_offset);
10184 running_offset += sizeof(file.segdir);
10186 TRACE("typeinfo at: 0x%x\n", running_offset);
10187 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10189 TRACE("guidhashtab at: 0x%x\n", running_offset);
10190 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10192 TRACE("guidtab at: 0x%x\n", running_offset);
10193 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10195 TRACE("reftab at: 0x%x\n", running_offset);
10196 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10198 TRACE("impinfo at: 0x%x\n", running_offset);
10199 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10201 TRACE("impfiles at: 0x%x\n", running_offset);
10202 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10204 TRACE("namehashtab at: 0x%x\n", running_offset);
10205 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10207 TRACE("nametab at: 0x%x\n", running_offset);
10208 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10210 TRACE("stringtab at: 0x%x\n", running_offset);
10211 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10213 TRACE("typdesc at: 0x%x\n", running_offset);
10214 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10216 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10217 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10219 TRACE("custdata at: 0x%x\n", running_offset);
10220 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10222 TRACE("cdguids at: 0x%x\n", running_offset);
10223 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10225 TRACE("res0e at: 0x%x\n", running_offset);
10226 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10228 TRACE("res0f at: 0x%x\n", running_offset);
10229 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10231 TRACE("aux_seg at: 0x%x\n", running_offset);
10233 WMSFT_fixup_typeinfos(This, &file, running_offset);
10235 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10236 FILE_ATTRIBUTE_NORMAL, 0);
10237 if (outfile == INVALID_HANDLE_VALUE){
10238 WMSFT_free_file(&file);
10239 heap_free(junk);
10240 return TYPE_E_IOERROR;
10243 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10244 if (!br) {
10245 WMSFT_free_file(&file);
10246 CloseHandle(outfile);
10247 heap_free(junk);
10248 return TYPE_E_IOERROR;
10251 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10252 heap_free(junk);
10253 if (!br) {
10254 WMSFT_free_file(&file);
10255 CloseHandle(outfile);
10256 return TYPE_E_IOERROR;
10259 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10260 if (!br) {
10261 WMSFT_free_file(&file);
10262 CloseHandle(outfile);
10263 return TYPE_E_IOERROR;
10266 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10267 WMSFT_write_segment(outfile, &file.guidhash_seg);
10268 WMSFT_write_segment(outfile, &file.guid_seg);
10269 WMSFT_write_segment(outfile, &file.ref_seg);
10270 WMSFT_write_segment(outfile, &file.impinfo_seg);
10271 WMSFT_write_segment(outfile, &file.impfile_seg);
10272 WMSFT_write_segment(outfile, &file.namehash_seg);
10273 WMSFT_write_segment(outfile, &file.name_seg);
10274 WMSFT_write_segment(outfile, &file.string_seg);
10275 WMSFT_write_segment(outfile, &file.typdesc_seg);
10276 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10277 WMSFT_write_segment(outfile, &file.custdata_seg);
10278 WMSFT_write_segment(outfile, &file.cdguids_seg);
10279 WMSFT_write_segment(outfile, &file.aux_seg);
10281 WMSFT_free_file(&file);
10283 CloseHandle(outfile);
10285 return S_OK;
10288 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10289 LPOLESTR name)
10291 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10292 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10293 return E_NOTIMPL;
10296 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10297 REFGUID guid, VARIANT *varVal)
10299 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10300 TLBGuid *tlbguid;
10302 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10304 if (!guid || !varVal)
10305 return E_INVALIDARG;
10307 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10309 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10312 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10313 ULONG helpStringContext)
10315 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10316 FIXME("%p %u - stub\n", This, helpStringContext);
10317 return E_NOTIMPL;
10320 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10321 LPOLESTR filename)
10323 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10324 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10326 if (!filename)
10327 return E_INVALIDARG;
10329 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10331 return S_OK;
10334 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10335 ICreateTypeLib2_fnQueryInterface,
10336 ICreateTypeLib2_fnAddRef,
10337 ICreateTypeLib2_fnRelease,
10338 ICreateTypeLib2_fnCreateTypeInfo,
10339 ICreateTypeLib2_fnSetName,
10340 ICreateTypeLib2_fnSetVersion,
10341 ICreateTypeLib2_fnSetGuid,
10342 ICreateTypeLib2_fnSetDocString,
10343 ICreateTypeLib2_fnSetHelpFileName,
10344 ICreateTypeLib2_fnSetHelpContext,
10345 ICreateTypeLib2_fnSetLcid,
10346 ICreateTypeLib2_fnSetLibFlags,
10347 ICreateTypeLib2_fnSaveAllChanges,
10348 ICreateTypeLib2_fnDeleteTypeInfo,
10349 ICreateTypeLib2_fnSetCustData,
10350 ICreateTypeLib2_fnSetHelpStringContext,
10351 ICreateTypeLib2_fnSetHelpStringDll
10354 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10355 REFIID riid, void **object)
10357 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10359 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10362 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10364 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10366 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10369 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10371 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10373 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10376 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10377 REFGUID guid)
10379 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10381 TRACE("%p %s\n", This, debugstr_guid(guid));
10383 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10385 return S_OK;
10388 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10389 UINT typeFlags)
10391 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10392 WORD old_flags;
10393 HRESULT hres;
10395 TRACE("%p %x\n", This, typeFlags);
10397 if (typeFlags & TYPEFLAG_FDUAL) {
10398 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10399 ITypeLib *stdole;
10400 ITypeInfo *dispatch;
10401 HREFTYPE hreftype;
10402 HRESULT hres;
10404 hres = LoadTypeLib(stdole2tlb, &stdole);
10405 if(FAILED(hres))
10406 return hres;
10408 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10409 ITypeLib_Release(stdole);
10410 if(FAILED(hres))
10411 return hres;
10413 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10414 ITypeInfo_Release(dispatch);
10415 if(FAILED(hres))
10416 return hres;
10419 old_flags = This->typeattr.wTypeFlags;
10420 This->typeattr.wTypeFlags = typeFlags;
10422 hres = ICreateTypeInfo2_LayOut(iface);
10423 if (FAILED(hres)) {
10424 This->typeattr.wTypeFlags = old_flags;
10425 return hres;
10428 return S_OK;
10431 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10432 LPOLESTR doc)
10434 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10436 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10438 if (!doc)
10439 return E_INVALIDARG;
10441 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10443 return S_OK;
10446 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10447 DWORD helpContext)
10449 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10451 TRACE("%p %d\n", This, helpContext);
10453 This->dwHelpContext = helpContext;
10455 return S_OK;
10458 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10459 WORD majorVerNum, WORD minorVerNum)
10461 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10463 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10465 This->typeattr.wMajorVerNum = majorVerNum;
10466 This->typeattr.wMinorVerNum = minorVerNum;
10468 return S_OK;
10471 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10472 ITypeInfo *typeInfo, HREFTYPE *refType)
10474 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10475 UINT index;
10476 ITypeLib *container;
10477 TLBRefType *ref_type;
10478 TLBImpLib *implib;
10479 TYPEATTR *typeattr;
10480 TLIBATTR *libattr;
10481 HRESULT hres;
10483 TRACE("%p %p %p\n", This, typeInfo, refType);
10485 if (!typeInfo || !refType)
10486 return E_INVALIDARG;
10488 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10489 if (FAILED(hres))
10490 return hres;
10492 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10493 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10495 ITypeLib_Release(container);
10497 *refType = target->hreftype;
10499 return S_OK;
10502 hres = ITypeLib_GetLibAttr(container, &libattr);
10503 if (FAILED(hres)) {
10504 ITypeLib_Release(container);
10505 return hres;
10508 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10509 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10510 implib->lcid == libattr->lcid &&
10511 implib->wVersionMajor == libattr->wMajorVerNum &&
10512 implib->wVersionMinor == libattr->wMinorVerNum)
10513 break;
10516 if(&implib->entry == &This->pTypeLib->implib_list){
10517 implib = heap_alloc_zero(sizeof(TLBImpLib));
10519 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10520 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10521 implib->name = SysAllocString(our_container->path);
10522 }else{
10523 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10524 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10525 if(FAILED(hres)){
10526 implib->name = NULL;
10527 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10531 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10532 implib->lcid = libattr->lcid;
10533 implib->wVersionMajor = libattr->wMajorVerNum;
10534 implib->wVersionMinor = libattr->wMinorVerNum;
10536 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10539 ITypeLib_ReleaseTLibAttr(container, libattr);
10540 ITypeLib_Release(container);
10542 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10543 if (FAILED(hres))
10544 return hres;
10546 index = 0;
10547 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10548 if(ref_type->index == TLB_REF_USE_GUID &&
10549 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10550 ref_type->tkind == typeattr->typekind)
10551 break;
10552 ++index;
10555 if(&ref_type->entry == &This->pTypeLib->ref_list){
10556 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10558 ref_type->tkind = typeattr->typekind;
10559 ref_type->pImpTLInfo = implib;
10560 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10562 ref_type->index = TLB_REF_USE_GUID;
10564 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10566 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10569 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10571 *refType = ref_type->reference | 0x1;
10573 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10574 This->pTypeLib->dispatch_href = *refType;
10576 return S_OK;
10579 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10580 UINT index, FUNCDESC *funcDesc)
10582 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10583 TLBFuncDesc tmp_func_desc, *func_desc;
10584 int buf_size, i;
10585 char *buffer;
10586 HRESULT hres;
10588 TRACE("%p %u %p\n", This, index, funcDesc);
10590 if (!funcDesc || funcDesc->oVft & 3)
10591 return E_INVALIDARG;
10593 switch (This->typeattr.typekind) {
10594 case TKIND_MODULE:
10595 if (funcDesc->funckind != FUNC_STATIC)
10596 return TYPE_E_BADMODULEKIND;
10597 break;
10598 case TKIND_DISPATCH:
10599 if (funcDesc->funckind != FUNC_DISPATCH)
10600 return TYPE_E_BADMODULEKIND;
10601 break;
10602 default:
10603 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10604 return TYPE_E_BADMODULEKIND;
10607 if (index > This->typeattr.cFuncs)
10608 return TYPE_E_ELEMENTNOTFOUND;
10610 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10611 !funcDesc->cParams)
10612 return TYPE_E_INCONSISTENTPROPFUNCS;
10614 #ifdef _WIN64
10615 if(This->pTypeLib->syskind == SYS_WIN64 &&
10616 funcDesc->oVft % 8 != 0)
10617 return E_INVALIDARG;
10618 #endif
10620 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10621 TLBFuncDesc_Constructor(&tmp_func_desc);
10623 tmp_func_desc.funcdesc = *funcDesc;
10625 if (tmp_func_desc.funcdesc.oVft != 0)
10626 tmp_func_desc.funcdesc.oVft |= 1;
10628 if (funcDesc->cScodes && funcDesc->lprgscode) {
10629 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10630 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10631 } else {
10632 tmp_func_desc.funcdesc.lprgscode = NULL;
10633 tmp_func_desc.funcdesc.cScodes = 0;
10636 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10637 for (i = 0; i < funcDesc->cParams; ++i) {
10638 buf_size += sizeof(ELEMDESC);
10639 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10641 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10642 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10644 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10645 if (FAILED(hres)) {
10646 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10647 heap_free(tmp_func_desc.funcdesc.lprgscode);
10648 return hres;
10651 for (i = 0; i < funcDesc->cParams; ++i) {
10652 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10653 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10654 if (FAILED(hres)) {
10655 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10656 heap_free(tmp_func_desc.funcdesc.lprgscode);
10657 return hres;
10659 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10660 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10661 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10662 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10663 if (FAILED(hres)) {
10664 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10665 heap_free(tmp_func_desc.funcdesc.lprgscode);
10666 return hres;
10671 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10673 if (This->funcdescs) {
10674 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10675 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10677 if (index < This->typeattr.cFuncs) {
10678 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10679 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10680 func_desc = This->funcdescs + index;
10681 } else
10682 func_desc = This->funcdescs + This->typeattr.cFuncs;
10684 /* move custdata lists to the new memory location */
10685 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10686 if(index != i){
10687 TLBFuncDesc *fd = &This->funcdescs[i];
10688 if(fd->custdata_list.prev == fd->custdata_list.next)
10689 list_init(&fd->custdata_list);
10690 else{
10691 fd->custdata_list.prev->next = &fd->custdata_list;
10692 fd->custdata_list.next->prev = &fd->custdata_list;
10696 } else
10697 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10699 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10700 list_init(&func_desc->custdata_list);
10702 ++This->typeattr.cFuncs;
10704 This->needs_layout = TRUE;
10706 return S_OK;
10709 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10710 UINT index, HREFTYPE refType)
10712 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10713 TLBImplType *impl_type;
10714 HRESULT hres;
10716 TRACE("%p %u %d\n", This, index, refType);
10718 switch(This->typeattr.typekind){
10719 case TKIND_COCLASS: {
10720 if (index == -1) {
10721 FIXME("Unhandled index: -1\n");
10722 return E_NOTIMPL;
10725 if(index != This->typeattr.cImplTypes)
10726 return TYPE_E_ELEMENTNOTFOUND;
10728 break;
10730 case TKIND_INTERFACE:
10731 case TKIND_DISPATCH:
10732 if (index != 0 || This->typeattr.cImplTypes)
10733 return TYPE_E_ELEMENTNOTFOUND;
10734 break;
10735 default:
10736 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10737 return E_NOTIMPL;
10740 if (This->impltypes){
10741 UINT i;
10743 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10744 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10746 if (index < This->typeattr.cImplTypes) {
10747 memmove(This->impltypes + index + 1, This->impltypes + index,
10748 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10749 impl_type = This->impltypes + index;
10750 } else
10751 impl_type = This->impltypes + This->typeattr.cImplTypes;
10753 /* move custdata lists to the new memory location */
10754 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10755 if(index != i){
10756 TLBImplType *it = &This->impltypes[i];
10757 if(it->custdata_list.prev == it->custdata_list.next)
10758 list_init(&it->custdata_list);
10759 else{
10760 it->custdata_list.prev->next = &it->custdata_list;
10761 it->custdata_list.next->prev = &it->custdata_list;
10765 } else
10766 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10768 memset(impl_type, 0, sizeof(TLBImplType));
10769 TLBImplType_Constructor(impl_type);
10770 impl_type->hRef = refType;
10772 ++This->typeattr.cImplTypes;
10774 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10775 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10777 hres = ICreateTypeInfo2_LayOut(iface);
10778 if (FAILED(hres))
10779 return hres;
10781 return S_OK;
10784 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10785 UINT index, INT implTypeFlags)
10787 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10788 TLBImplType *impl_type = &This->impltypes[index];
10790 TRACE("%p %u %x\n", This, index, implTypeFlags);
10792 if (This->typeattr.typekind != TKIND_COCLASS)
10793 return TYPE_E_BADMODULEKIND;
10795 if (index >= This->typeattr.cImplTypes)
10796 return TYPE_E_ELEMENTNOTFOUND;
10798 impl_type->implflags = implTypeFlags;
10800 return S_OK;
10803 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10804 WORD alignment)
10806 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10808 TRACE("%p %d\n", This, alignment);
10810 This->typeattr.cbAlignment = alignment;
10812 return S_OK;
10815 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10816 LPOLESTR schema)
10818 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10820 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10822 if (!schema)
10823 return E_INVALIDARG;
10825 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10827 This->typeattr.lpstrSchema = This->Schema->str;
10829 return S_OK;
10832 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10833 UINT index, VARDESC *varDesc)
10835 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10836 TLBVarDesc *var_desc;
10838 TRACE("%p %u %p\n", This, index, varDesc);
10840 if (This->vardescs){
10841 UINT i;
10843 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10844 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10846 if (index < This->typeattr.cVars) {
10847 memmove(This->vardescs + index + 1, This->vardescs + index,
10848 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10849 var_desc = This->vardescs + index;
10850 } else
10851 var_desc = This->vardescs + This->typeattr.cVars;
10853 /* move custdata lists to the new memory location */
10854 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10855 if(index != i){
10856 TLBVarDesc *var = &This->vardescs[i];
10857 if(var->custdata_list.prev == var->custdata_list.next)
10858 list_init(&var->custdata_list);
10859 else{
10860 var->custdata_list.prev->next = &var->custdata_list;
10861 var->custdata_list.next->prev = &var->custdata_list;
10865 } else
10866 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10868 TLBVarDesc_Constructor(var_desc);
10869 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10870 var_desc->vardesc = *var_desc->vardesc_create;
10872 ++This->typeattr.cVars;
10874 This->needs_layout = TRUE;
10876 return S_OK;
10879 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10880 UINT index, LPOLESTR *names, UINT numNames)
10882 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10883 TLBFuncDesc *func_desc = &This->funcdescs[index];
10884 int i;
10886 TRACE("%p %u %p %u\n", This, index, names, numNames);
10888 if (!names)
10889 return E_INVALIDARG;
10891 if (index >= This->typeattr.cFuncs || numNames == 0)
10892 return TYPE_E_ELEMENTNOTFOUND;
10894 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10895 if(numNames > func_desc->funcdesc.cParams)
10896 return TYPE_E_ELEMENTNOTFOUND;
10897 } else
10898 if(numNames > func_desc->funcdesc.cParams + 1)
10899 return TYPE_E_ELEMENTNOTFOUND;
10901 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10902 TLBFuncDesc *iter = &This->funcdescs[i];
10903 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10904 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10905 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10906 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10907 continue;
10908 return TYPE_E_AMBIGUOUSNAME;
10912 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10914 for (i = 1; i < numNames; ++i) {
10915 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10916 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10919 return S_OK;
10922 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10923 UINT index, LPOLESTR name)
10925 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10927 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10929 if(!name)
10930 return E_INVALIDARG;
10932 if(index >= This->typeattr.cVars)
10933 return TYPE_E_ELEMENTNOTFOUND;
10935 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10936 return S_OK;
10939 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10940 TYPEDESC *tdescAlias)
10942 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10943 HRESULT hr;
10945 TRACE("%p %p\n", This, tdescAlias);
10947 if(!tdescAlias)
10948 return E_INVALIDARG;
10950 if(This->typeattr.typekind != TKIND_ALIAS)
10951 return TYPE_E_BADMODULEKIND;
10953 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
10954 if(FAILED(hr))
10955 return hr;
10957 heap_free(This->tdescAlias);
10958 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10959 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10961 return S_OK;
10964 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10965 UINT index, LPOLESTR dllName, LPOLESTR procName)
10967 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10968 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10969 return E_NOTIMPL;
10972 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10973 UINT index, LPOLESTR docString)
10975 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10976 TLBFuncDesc *func_desc = &This->funcdescs[index];
10978 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10980 if(!docString)
10981 return E_INVALIDARG;
10983 if(index >= This->typeattr.cFuncs)
10984 return TYPE_E_ELEMENTNOTFOUND;
10986 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10988 return S_OK;
10991 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10992 UINT index, LPOLESTR docString)
10994 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10995 TLBVarDesc *var_desc = &This->vardescs[index];
10997 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10999 if(!docString)
11000 return E_INVALIDARG;
11002 if(index >= This->typeattr.cVars)
11003 return TYPE_E_ELEMENTNOTFOUND;
11005 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11007 return S_OK;
11010 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11011 UINT index, DWORD helpContext)
11013 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11014 TLBFuncDesc *func_desc = &This->funcdescs[index];
11016 TRACE("%p %u %d\n", This, index, helpContext);
11018 if(index >= This->typeattr.cFuncs)
11019 return TYPE_E_ELEMENTNOTFOUND;
11021 func_desc->helpcontext = helpContext;
11023 return S_OK;
11026 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11027 UINT index, DWORD helpContext)
11029 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11030 TLBVarDesc *var_desc = &This->vardescs[index];
11032 TRACE("%p %u %d\n", This, index, helpContext);
11034 if(index >= This->typeattr.cVars)
11035 return TYPE_E_ELEMENTNOTFOUND;
11037 var_desc->HelpContext = helpContext;
11039 return S_OK;
11042 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11043 UINT index, BSTR bstrMops)
11045 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11046 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11047 return E_NOTIMPL;
11050 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11051 IDLDESC *idlDesc)
11053 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11055 TRACE("%p %p\n", This, idlDesc);
11057 if (!idlDesc)
11058 return E_INVALIDARG;
11060 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11061 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11063 return S_OK;
11066 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11068 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11069 ITypeInfo *tinfo;
11070 TLBFuncDesc *func_desc;
11071 UINT user_vft = 0, i, depth = 0;
11072 HRESULT hres = S_OK;
11074 TRACE("%p\n", This);
11076 This->needs_layout = FALSE;
11078 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
11079 if (FAILED(hres))
11080 return hres;
11082 if (This->typeattr.typekind == TKIND_INTERFACE) {
11083 ITypeInfo *inh;
11084 TYPEATTR *attr;
11085 HREFTYPE inh_href;
11087 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11089 if (SUCCEEDED(hres)) {
11090 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
11092 if (SUCCEEDED(hres)) {
11093 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11094 if (FAILED(hres)) {
11095 ITypeInfo_Release(inh);
11096 ITypeInfo_Release(tinfo);
11097 return hres;
11099 This->typeattr.cbSizeVft = attr->cbSizeVft;
11100 ITypeInfo_ReleaseTypeAttr(inh, attr);
11103 ++depth;
11104 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11105 if(SUCCEEDED(hres)){
11106 ITypeInfo *next;
11107 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11108 if(SUCCEEDED(hres)){
11109 ITypeInfo_Release(inh);
11110 inh = next;
11113 }while(SUCCEEDED(hres));
11114 hres = S_OK;
11116 ITypeInfo_Release(inh);
11117 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11118 This->typeattr.cbSizeVft = 0;
11119 hres = S_OK;
11120 } else {
11121 ITypeInfo_Release(tinfo);
11122 return hres;
11124 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11125 This->typeattr.cbSizeVft = 0;
11126 hres = S_OK;
11127 } else {
11128 ITypeInfo_Release(tinfo);
11129 return hres;
11131 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11132 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11133 else
11134 This->typeattr.cbSizeVft = 0;
11136 func_desc = This->funcdescs;
11137 i = 0;
11138 while (i < This->typeattr.cFuncs) {
11139 if (!(func_desc->funcdesc.oVft & 0x1))
11140 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11142 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11143 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11145 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11147 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11148 TLBFuncDesc *iter;
11149 UINT j = 0;
11150 BOOL reset = FALSE;
11152 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11154 iter = This->funcdescs;
11155 while (j < This->typeattr.cFuncs) {
11156 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11157 if (!reset) {
11158 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11159 reset = TRUE;
11160 } else
11161 ++func_desc->funcdesc.memid;
11162 iter = This->funcdescs;
11163 j = 0;
11164 } else {
11165 ++iter;
11166 ++j;
11171 ++func_desc;
11172 ++i;
11175 if (user_vft > This->typeattr.cbSizeVft)
11176 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11178 for(i = 0; i < This->typeattr.cVars; ++i){
11179 TLBVarDesc *var_desc = &This->vardescs[i];
11180 if(var_desc->vardesc.memid == MEMBERID_NIL){
11181 UINT j = 0;
11182 BOOL reset = FALSE;
11183 TLBVarDesc *iter;
11185 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11187 iter = This->vardescs;
11188 while (j < This->typeattr.cVars) {
11189 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11190 if (!reset) {
11191 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11192 reset = TRUE;
11193 } else
11194 ++var_desc->vardesc.memid;
11195 iter = This->vardescs;
11196 j = 0;
11197 } else {
11198 ++iter;
11199 ++j;
11205 ITypeInfo_Release(tinfo);
11206 return hres;
11209 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11210 UINT index)
11212 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11213 FIXME("%p %u - stub\n", This, index);
11214 return E_NOTIMPL;
11217 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11218 MEMBERID memid, INVOKEKIND invKind)
11220 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11221 FIXME("%p %x %d - stub\n", This, memid, invKind);
11222 return E_NOTIMPL;
11225 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11226 UINT index)
11228 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11229 FIXME("%p %u - stub\n", This, index);
11230 return E_NOTIMPL;
11233 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11234 MEMBERID memid)
11236 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11237 FIXME("%p %x - stub\n", This, memid);
11238 return E_NOTIMPL;
11241 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11242 UINT index)
11244 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11245 FIXME("%p %u - stub\n", This, index);
11246 return E_NOTIMPL;
11249 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11250 REFGUID guid, VARIANT *varVal)
11252 TLBGuid *tlbguid;
11254 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11256 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11258 if (!guid || !varVal)
11259 return E_INVALIDARG;
11261 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11263 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11266 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11267 UINT index, REFGUID guid, VARIANT *varVal)
11269 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11270 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11271 return E_NOTIMPL;
11274 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11275 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11277 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11278 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11279 return E_NOTIMPL;
11282 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11283 UINT index, REFGUID guid, VARIANT *varVal)
11285 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11286 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11287 return E_NOTIMPL;
11290 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11291 UINT index, REFGUID guid, VARIANT *varVal)
11293 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11294 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11295 return E_NOTIMPL;
11298 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11299 ULONG helpStringContext)
11301 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11303 TRACE("%p %u\n", This, helpStringContext);
11305 This->dwHelpStringContext = helpStringContext;
11307 return S_OK;
11310 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11311 UINT index, ULONG helpStringContext)
11313 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11314 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11315 return E_NOTIMPL;
11318 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11319 UINT index, ULONG helpStringContext)
11321 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11322 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11323 return E_NOTIMPL;
11326 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11328 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11329 FIXME("%p - stub\n", This);
11330 return E_NOTIMPL;
11333 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11334 LPOLESTR name)
11336 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11338 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11340 if (!name)
11341 return E_INVALIDARG;
11343 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11345 return S_OK;
11348 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11349 ICreateTypeInfo2_fnQueryInterface,
11350 ICreateTypeInfo2_fnAddRef,
11351 ICreateTypeInfo2_fnRelease,
11352 ICreateTypeInfo2_fnSetGuid,
11353 ICreateTypeInfo2_fnSetTypeFlags,
11354 ICreateTypeInfo2_fnSetDocString,
11355 ICreateTypeInfo2_fnSetHelpContext,
11356 ICreateTypeInfo2_fnSetVersion,
11357 ICreateTypeInfo2_fnAddRefTypeInfo,
11358 ICreateTypeInfo2_fnAddFuncDesc,
11359 ICreateTypeInfo2_fnAddImplType,
11360 ICreateTypeInfo2_fnSetImplTypeFlags,
11361 ICreateTypeInfo2_fnSetAlignment,
11362 ICreateTypeInfo2_fnSetSchema,
11363 ICreateTypeInfo2_fnAddVarDesc,
11364 ICreateTypeInfo2_fnSetFuncAndParamNames,
11365 ICreateTypeInfo2_fnSetVarName,
11366 ICreateTypeInfo2_fnSetTypeDescAlias,
11367 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11368 ICreateTypeInfo2_fnSetFuncDocString,
11369 ICreateTypeInfo2_fnSetVarDocString,
11370 ICreateTypeInfo2_fnSetFuncHelpContext,
11371 ICreateTypeInfo2_fnSetVarHelpContext,
11372 ICreateTypeInfo2_fnSetMops,
11373 ICreateTypeInfo2_fnSetTypeIdldesc,
11374 ICreateTypeInfo2_fnLayOut,
11375 ICreateTypeInfo2_fnDeleteFuncDesc,
11376 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11377 ICreateTypeInfo2_fnDeleteVarDesc,
11378 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11379 ICreateTypeInfo2_fnDeleteImplType,
11380 ICreateTypeInfo2_fnSetCustData,
11381 ICreateTypeInfo2_fnSetFuncCustData,
11382 ICreateTypeInfo2_fnSetParamCustData,
11383 ICreateTypeInfo2_fnSetVarCustData,
11384 ICreateTypeInfo2_fnSetImplTypeCustData,
11385 ICreateTypeInfo2_fnSetHelpStringContext,
11386 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11387 ICreateTypeInfo2_fnSetVarHelpStringContext,
11388 ICreateTypeInfo2_fnInvalidate,
11389 ICreateTypeInfo2_fnSetName
11392 /******************************************************************************
11393 * ClearCustData (OLEAUT32.171)
11395 * Clear a custom data type's data.
11397 * PARAMS
11398 * lpCust [I] The custom data type instance
11400 * RETURNS
11401 * Nothing.
11403 void WINAPI ClearCustData(CUSTDATA *lpCust)
11405 if (lpCust && lpCust->cCustData)
11407 if (lpCust->prgCustData)
11409 DWORD i;
11411 for (i = 0; i < lpCust->cCustData; i++)
11412 VariantClear(&lpCust->prgCustData[i].varValue);
11414 CoTaskMemFree(lpCust->prgCustData);
11415 lpCust->prgCustData = NULL;
11417 lpCust->cCustData = 0;