regedit: Allow importing strings with escaped NULL.
[wine.git] / dlls / oleaut32 / typelib.c
blob00f504347deb9d1f395c7ded30276dd03948dae4
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
45 * behaviour.
46 * -. lousy fatal error handling
50 #include "config.h"
51 #include "wine/port.h"
53 #include <stdlib.h>
54 #include <string.h>
55 #include <stdarg.h>
56 #include <stdio.h>
57 #include <ctype.h>
59 #define COBJMACROS
60 #define NONAMELESSUNION
61 #define NONAMELESSSTRUCT
63 #include "winerror.h"
64 #include "windef.h"
65 #include "winbase.h"
66 #include "winnls.h"
67 #include "winreg.h"
68 #include "winuser.h"
69 #include "winternl.h"
70 #include "lzexpand.h"
72 #include "wine/unicode.h"
73 #include "objbase.h"
74 #include "typelib.h"
75 #include "wine/debug.h"
76 #include "variant.h"
77 #include "wine/list.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(ole);
80 WINE_DECLARE_DEBUG_CHANNEL(typelib);
82 typedef struct
84 WORD offset;
85 WORD length;
86 WORD flags;
87 WORD id;
88 WORD handle;
89 WORD usage;
90 } NE_NAMEINFO;
92 typedef struct
94 WORD type_id; /* Type identifier */
95 WORD count; /* Number of resources of this type */
96 DWORD resloader; /* SetResourceHandler() */
98 * Name info array.
100 } NE_TYPEINFO;
102 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
103 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
104 static void TLB_FreeVarDesc(VARDESC*);
106 /****************************************************************************
107 * FromLExxx
109 * Takes p_iVal (which is in little endian) and returns it
110 * in the host machine's byte order.
112 #ifdef WORDS_BIGENDIAN
113 static WORD FromLEWord(WORD p_iVal)
115 return (((p_iVal & 0x00FF) << 8) |
116 ((p_iVal & 0xFF00) >> 8));
120 static DWORD FromLEDWord(DWORD p_iVal)
122 return (((p_iVal & 0x000000FF) << 24) |
123 ((p_iVal & 0x0000FF00) << 8) |
124 ((p_iVal & 0x00FF0000) >> 8) |
125 ((p_iVal & 0xFF000000) >> 24));
127 #else
128 #define FromLEWord(X) (X)
129 #define FromLEDWord(X) (X)
130 #endif
132 #define DISPATCH_HREF_OFFSET 0x01000000
133 #define DISPATCH_HREF_MASK 0xff000000
135 /****************************************************************************
136 * FromLExxx
138 * Fix byte order in any structure if necessary
140 #ifdef WORDS_BIGENDIAN
141 static void FromLEWords(void *p_Val, int p_iSize)
143 WORD *Val = p_Val;
145 p_iSize /= sizeof(WORD);
147 while (p_iSize) {
148 *Val = FromLEWord(*Val);
149 Val++;
150 p_iSize--;
155 static void FromLEDWords(void *p_Val, int p_iSize)
157 DWORD *Val = p_Val;
159 p_iSize /= sizeof(DWORD);
161 while (p_iSize) {
162 *Val = FromLEDWord(*Val);
163 Val++;
164 p_iSize--;
167 #else
168 #define FromLEWords(X,Y) /*nothing*/
169 #define FromLEDWords(X,Y) /*nothing*/
170 #endif
173 * Find a typelib key which matches a requested maj.min version.
175 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
177 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
178 WCHAR buffer[60];
179 char key_name[16];
180 DWORD len, i;
181 INT best_maj = -1, best_min = -1;
182 HKEY hkey;
184 memcpy( buffer, typelibW, sizeof(typelibW) );
185 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
187 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
188 return FALSE;
190 len = sizeof(key_name);
191 i = 0;
192 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
194 INT v_maj, v_min;
196 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
198 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
200 if (*wMaj == 0xffff && *wMin == 0xffff)
202 if (v_maj > best_maj) best_maj = v_maj;
203 if (v_min > best_min) best_min = v_min;
205 else if (*wMaj == v_maj)
207 best_maj = v_maj;
209 if (*wMin == v_min)
211 best_min = v_min;
212 break; /* exact match */
214 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
217 len = sizeof(key_name);
219 RegCloseKey( hkey );
221 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
223 if (*wMaj == 0xffff && *wMin == 0xffff)
225 if (best_maj >= 0 && best_min >= 0)
227 *wMaj = best_maj;
228 *wMin = best_min;
229 return TRUE;
233 if (*wMaj == best_maj && best_min >= 0)
235 *wMin = best_min;
236 return TRUE;
238 return FALSE;
241 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
242 /* buffer must be at least 60 characters long */
243 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
245 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
246 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
248 memcpy( buffer, TypelibW, sizeof(TypelibW) );
249 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
250 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
251 return buffer;
254 /* get the path of an interface key, in the form "Interface\\<guid>" */
255 /* buffer must be at least 50 characters long */
256 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
258 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
260 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
261 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
262 return buffer;
265 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
266 /* buffer must be at least 16 characters long */
267 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
269 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
270 static const WCHAR win16W[] = {'w','i','n','1','6',0};
271 static const WCHAR win32W[] = {'w','i','n','3','2',0};
272 static const WCHAR win64W[] = {'w','i','n','6','4',0};
274 sprintfW( buffer, LcidFormatW, lcid );
275 switch(syskind)
277 case SYS_WIN16: strcatW( buffer, win16W ); break;
278 case SYS_WIN32: strcatW( buffer, win32W ); break;
279 case SYS_WIN64: strcatW( buffer, win64W ); break;
280 default:
281 TRACE("Typelib is for unsupported syskind %i\n", syskind);
282 return NULL;
284 return buffer;
287 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
289 struct tlibredirect_data
291 ULONG size;
292 DWORD res;
293 ULONG name_len;
294 ULONG name_offset;
295 LANGID langid;
296 WORD flags;
297 ULONG help_len;
298 ULONG help_offset;
299 WORD major_version;
300 WORD minor_version;
303 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
304 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
305 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
307 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
308 LCID myLCID = lcid;
309 HKEY hkey;
310 WCHAR buffer[60];
311 WCHAR Path[MAX_PATH];
312 LONG res;
314 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
316 if (redir)
318 ACTCTX_SECTION_KEYED_DATA data;
320 data.cbSize = sizeof(data);
321 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
323 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
324 WCHAR *nameW;
325 DWORD len;
327 if (tlib->major_version != wMaj || tlib->minor_version < wMin)
328 return TYPE_E_LIBNOTREGISTERED;
330 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
331 len = SearchPathW( NULL, nameW, NULL, sizeof(Path)/sizeof(WCHAR), Path, NULL );
332 if (!len) return TYPE_E_LIBNOTREGISTERED;
334 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
335 *path = SysAllocString( Path );
336 return S_OK;
340 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
341 get_typelib_key( guid, wMaj, wMin, buffer );
343 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
344 if (res == ERROR_FILE_NOT_FOUND)
346 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
347 return TYPE_E_LIBNOTREGISTERED;
349 else if (res != ERROR_SUCCESS)
351 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
352 return TYPE_E_REGISTRYACCESS;
355 while (hr != S_OK)
357 LONG dwPathLen = sizeof(Path);
359 get_lcid_subkey( myLCID, syskind, buffer );
361 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
363 if (!lcid)
364 break;
365 else if (myLCID == lcid)
367 /* try with sub-langid */
368 myLCID = SUBLANGID(lcid);
370 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
372 /* try with system langid */
373 myLCID = 0;
375 else
377 break;
380 else
382 *path = SysAllocString( Path );
383 hr = S_OK;
386 RegCloseKey( hkey );
387 TRACE_(typelib)("-- 0x%08x\n", hr);
388 return hr;
391 /****************************************************************************
392 * QueryPathOfRegTypeLib [OLEAUT32.164]
394 * Gets the path to a registered type library.
396 * PARAMS
397 * guid [I] referenced guid
398 * wMaj [I] major version
399 * wMin [I] minor version
400 * lcid [I] locale id
401 * path [O] path of typelib
403 * RETURNS
404 * Success: S_OK.
405 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
406 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
407 * opened.
409 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
411 BOOL redir = TRUE;
412 #ifdef _WIN64
413 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
414 if(SUCCEEDED(hres))
415 return hres;
416 redir = FALSE;
417 #endif
418 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
421 /******************************************************************************
422 * CreateTypeLib [OLEAUT32.160] creates a typelib
424 * RETURNS
425 * Success: S_OK
426 * Failure: Status
428 HRESULT WINAPI CreateTypeLib(
429 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
431 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
432 return E_FAIL;
435 /******************************************************************************
436 * LoadTypeLib [OLEAUT32.161]
438 * Loads a type library
440 * PARAMS
441 * szFile [I] Name of file to load from.
442 * pptLib [O] Pointer that receives ITypeLib object on success.
444 * RETURNS
445 * Success: S_OK
446 * Failure: Status
448 * SEE
449 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
451 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
453 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
454 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
457 /******************************************************************************
458 * LoadTypeLibEx [OLEAUT32.183]
460 * Loads and optionally registers a type library
462 * RETURNS
463 * Success: S_OK
464 * Failure: Status
466 HRESULT WINAPI LoadTypeLibEx(
467 LPCOLESTR szFile, /* [in] Name of file to load from */
468 REGKIND regkind, /* [in] Specify kind of registration */
469 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
471 WCHAR szPath[MAX_PATH+1];
472 HRESULT res;
474 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
476 *pptLib = NULL;
478 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
480 if (SUCCEEDED(res))
481 switch(regkind)
483 case REGKIND_DEFAULT:
484 /* don't register typelibs supplied with full path. Experimentation confirms the following */
485 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
486 (szFile[0] && (szFile[1] == ':'))) break;
487 /* else fall-through */
489 case REGKIND_REGISTER:
490 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
492 ITypeLib_Release(*pptLib);
493 *pptLib = 0;
495 break;
496 case REGKIND_NONE:
497 break;
500 TRACE(" returns %08x\n",res);
501 return res;
504 /******************************************************************************
505 * LoadRegTypeLib [OLEAUT32.162]
507 * Loads a registered type library.
509 * PARAMS
510 * rguid [I] GUID of the registered type library.
511 * wVerMajor [I] major version.
512 * wVerMinor [I] minor version.
513 * lcid [I] locale ID.
514 * ppTLib [O] pointer that receives an ITypeLib object on success.
516 * RETURNS
517 * Success: S_OK.
518 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
519 * LoadTypeLib.
521 HRESULT WINAPI LoadRegTypeLib(
522 REFGUID rguid,
523 WORD wVerMajor,
524 WORD wVerMinor,
525 LCID lcid,
526 ITypeLib **ppTLib)
528 BSTR bstr=NULL;
529 HRESULT res;
531 *ppTLib = NULL;
533 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
535 if(SUCCEEDED(res))
537 res= LoadTypeLib(bstr, ppTLib);
538 SysFreeString(bstr);
540 if (*ppTLib)
542 TLIBATTR *attr;
544 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
545 if (res == S_OK)
547 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
548 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
550 if (mismatch)
552 ITypeLib_Release(*ppTLib);
553 *ppTLib = NULL;
554 res = TYPE_E_LIBNOTREGISTERED;
560 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
562 return res;
566 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
567 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
568 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
569 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
570 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
571 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
573 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
575 WCHAR keyName[60];
576 HKEY key, subKey;
578 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
579 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
580 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
582 get_interface_key( &tattr->guid, keyName );
583 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
584 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
586 if (name)
587 RegSetValueExW(key, NULL, 0, REG_SZ,
588 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
590 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
591 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
592 RegSetValueExW(subKey, NULL, 0, REG_SZ,
593 (const BYTE *)PSOA, sizeof PSOA);
594 RegCloseKey(subKey);
597 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
598 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
599 RegSetValueExW(subKey, NULL, 0, REG_SZ,
600 (const BYTE *)PSOA, sizeof PSOA);
601 RegCloseKey(subKey);
604 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
605 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
607 WCHAR buffer[40];
608 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
609 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
611 StringFromGUID2(&libattr->guid, buffer, 40);
612 RegSetValueExW(subKey, NULL, 0, REG_SZ,
613 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
614 sprintfW(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
615 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
616 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
617 RegCloseKey(subKey);
620 RegCloseKey(key);
624 /******************************************************************************
625 * RegisterTypeLib [OLEAUT32.163]
626 * Adds information about a type library to the System Registry
627 * NOTES
628 * Docs: ITypeLib FAR * ptlib
629 * Docs: OLECHAR FAR* szFullPath
630 * Docs: OLECHAR FAR* szHelpDir
632 * RETURNS
633 * Success: S_OK
634 * Failure: Status
636 HRESULT WINAPI RegisterTypeLib(
637 ITypeLib * ptlib, /* [in] Pointer to the library*/
638 OLECHAR * szFullPath, /* [in] full Path of the library*/
639 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
640 may be NULL*/
642 HRESULT res;
643 TLIBATTR *attr;
644 WCHAR keyName[60];
645 WCHAR tmp[16];
646 HKEY key, subKey;
647 UINT types, tidx;
648 TYPEKIND kind;
649 DWORD disposition;
651 if (ptlib == NULL || szFullPath == NULL)
652 return E_INVALIDARG;
654 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
655 return E_FAIL;
657 #ifndef _WIN64
658 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
659 #endif
661 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
663 res = S_OK;
664 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
665 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
667 LPOLESTR doc;
669 /* Set the human-readable name of the typelib */
670 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
671 res = E_FAIL;
672 else if (doc)
674 if (RegSetValueExW(key, NULL, 0, REG_SZ,
675 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
676 res = E_FAIL;
678 SysFreeString(doc);
681 /* Make up the name of the typelib path subkey */
682 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
684 /* Create the typelib path subkey */
685 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
686 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
688 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
689 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
690 res = E_FAIL;
692 RegCloseKey(subKey);
694 else
695 res = E_FAIL;
697 /* Create the flags subkey */
698 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
699 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
701 /* FIXME: is %u correct? */
702 static const WCHAR formatW[] = {'%','u',0};
703 WCHAR buf[20];
704 sprintfW(buf, formatW, attr->wLibFlags);
705 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
706 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
707 res = E_FAIL;
709 RegCloseKey(subKey);
711 else
712 res = E_FAIL;
714 /* create the helpdir subkey */
715 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
716 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
718 BOOL freeHelpDir = FALSE;
719 OLECHAR* pIndexStr;
721 /* if we created a new key, and helpDir was null, set the helpdir
722 to the directory which contains the typelib. However,
723 if we just opened an existing key, we leave the helpdir alone */
724 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
725 szHelpDir = SysAllocString(szFullPath);
726 pIndexStr = strrchrW(szHelpDir, '\\');
727 if (pIndexStr) {
728 *pIndexStr = 0;
730 freeHelpDir = TRUE;
733 /* if we have an szHelpDir, set it! */
734 if (szHelpDir != NULL) {
735 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
736 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
737 res = E_FAIL;
741 /* tidy up */
742 if (freeHelpDir) SysFreeString(szHelpDir);
743 RegCloseKey(subKey);
745 } else {
746 res = E_FAIL;
749 RegCloseKey(key);
751 else
752 res = E_FAIL;
754 /* register OLE Automation-compatible interfaces for this typelib */
755 types = ITypeLib_GetTypeInfoCount(ptlib);
756 for (tidx=0; tidx<types; tidx++) {
757 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
758 LPOLESTR name = NULL;
759 ITypeInfo *tinfo = NULL;
761 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
763 switch (kind) {
764 case TKIND_INTERFACE:
765 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
766 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
767 break;
769 case TKIND_DISPATCH:
770 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
771 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
772 break;
774 default:
775 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
776 break;
779 if (tinfo) {
780 TYPEATTR *tattr = NULL;
781 ITypeInfo_GetTypeAttr(tinfo, &tattr);
783 if (tattr) {
784 TRACE_(typelib)("guid=%s, flags=%04x (",
785 debugstr_guid(&tattr->guid),
786 tattr->wTypeFlags);
788 if (TRACE_ON(typelib)) {
789 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
790 XX(FAPPOBJECT);
791 XX(FCANCREATE);
792 XX(FLICENSED);
793 XX(FPREDECLID);
794 XX(FHIDDEN);
795 XX(FCONTROL);
796 XX(FDUAL);
797 XX(FNONEXTENSIBLE);
798 XX(FOLEAUTOMATION);
799 XX(FRESTRICTED);
800 XX(FAGGREGATABLE);
801 XX(FREPLACEABLE);
802 XX(FDISPATCHABLE);
803 XX(FREVERSEBIND);
804 XX(FPROXY);
805 #undef XX
806 MESSAGE("\n");
809 /* Register all dispinterfaces (which includes dual interfaces) and
810 oleautomation interfaces */
811 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
812 kind == TKIND_DISPATCH)
814 BOOL is_wow64;
815 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
817 /* register interface<->typelib coupling */
818 TLB_register_interface(attr, name, tattr, 0);
820 /* register TLBs into the opposite registry view, too */
821 if(opposite == KEY_WOW64_32KEY ||
822 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
823 TLB_register_interface(attr, name, tattr, opposite);
826 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
829 ITypeInfo_Release(tinfo);
832 SysFreeString(name);
836 ITypeLib_ReleaseTLibAttr(ptlib, attr);
838 return res;
841 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
843 WCHAR subKeyName[50];
844 HKEY subKey;
846 /* the path to the type */
847 get_interface_key( guid, subKeyName );
849 /* Delete its bits */
850 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
851 return;
853 RegDeleteKeyW(subKey, ProxyStubClsidW);
854 RegDeleteKeyW(subKey, ProxyStubClsid32W);
855 RegDeleteKeyW(subKey, TypeLibW);
856 RegCloseKey(subKey);
857 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
860 /******************************************************************************
861 * UnRegisterTypeLib [OLEAUT32.186]
862 * Removes information about a type library from the System Registry
863 * NOTES
865 * RETURNS
866 * Success: S_OK
867 * Failure: Status
869 HRESULT WINAPI UnRegisterTypeLib(
870 REFGUID libid, /* [in] Guid of the library */
871 WORD wVerMajor, /* [in] major version */
872 WORD wVerMinor, /* [in] minor version */
873 LCID lcid, /* [in] locale id */
874 SYSKIND syskind)
876 BSTR tlibPath = NULL;
877 DWORD tmpLength;
878 WCHAR keyName[60];
879 WCHAR subKeyName[50];
880 int result = S_OK;
881 DWORD i = 0;
882 BOOL deleteOtherStuff;
883 HKEY key = NULL;
884 TYPEATTR* typeAttr = NULL;
885 TYPEKIND kind;
886 ITypeInfo* typeInfo = NULL;
887 ITypeLib* typeLib = NULL;
888 int numTypes;
890 TRACE("(IID: %s)\n",debugstr_guid(libid));
892 /* Create the path to the key */
893 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
895 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
897 TRACE("Unsupported syskind %i\n", syskind);
898 result = E_INVALIDARG;
899 goto end;
902 /* get the path to the typelib on disk */
903 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
904 result = E_INVALIDARG;
905 goto end;
908 /* Try and open the key to the type library. */
909 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
910 result = E_INVALIDARG;
911 goto end;
914 /* Try and load the type library */
915 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
916 result = TYPE_E_INVALIDSTATE;
917 goto end;
920 /* remove any types registered with this typelib */
921 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
922 for (i=0; i<numTypes; i++) {
923 /* get the kind of type */
924 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
925 goto enddeleteloop;
928 /* skip non-interfaces, and get type info for the type */
929 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
930 goto enddeleteloop;
932 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
933 goto enddeleteloop;
935 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
936 goto enddeleteloop;
939 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
940 kind == TKIND_DISPATCH)
942 BOOL is_wow64;
943 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
945 TLB_unregister_interface(&typeAttr->guid, 0);
947 /* unregister TLBs into the opposite registry view, too */
948 if(opposite == KEY_WOW64_32KEY ||
949 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
950 TLB_unregister_interface(&typeAttr->guid, opposite);
954 enddeleteloop:
955 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
956 typeAttr = NULL;
957 if (typeInfo) ITypeInfo_Release(typeInfo);
958 typeInfo = NULL;
961 /* Now, delete the type library path subkey */
962 get_lcid_subkey( lcid, syskind, subKeyName );
963 RegDeleteKeyW(key, subKeyName);
964 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
965 RegDeleteKeyW(key, subKeyName);
967 /* check if there is anything besides the FLAGS/HELPDIR keys.
968 If there is, we don't delete them */
969 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
970 deleteOtherStuff = TRUE;
971 i = 0;
972 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
973 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
975 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
976 if (!strcmpW(subKeyName, FLAGSW)) continue;
977 if (!strcmpW(subKeyName, HELPDIRW)) continue;
978 deleteOtherStuff = FALSE;
979 break;
982 /* only delete the other parts of the key if we're absolutely sure */
983 if (deleteOtherStuff) {
984 RegDeleteKeyW(key, FLAGSW);
985 RegDeleteKeyW(key, HELPDIRW);
986 RegCloseKey(key);
987 key = NULL;
989 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
990 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
991 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
994 end:
995 SysFreeString(tlibPath);
996 if (typeLib) ITypeLib_Release(typeLib);
997 if (key) RegCloseKey(key);
998 return result;
1001 /******************************************************************************
1002 * RegisterTypeLibForUser [OLEAUT32.442]
1003 * Adds information about a type library to the user registry
1004 * NOTES
1005 * Docs: ITypeLib FAR * ptlib
1006 * Docs: OLECHAR FAR* szFullPath
1007 * Docs: OLECHAR FAR* szHelpDir
1009 * RETURNS
1010 * Success: S_OK
1011 * Failure: Status
1013 HRESULT WINAPI RegisterTypeLibForUser(
1014 ITypeLib * ptlib, /* [in] Pointer to the library*/
1015 OLECHAR * szFullPath, /* [in] full Path of the library*/
1016 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1017 may be NULL*/
1019 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1020 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1021 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1024 /******************************************************************************
1025 * UnRegisterTypeLibForUser [OLEAUT32.443]
1026 * Removes information about a type library from the user registry
1028 * RETURNS
1029 * Success: S_OK
1030 * Failure: Status
1032 HRESULT WINAPI UnRegisterTypeLibForUser(
1033 REFGUID libid, /* [in] GUID of the library */
1034 WORD wVerMajor, /* [in] major version */
1035 WORD wVerMinor, /* [in] minor version */
1036 LCID lcid, /* [in] locale id */
1037 SYSKIND syskind)
1039 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1040 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1041 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1044 /*======================= ITypeLib implementation =======================*/
1046 typedef struct tagTLBGuid {
1047 GUID guid;
1048 INT hreftype;
1049 UINT offset;
1050 struct list entry;
1051 } TLBGuid;
1053 typedef struct tagTLBCustData
1055 TLBGuid *guid;
1056 VARIANT data;
1057 struct list entry;
1058 } TLBCustData;
1060 /* data structure for import typelibs */
1061 typedef struct tagTLBImpLib
1063 int offset; /* offset in the file (MSFT)
1064 offset in nametable (SLTG)
1065 just used to identify library while reading
1066 data from file */
1067 TLBGuid *guid; /* libid */
1068 BSTR name; /* name */
1070 LCID lcid; /* lcid of imported typelib */
1072 WORD wVersionMajor; /* major version number */
1073 WORD wVersionMinor; /* minor version number */
1075 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1076 NULL if not yet loaded */
1077 struct list entry;
1078 } TLBImpLib;
1080 typedef struct tagTLBString {
1081 BSTR str;
1082 UINT offset;
1083 struct list entry;
1084 } TLBString;
1086 /* internal ITypeLib data */
1087 typedef struct tagITypeLibImpl
1089 ITypeLib2 ITypeLib2_iface;
1090 ITypeComp ITypeComp_iface;
1091 ICreateTypeLib2 ICreateTypeLib2_iface;
1092 LONG ref;
1093 TLBGuid *guid;
1094 LCID lcid;
1095 SYSKIND syskind;
1096 int ptr_size;
1097 WORD ver_major;
1098 WORD ver_minor;
1099 WORD libflags;
1100 LCID set_lcid;
1102 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1103 * exported to the application as a UNICODE string.
1105 struct list string_list;
1106 struct list name_list;
1107 struct list guid_list;
1109 const TLBString *Name;
1110 const TLBString *DocString;
1111 const TLBString *HelpFile;
1112 const TLBString *HelpStringDll;
1113 DWORD dwHelpContext;
1114 int TypeInfoCount; /* nr of typeinfo's in librarry */
1115 struct tagITypeInfoImpl **typeinfos;
1116 struct list custdata_list;
1117 struct list implib_list;
1118 int ctTypeDesc; /* number of items in type desc array */
1119 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1120 library. Only used while reading MSFT
1121 typelibs */
1122 struct list ref_list; /* list of ref types in this typelib */
1123 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1126 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1127 struct list entry;
1128 WCHAR *path;
1129 INT index;
1130 } ITypeLibImpl;
1132 static const ITypeLib2Vtbl tlbvt;
1133 static const ITypeCompVtbl tlbtcvt;
1134 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1136 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1138 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1141 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1143 return impl_from_ITypeLib2((ITypeLib2*)iface);
1146 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1148 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1151 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1153 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1156 /* ITypeLib methods */
1157 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1158 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1160 /*======================= ITypeInfo implementation =======================*/
1162 /* data for referenced types */
1163 typedef struct tagTLBRefType
1165 INT index; /* Type index for internal ref or for external ref
1166 it the format is SLTG. -2 indicates to
1167 use guid */
1169 TYPEKIND tkind;
1170 TLBGuid *guid; /* guid of the referenced type */
1171 /* if index == TLB_REF_USE_GUID */
1173 HREFTYPE reference; /* The href of this ref */
1174 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1175 TLB_REF_INTERNAL for internal refs
1176 TLB_REF_NOT_FOUND for broken refs */
1178 struct list entry;
1179 } TLBRefType;
1181 #define TLB_REF_USE_GUID -2
1183 #define TLB_REF_INTERNAL (void*)-2
1184 #define TLB_REF_NOT_FOUND (void*)-1
1186 /* internal Parameter data */
1187 typedef struct tagTLBParDesc
1189 const TLBString *Name;
1190 struct list custdata_list;
1191 } TLBParDesc;
1193 /* internal Function data */
1194 typedef struct tagTLBFuncDesc
1196 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1197 const TLBString *Name; /* the name of this function */
1198 TLBParDesc *pParamDesc; /* array with param names and custom data */
1199 int helpcontext;
1200 int HelpStringContext;
1201 const TLBString *HelpString;
1202 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1203 struct list custdata_list;
1204 } TLBFuncDesc;
1206 /* internal Variable data */
1207 typedef struct tagTLBVarDesc
1209 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1210 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1211 const TLBString *Name; /* the name of this variable */
1212 int HelpContext;
1213 int HelpStringContext;
1214 const TLBString *HelpString;
1215 struct list custdata_list;
1216 } TLBVarDesc;
1218 /* internal implemented interface data */
1219 typedef struct tagTLBImplType
1221 HREFTYPE hRef; /* hRef of interface */
1222 int implflags; /* IMPLFLAG_*s */
1223 struct list custdata_list;
1224 } TLBImplType;
1226 /* internal TypeInfo data */
1227 typedef struct tagITypeInfoImpl
1229 ITypeInfo2 ITypeInfo2_iface;
1230 ITypeComp ITypeComp_iface;
1231 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1232 LONG ref;
1233 BOOL not_attached_to_typelib;
1234 BOOL needs_layout;
1236 TLBGuid *guid;
1237 LCID lcid;
1238 MEMBERID memidConstructor;
1239 MEMBERID memidDestructor;
1240 LPOLESTR lpstrSchema;
1241 ULONG cbSizeInstance;
1242 TYPEKIND typekind;
1243 WORD cFuncs;
1244 WORD cVars;
1245 WORD cImplTypes;
1246 WORD cbSizeVft;
1247 WORD cbAlignment;
1248 WORD wTypeFlags;
1249 WORD wMajorVerNum;
1250 WORD wMinorVerNum;
1251 TYPEDESC *tdescAlias;
1252 IDLDESC idldescType;
1254 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1255 int index; /* index in this typelib; */
1256 HREFTYPE hreftype; /* hreftype for app object binding */
1257 /* type libs seem to store the doc strings in ascii
1258 * so why should we do it in unicode?
1260 const TLBString *Name;
1261 const TLBString *DocString;
1262 const TLBString *DllName;
1263 const TLBString *Schema;
1264 DWORD dwHelpContext;
1265 DWORD dwHelpStringContext;
1267 /* functions */
1268 TLBFuncDesc *funcdescs;
1270 /* variables */
1271 TLBVarDesc *vardescs;
1273 /* Implemented Interfaces */
1274 TLBImplType *impltypes;
1276 struct list *pcustdata_list;
1277 struct list custdata_list;
1278 } ITypeInfoImpl;
1280 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1282 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1285 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1287 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1290 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1292 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1295 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1297 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1300 static const ITypeInfo2Vtbl tinfvt;
1301 static const ITypeCompVtbl tcompvt;
1302 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1304 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1305 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1307 typedef struct tagTLBContext
1309 unsigned int oStart; /* start of TLB in file */
1310 unsigned int pos; /* current pos */
1311 unsigned int length; /* total length */
1312 void *mapping; /* memory mapping */
1313 MSFT_SegDir * pTblDir;
1314 ITypeLibImpl* pLibInfo;
1315 } TLBContext;
1318 static inline BSTR TLB_get_bstr(const TLBString *str)
1320 return str != NULL ? str->str : NULL;
1323 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1325 if(!str)
1326 return 1;
1327 return memcmp(left, str->str, len);
1330 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1332 return guid != NULL ? &guid->guid : NULL;
1335 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1337 return guid != NULL ? &guid->guid : &GUID_NULL;
1340 static int get_ptr_size(SYSKIND syskind)
1342 switch(syskind){
1343 case SYS_WIN64:
1344 return 8;
1345 case SYS_WIN32:
1346 case SYS_MAC:
1347 case SYS_WIN16:
1348 return 4;
1350 WARN("Unhandled syskind: 0x%x\n", syskind);
1351 return 4;
1355 debug
1357 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1358 if (pTD->vt & VT_RESERVED)
1359 szVarType += strlen(strcpy(szVarType, "reserved | "));
1360 if (pTD->vt & VT_BYREF)
1361 szVarType += strlen(strcpy(szVarType, "ref to "));
1362 if (pTD->vt & VT_ARRAY)
1363 szVarType += strlen(strcpy(szVarType, "array of "));
1364 if (pTD->vt & VT_VECTOR)
1365 szVarType += strlen(strcpy(szVarType, "vector of "));
1366 switch(pTD->vt & VT_TYPEMASK) {
1367 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1368 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1369 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1370 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1371 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1372 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1373 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1374 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1375 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1376 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1377 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1378 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1379 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1380 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1381 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1382 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1383 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1384 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1385 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1386 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1387 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1388 pTD->u.hreftype); break;
1389 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1390 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1391 case VT_PTR: sprintf(szVarType, "ptr to ");
1392 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1393 break;
1394 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1395 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1396 break;
1397 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1398 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1399 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1400 break;
1402 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1406 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1407 char buf[200];
1408 USHORT flags = edesc->u.paramdesc.wParamFlags;
1409 dump_TypeDesc(&edesc->tdesc,buf);
1410 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1411 MESSAGE("\t\tu.paramdesc.wParamFlags");
1412 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1413 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1414 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1415 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1416 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1417 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1418 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1419 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1420 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1422 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1423 int i;
1424 MESSAGE("memid is %08x\n",funcdesc->memid);
1425 for (i=0;i<funcdesc->cParams;i++) {
1426 MESSAGE("Param %d:\n",i);
1427 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1429 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1430 switch (funcdesc->funckind) {
1431 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1432 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1433 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1434 case FUNC_STATIC: MESSAGE("static");break;
1435 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1436 default: MESSAGE("unknown");break;
1438 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1439 switch (funcdesc->invkind) {
1440 case INVOKE_FUNC: MESSAGE("func");break;
1441 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1442 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1443 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1445 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1446 switch (funcdesc->callconv) {
1447 case CC_CDECL: MESSAGE("cdecl");break;
1448 case CC_PASCAL: MESSAGE("pascal");break;
1449 case CC_STDCALL: MESSAGE("stdcall");break;
1450 case CC_SYSCALL: MESSAGE("syscall");break;
1451 default:break;
1453 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1454 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1455 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1457 MESSAGE("\telemdescFunc (return value type):\n");
1458 dump_ELEMDESC(&funcdesc->elemdescFunc);
1461 static const char * const typekind_desc[] =
1463 "TKIND_ENUM",
1464 "TKIND_RECORD",
1465 "TKIND_MODULE",
1466 "TKIND_INTERFACE",
1467 "TKIND_DISPATCH",
1468 "TKIND_COCLASS",
1469 "TKIND_ALIAS",
1470 "TKIND_UNION",
1471 "TKIND_MAX"
1474 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1476 int i;
1477 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1478 for (i=0;i<pfd->funcdesc.cParams;i++)
1479 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1482 dump_FUNCDESC(&(pfd->funcdesc));
1484 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1485 if(pfd->Entry == NULL)
1486 MESSAGE("\tentry: (null)\n");
1487 else if(pfd->Entry == (void*)-1)
1488 MESSAGE("\tentry: invalid\n");
1489 else if(IS_INTRESOURCE(pfd->Entry))
1490 MESSAGE("\tentry: %p\n", pfd->Entry);
1491 else
1492 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1494 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1496 while (n)
1498 dump_TLBFuncDescOne(pfd);
1499 ++pfd;
1500 --n;
1503 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1505 while (n)
1507 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1508 ++pvd;
1509 --n;
1513 static void dump_TLBImpLib(const TLBImpLib *import)
1515 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1516 debugstr_w(import->name));
1517 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1518 import->wVersionMinor, import->lcid, import->offset);
1521 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1523 TLBRefType *ref;
1525 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1527 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1528 if(ref->index == -1)
1529 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1530 else
1531 TRACE_(typelib)("type no: %d\n", ref->index);
1533 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1535 TRACE_(typelib)("in lib\n");
1536 dump_TLBImpLib(ref->pImpTLInfo);
1541 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1543 if(!impl)
1544 return;
1545 while (n) {
1546 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1547 impl->hRef, impl->implflags);
1548 ++impl;
1549 --n;
1553 static void dump_DispParms(const DISPPARAMS * pdp)
1555 unsigned int index;
1557 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1559 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1561 TRACE("named args:\n");
1562 for (index = 0; index < pdp->cNamedArgs; index++)
1563 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1566 if (pdp->cArgs && pdp->rgvarg)
1568 TRACE("args:\n");
1569 for (index = 0; index < pdp->cArgs; index++)
1570 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1574 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1576 TRACE("%p ref=%u\n", pty, pty->ref);
1577 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1578 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1579 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1580 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1581 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1582 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1583 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1584 if (TRACE_ON(ole))
1585 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1586 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1587 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1590 static void dump_VARDESC(const VARDESC *v)
1592 MESSAGE("memid %d\n",v->memid);
1593 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1594 MESSAGE("oInst %d\n",v->u.oInst);
1595 dump_ELEMDESC(&(v->elemdescVar));
1596 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1597 MESSAGE("varkind %d\n",v->varkind);
1600 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1602 /* VT_LPWSTR is largest type that, may appear in type description */
1603 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1604 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1605 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1606 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1607 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1608 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1609 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1610 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1613 static void TLB_abort(void)
1615 DebugBreak();
1618 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1620 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1621 if (!ret) ERR("cannot allocate memory\n");
1622 return ret;
1625 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1627 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1628 if (!ret) ERR("cannot allocate memory\n");
1629 return ret;
1632 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1634 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1637 void heap_free(void *ptr)
1639 HeapFree(GetProcessHeap(), 0, ptr);
1642 /* returns the size required for a deep copy of a typedesc into a
1643 * flat buffer */
1644 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1646 SIZE_T size = 0;
1648 if (alloc_initial_space)
1649 size += sizeof(TYPEDESC);
1651 switch (tdesc->vt)
1653 case VT_PTR:
1654 case VT_SAFEARRAY:
1655 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1656 break;
1657 case VT_CARRAY:
1658 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1659 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1660 break;
1662 return size;
1665 /* deep copy a typedesc into a flat buffer */
1666 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1668 if (!dest)
1670 dest = buffer;
1671 buffer = (char *)buffer + sizeof(TYPEDESC);
1674 *dest = *src;
1676 switch (src->vt)
1678 case VT_PTR:
1679 case VT_SAFEARRAY:
1680 dest->u.lptdesc = buffer;
1681 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1682 break;
1683 case VT_CARRAY:
1684 dest->u.lpadesc = buffer;
1685 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1686 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1687 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1688 break;
1690 return buffer;
1693 /* free custom data allocated by MSFT_CustData */
1694 static inline void TLB_FreeCustData(struct list *custdata_list)
1696 TLBCustData *cd, *cdn;
1697 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1699 list_remove(&cd->entry);
1700 VariantClear(&cd->data);
1701 heap_free(cd);
1705 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1707 DWORD len;
1708 BSTR ret;
1710 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1711 ret = SysAllocStringLen(NULL, len - 1);
1712 if (!ret) return ret;
1713 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1714 return ret;
1717 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1718 UINT n, MEMBERID memid)
1720 while(n){
1721 if(funcdescs->funcdesc.memid == memid)
1722 return funcdescs;
1723 ++funcdescs;
1724 --n;
1726 return NULL;
1729 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1730 UINT n, const OLECHAR *name)
1732 while(n){
1733 if(!lstrcmpiW(TLB_get_bstr(funcdescs->Name), name))
1734 return funcdescs;
1735 ++funcdescs;
1736 --n;
1738 return NULL;
1741 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1742 UINT n, MEMBERID memid)
1744 while(n){
1745 if(vardescs->vardesc.memid == memid)
1746 return vardescs;
1747 ++vardescs;
1748 --n;
1750 return NULL;
1753 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1754 UINT n, const OLECHAR *name)
1756 while(n){
1757 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1758 return vardescs;
1759 ++vardescs;
1760 --n;
1762 return NULL;
1765 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1767 TLBCustData *cust_data;
1768 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1769 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1770 return cust_data;
1771 return NULL;
1774 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1775 UINT n, const OLECHAR *name)
1777 while(n){
1778 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1779 return *typeinfos;
1780 ++typeinfos;
1781 --n;
1783 return NULL;
1786 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1788 list_init(&var_desc->custdata_list);
1791 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1793 TLBVarDesc *ret;
1795 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1796 if(!ret)
1797 return NULL;
1799 while(n){
1800 TLBVarDesc_Constructor(&ret[n-1]);
1801 --n;
1804 return ret;
1807 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1809 TLBParDesc *ret;
1811 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1812 if(!ret)
1813 return NULL;
1815 while(n){
1816 list_init(&ret[n-1].custdata_list);
1817 --n;
1820 return ret;
1823 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1825 list_init(&func_desc->custdata_list);
1828 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1830 TLBFuncDesc *ret;
1832 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1833 if(!ret)
1834 return NULL;
1836 while(n){
1837 TLBFuncDesc_Constructor(&ret[n-1]);
1838 --n;
1841 return ret;
1844 static void TLBImplType_Constructor(TLBImplType *impl)
1846 list_init(&impl->custdata_list);
1849 static TLBImplType *TLBImplType_Alloc(UINT n)
1851 TLBImplType *ret;
1853 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1854 if(!ret)
1855 return NULL;
1857 while(n){
1858 TLBImplType_Constructor(&ret[n-1]);
1859 --n;
1862 return ret;
1865 static TLBGuid *TLB_append_guid(struct list *guid_list,
1866 const GUID *new_guid, HREFTYPE hreftype)
1868 TLBGuid *guid;
1870 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1871 if (IsEqualGUID(&guid->guid, new_guid))
1872 return guid;
1875 guid = heap_alloc(sizeof(TLBGuid));
1876 if (!guid)
1877 return NULL;
1879 memcpy(&guid->guid, new_guid, sizeof(GUID));
1880 guid->hreftype = hreftype;
1882 list_add_tail(guid_list, &guid->entry);
1884 return guid;
1887 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1889 TLBCustData *cust_data;
1891 switch(V_VT(var)){
1892 case VT_I4:
1893 case VT_R4:
1894 case VT_UI4:
1895 case VT_INT:
1896 case VT_UINT:
1897 case VT_HRESULT:
1898 case VT_BSTR:
1899 break;
1900 default:
1901 return DISP_E_BADVARTYPE;
1904 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1906 if (!cust_data) {
1907 cust_data = heap_alloc(sizeof(TLBCustData));
1908 if (!cust_data)
1909 return E_OUTOFMEMORY;
1911 cust_data->guid = tlbguid;
1912 VariantInit(&cust_data->data);
1914 list_add_tail(custdata_list, &cust_data->entry);
1915 }else
1916 VariantClear(&cust_data->data);
1918 return VariantCopy(&cust_data->data, var);
1921 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1923 TLBString *str;
1925 if(!new_str)
1926 return NULL;
1928 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1929 if (strcmpW(str->str, new_str) == 0)
1930 return str;
1933 str = heap_alloc(sizeof(TLBString));
1934 if (!str)
1935 return NULL;
1937 str->str = SysAllocString(new_str);
1938 if (!str->str) {
1939 heap_free(str);
1940 return NULL;
1943 list_add_tail(string_list, &str->entry);
1945 return str;
1948 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1949 ULONG *size, WORD *align)
1951 ITypeInfo *other;
1952 TYPEATTR *attr;
1953 HRESULT hr;
1955 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1956 if(FAILED(hr))
1957 return hr;
1959 hr = ITypeInfo_GetTypeAttr(other, &attr);
1960 if(FAILED(hr)){
1961 ITypeInfo_Release(other);
1962 return hr;
1965 if(size)
1966 *size = attr->cbSizeInstance;
1967 if(align)
1968 *align = attr->cbAlignment;
1970 ITypeInfo_ReleaseTypeAttr(other, attr);
1971 ITypeInfo_Release(other);
1973 return S_OK;
1976 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1977 TYPEDESC *tdesc, ULONG *size, WORD *align)
1979 ULONG i, sub, ptr_size;
1980 HRESULT hr;
1982 ptr_size = get_ptr_size(sys);
1984 switch(tdesc->vt){
1985 case VT_VOID:
1986 *size = 0;
1987 break;
1988 case VT_I1:
1989 case VT_UI1:
1990 *size = 1;
1991 break;
1992 case VT_I2:
1993 case VT_BOOL:
1994 case VT_UI2:
1995 *size = 2;
1996 break;
1997 case VT_I4:
1998 case VT_R4:
1999 case VT_ERROR:
2000 case VT_UI4:
2001 case VT_INT:
2002 case VT_UINT:
2003 case VT_HRESULT:
2004 *size = 4;
2005 break;
2006 case VT_R8:
2007 case VT_I8:
2008 case VT_UI8:
2009 *size = 8;
2010 break;
2011 case VT_BSTR:
2012 case VT_DISPATCH:
2013 case VT_UNKNOWN:
2014 case VT_PTR:
2015 case VT_SAFEARRAY:
2016 case VT_LPSTR:
2017 case VT_LPWSTR:
2018 *size = ptr_size;
2019 break;
2020 case VT_DATE:
2021 *size = sizeof(DATE);
2022 break;
2023 case VT_VARIANT:
2024 *size = sizeof(VARIANT);
2025 #ifdef _WIN64
2026 if(sys == SYS_WIN32)
2027 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2028 #endif
2029 break;
2030 case VT_DECIMAL:
2031 *size = sizeof(DECIMAL);
2032 break;
2033 case VT_CY:
2034 *size = sizeof(CY);
2035 break;
2036 case VT_CARRAY:
2037 *size = 0;
2038 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2039 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2040 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2041 if(FAILED(hr))
2042 return hr;
2043 *size *= sub;
2044 return S_OK;
2045 case VT_USERDEFINED:
2046 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2047 default:
2048 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2049 return E_FAIL;
2052 if(align){
2053 if(*size < 4)
2054 *align = *size;
2055 else
2056 *align = 4;
2059 return S_OK;
2062 /**********************************************************************
2064 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2066 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
2068 return pcx->pos;
2071 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2073 if (where != DO_NOT_SEEK)
2075 where += pcx->oStart;
2076 if (where > pcx->length)
2078 /* FIXME */
2079 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2080 TLB_abort();
2082 pcx->pos = where;
2086 /* read function */
2087 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2089 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2090 pcx->pos, count, pcx->oStart, pcx->length, where);
2092 MSFT_Seek(pcx, where);
2093 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2094 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2095 pcx->pos += count;
2096 return count;
2099 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2100 LONG where )
2102 DWORD ret;
2104 ret = MSFT_Read(buffer, count, pcx, where);
2105 FromLEDWords(buffer, ret);
2107 return ret;
2110 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2111 LONG where )
2113 DWORD ret;
2115 ret = MSFT_Read(buffer, count, pcx, where);
2116 FromLEWords(buffer, ret);
2118 return ret;
2121 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2123 TLBGuid *guid;
2124 MSFT_GuidEntry entry;
2125 int offs = 0;
2127 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2128 while (1) {
2129 if (offs >= pcx->pTblDir->pGuidTab.length)
2130 return S_OK;
2132 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2134 guid = heap_alloc(sizeof(TLBGuid));
2136 guid->offset = offs;
2137 guid->guid = entry.guid;
2138 guid->hreftype = entry.hreftype;
2140 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2142 offs += sizeof(MSFT_GuidEntry);
2146 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2148 TLBGuid *ret;
2150 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2151 if(ret->offset == offset){
2152 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2153 return ret;
2157 return NULL;
2160 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2162 MSFT_NameIntro niName;
2164 if (offset < 0)
2166 ERR_(typelib)("bad offset %d\n", offset);
2167 return -1;
2170 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2171 pcx->pTblDir->pNametab.offset+offset);
2173 return niName.hreftype;
2176 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2178 char *string;
2179 MSFT_NameIntro intro;
2180 INT16 len_piece;
2181 int offs = 0, lengthInChars;
2183 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2184 while (1) {
2185 TLBString *tlbstr;
2187 if (offs >= pcx->pTblDir->pNametab.length)
2188 return S_OK;
2190 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2191 intro.namelen &= 0xFF;
2192 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2193 if(len_piece % 4)
2194 len_piece = (len_piece + 4) & ~0x3;
2195 if(len_piece < 8)
2196 len_piece = 8;
2198 string = heap_alloc(len_piece + 1);
2199 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2200 string[intro.namelen] = '\0';
2202 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2203 string, -1, NULL, 0);
2204 if (!lengthInChars) {
2205 heap_free(string);
2206 return E_UNEXPECTED;
2209 tlbstr = heap_alloc(sizeof(TLBString));
2211 tlbstr->offset = offs;
2212 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2213 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2215 heap_free(string);
2217 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2219 offs += len_piece;
2223 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2225 TLBString *tlbstr;
2227 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2228 if (tlbstr->offset == offset) {
2229 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2230 return tlbstr;
2234 return NULL;
2237 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2239 TLBString *tlbstr;
2241 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2242 if (tlbstr->offset == offset) {
2243 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2244 return tlbstr;
2248 return NULL;
2252 * read a value and fill a VARIANT structure
2254 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2256 int size;
2258 TRACE_(typelib)("\n");
2260 if(offset <0) { /* data are packed in here */
2261 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2262 V_I4(pVar) = offset & 0x3ffffff;
2263 return;
2265 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2266 pcx->pTblDir->pCustData.offset + offset );
2267 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2268 switch (V_VT(pVar)){
2269 case VT_EMPTY: /* FIXME: is this right? */
2270 case VT_NULL: /* FIXME: is this right? */
2271 case VT_I2 : /* this should not happen */
2272 case VT_I4 :
2273 case VT_R4 :
2274 case VT_ERROR :
2275 case VT_BOOL :
2276 case VT_I1 :
2277 case VT_UI1 :
2278 case VT_UI2 :
2279 case VT_UI4 :
2280 case VT_INT :
2281 case VT_UINT :
2282 case VT_VOID : /* FIXME: is this right? */
2283 case VT_HRESULT :
2284 size=4; break;
2285 case VT_R8 :
2286 case VT_CY :
2287 case VT_DATE :
2288 case VT_I8 :
2289 case VT_UI8 :
2290 case VT_DECIMAL : /* FIXME: is this right? */
2291 case VT_FILETIME :
2292 size=8;break;
2293 /* pointer types with known behaviour */
2294 case VT_BSTR :{
2295 char * ptr;
2296 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2297 if(size == -1){
2298 V_BSTR(pVar) = NULL;
2299 }else{
2300 ptr = heap_alloc_zero(size);
2301 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2302 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2303 /* FIXME: do we need a AtoW conversion here? */
2304 V_UNION(pVar, bstrVal[size])='\0';
2305 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2306 heap_free(ptr);
2309 size=-4; break;
2310 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2311 case VT_DISPATCH :
2312 case VT_VARIANT :
2313 case VT_UNKNOWN :
2314 case VT_PTR :
2315 case VT_SAFEARRAY :
2316 case VT_CARRAY :
2317 case VT_USERDEFINED :
2318 case VT_LPSTR :
2319 case VT_LPWSTR :
2320 case VT_BLOB :
2321 case VT_STREAM :
2322 case VT_STORAGE :
2323 case VT_STREAMED_OBJECT :
2324 case VT_STORED_OBJECT :
2325 case VT_BLOB_OBJECT :
2326 case VT_CF :
2327 case VT_CLSID :
2328 default:
2329 size=0;
2330 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2331 V_VT(pVar));
2334 if(size>0) /* (big|small) endian correct? */
2335 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2336 return;
2339 * create a linked list with custom data
2341 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2343 MSFT_CDGuid entry;
2344 TLBCustData* pNew;
2345 int count=0;
2347 TRACE_(typelib)("\n");
2349 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2351 while(offset >=0){
2352 count++;
2353 pNew=heap_alloc_zero(sizeof(TLBCustData));
2354 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2355 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2356 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2357 list_add_head(custdata_list, &pNew->entry);
2358 offset = entry.next;
2360 return count;
2363 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2365 if(type <0)
2366 pTd->vt=type & VT_TYPEMASK;
2367 else
2368 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2370 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2373 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2375 return (invkind == INVOKE_PROPERTYGET ||
2376 invkind == INVOKE_PROPERTYPUT ||
2377 invkind == INVOKE_PROPERTYPUTREF);
2380 static void
2381 MSFT_DoFuncs(TLBContext* pcx,
2382 ITypeInfoImpl* pTI,
2383 int cFuncs,
2384 int cVars,
2385 int offset,
2386 TLBFuncDesc** pptfd)
2389 * member information is stored in a data structure at offset
2390 * indicated by the memoffset field of the typeinfo structure
2391 * There are several distinctive parts.
2392 * The first part starts with a field that holds the total length
2393 * of this (first) part excluding this field. Then follow the records,
2394 * for each member there is one record.
2396 * The first entry is always the length of the record (including this
2397 * length word).
2398 * The rest of the record depends on the type of the member. If there is
2399 * a field indicating the member type (function, variable, interface, etc)
2400 * I have not found it yet. At this time we depend on the information
2401 * in the type info and the usual order how things are stored.
2403 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2404 * for each member;
2406 * Third is an equal sized array with file offsets to the name entry
2407 * of each member.
2409 * The fourth and last (?) part is an array with offsets to the records
2410 * in the first part of this file segment.
2413 int infolen, nameoffset, reclength, i;
2414 int recoffset = offset + sizeof(INT);
2416 char *recbuf = heap_alloc(0xffff);
2417 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2418 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2420 TRACE_(typelib)("\n");
2422 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2424 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2425 ptfd = *pptfd;
2426 for ( i = 0; i < cFuncs ; i++ )
2428 int optional;
2430 /* name, eventually add to a hash table */
2431 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2432 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2434 /* read the function information record */
2435 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2437 reclength &= 0xffff;
2439 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2441 /* size without argument data */
2442 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2443 if (pFuncRec->FKCCIC & 0x1000)
2444 optional -= pFuncRec->nrargs * sizeof(INT);
2446 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2447 ptfd->helpcontext = pFuncRec->HelpContext;
2449 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2450 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2452 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2454 if (pFuncRec->FKCCIC & 0x2000 )
2456 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2457 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2458 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2460 else
2461 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2463 else
2464 ptfd->Entry = (TLBString*)-1;
2466 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2467 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2469 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2470 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2472 /* fill the FuncDesc Structure */
2473 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2474 offset + infolen + ( i + 1) * sizeof(INT));
2476 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2477 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2478 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2479 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2480 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2481 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2482 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2484 /* nameoffset is sometimes -1 on the second half of a propget/propput
2485 * pair of functions */
2486 if ((nameoffset == -1) && (i > 0) &&
2487 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2488 TLB_is_propgetput(ptfd->funcdesc.invkind))
2489 ptfd->Name = ptfd_prev->Name;
2490 else
2491 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2493 MSFT_GetTdesc(pcx,
2494 pFuncRec->DataType,
2495 &ptfd->funcdesc.elemdescFunc.tdesc);
2497 /* do the parameters/arguments */
2498 if(pFuncRec->nrargs)
2500 int j = 0;
2501 MSFT_ParameterInfo paraminfo;
2503 ptfd->funcdesc.lprgelemdescParam =
2504 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2506 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2508 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2509 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2511 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2513 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2515 MSFT_GetTdesc(pcx,
2516 paraminfo.DataType,
2517 &elemdesc->tdesc);
2519 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2521 /* name */
2522 if (paraminfo.oName != -1)
2523 ptfd->pParamDesc[j].Name =
2524 MSFT_ReadName( pcx, paraminfo.oName );
2525 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2527 /* default value */
2528 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2529 (pFuncRec->FKCCIC & 0x1000) )
2531 INT* pInt = (INT *)((char *)pFuncRec +
2532 reclength -
2533 (pFuncRec->nrargs * 4) * sizeof(INT) );
2535 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2537 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2538 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2540 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2541 pInt[j], pcx);
2543 else
2544 elemdesc->u.paramdesc.pparamdescex = NULL;
2546 /* custom info */
2547 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2548 j*sizeof(pFuncRec->oArgCustData[0])) &&
2549 pFuncRec->FKCCIC & 0x80 )
2551 MSFT_CustData(pcx,
2552 pFuncRec->oArgCustData[j],
2553 &ptfd->pParamDesc[j].custdata_list);
2556 /* SEEK value = jump to offset,
2557 * from there jump to the end of record,
2558 * go back by (j-1) arguments
2560 MSFT_ReadLEDWords( &paraminfo ,
2561 sizeof(MSFT_ParameterInfo), pcx,
2562 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2563 * sizeof(MSFT_ParameterInfo)));
2567 /* scode is not used: archaic win16 stuff FIXME: right? */
2568 ptfd->funcdesc.cScodes = 0 ;
2569 ptfd->funcdesc.lprgscode = NULL ;
2571 ptfd_prev = ptfd;
2572 ++ptfd;
2573 recoffset += reclength;
2575 heap_free(recbuf);
2578 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2579 int cVars, int offset, TLBVarDesc ** pptvd)
2581 int infolen, nameoffset, reclength;
2582 char recbuf[256];
2583 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2584 TLBVarDesc *ptvd;
2585 int i;
2586 int recoffset;
2588 TRACE_(typelib)("\n");
2590 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2591 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2592 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2593 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2594 recoffset += offset+sizeof(INT);
2595 for(i=0;i<cVars;i++, ++ptvd){
2596 /* name, eventually add to a hash table */
2597 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2598 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2599 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2600 /* read the variable information record */
2601 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2602 reclength &= 0xff;
2603 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2605 /* optional data */
2606 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2607 ptvd->HelpContext = pVarRec->HelpContext;
2609 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2610 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2612 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2613 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2615 /* fill the VarDesc Structure */
2616 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2617 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2618 ptvd->vardesc.varkind = pVarRec->VarKind;
2619 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2620 MSFT_GetTdesc(pcx, pVarRec->DataType,
2621 &ptvd->vardesc.elemdescVar.tdesc);
2622 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2623 if(pVarRec->VarKind == VAR_CONST ){
2624 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2625 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2626 pVarRec->OffsValue, pcx);
2627 } else
2628 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2629 recoffset += reclength;
2633 /* process Implemented Interfaces of a com class */
2634 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2635 int offset)
2637 int i;
2638 MSFT_RefRecord refrec;
2639 TLBImplType *pImpl;
2641 TRACE_(typelib)("\n");
2643 pTI->impltypes = TLBImplType_Alloc(count);
2644 pImpl = pTI->impltypes;
2645 for(i=0;i<count;i++){
2646 if(offset<0) break; /* paranoia */
2647 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2648 pImpl->hRef = refrec.reftype;
2649 pImpl->implflags=refrec.flags;
2650 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2651 offset=refrec.onext;
2652 ++pImpl;
2656 #ifdef _WIN64
2657 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2658 * and some structures, and fix the alignment */
2659 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2661 if(info->typekind == TKIND_ALIAS){
2662 switch(info->tdescAlias->vt){
2663 case VT_BSTR:
2664 case VT_DISPATCH:
2665 case VT_UNKNOWN:
2666 case VT_PTR:
2667 case VT_SAFEARRAY:
2668 case VT_LPSTR:
2669 case VT_LPWSTR:
2670 info->cbSizeInstance = sizeof(void*);
2671 info->cbAlignment = sizeof(void*);
2672 break;
2673 case VT_CARRAY:
2674 case VT_USERDEFINED:
2675 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->cbSizeInstance, &info->cbAlignment);
2676 break;
2677 case VT_VARIANT:
2678 info->cbSizeInstance = sizeof(VARIANT);
2679 info->cbAlignment = 8;
2680 default:
2681 if(info->cbSizeInstance < sizeof(void*))
2682 info->cbAlignment = info->cbSizeInstance;
2683 else
2684 info->cbAlignment = sizeof(void*);
2685 break;
2687 }else if(info->typekind == TKIND_INTERFACE ||
2688 info->typekind == TKIND_DISPATCH ||
2689 info->typekind == TKIND_COCLASS){
2690 info->cbSizeInstance = sizeof(void*);
2691 info->cbAlignment = sizeof(void*);
2694 #endif
2697 * process a typeinfo record
2699 static ITypeInfoImpl * MSFT_DoTypeInfo(
2700 TLBContext *pcx,
2701 int count,
2702 ITypeLibImpl * pLibInfo)
2704 MSFT_TypeInfoBase tiBase;
2705 ITypeInfoImpl *ptiRet;
2707 TRACE_(typelib)("count=%u\n", count);
2709 ptiRet = ITypeInfoImpl_Constructor();
2710 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2711 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2713 /* this is where we are coming from */
2714 ptiRet->pTypeLib = pLibInfo;
2715 ptiRet->index=count;
2717 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2718 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2719 ptiRet->lpstrSchema=NULL; /* reserved */
2720 ptiRet->cbSizeInstance=tiBase.size;
2721 ptiRet->typekind=tiBase.typekind & 0xF;
2722 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2723 ptiRet->cVars=HIWORD(tiBase.cElement);
2724 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2725 ptiRet->wTypeFlags=tiBase.flags;
2726 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2727 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2728 ptiRet->cImplTypes=tiBase.cImplTypes;
2729 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2730 if(ptiRet->typekind == TKIND_ALIAS){
2731 TYPEDESC tmp;
2732 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2733 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2734 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2737 /* FIXME: */
2738 /* IDLDESC idldescType; *//* never saw this one != zero */
2740 /* name, eventually add to a hash table */
2741 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2742 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2743 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2744 /* help info */
2745 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2746 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2747 ptiRet->dwHelpContext=tiBase.helpcontext;
2749 if (ptiRet->typekind == TKIND_MODULE)
2750 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2752 /* note: InfoType's Help file and HelpStringDll come from the containing
2753 * library. Further HelpString and Docstring appear to be the same thing :(
2755 /* functions */
2756 if(ptiRet->cFuncs >0 )
2757 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2758 ptiRet->cVars,
2759 tiBase.memoffset, &ptiRet->funcdescs);
2760 /* variables */
2761 if(ptiRet->cVars >0 )
2762 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2763 ptiRet->cVars,
2764 tiBase.memoffset, &ptiRet->vardescs);
2765 if(ptiRet->cImplTypes >0 ) {
2766 switch(ptiRet->typekind)
2768 case TKIND_COCLASS:
2769 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2770 tiBase.datatype1);
2771 break;
2772 case TKIND_DISPATCH:
2773 /* This is not -1 when the interface is a non-base dual interface or
2774 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2775 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2776 not this interface.
2779 if (tiBase.datatype1 != -1)
2781 ptiRet->impltypes = TLBImplType_Alloc(1);
2782 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2784 break;
2785 default:
2786 ptiRet->impltypes = TLBImplType_Alloc(1);
2787 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2788 break;
2791 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2793 TRACE_(typelib)("%s guid: %s kind:%s\n",
2794 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2795 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2796 typekind_desc[ptiRet->typekind]);
2797 if (TRACE_ON(typelib))
2798 dump_TypeInfo(ptiRet);
2800 return ptiRet;
2803 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2805 char *string;
2806 INT16 len_str, len_piece;
2807 int offs = 0, lengthInChars;
2809 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2810 while (1) {
2811 TLBString *tlbstr;
2813 if (offs >= pcx->pTblDir->pStringtab.length)
2814 return S_OK;
2816 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2817 len_piece = len_str + sizeof(INT16);
2818 if(len_piece % 4)
2819 len_piece = (len_piece + 4) & ~0x3;
2820 if(len_piece < 8)
2821 len_piece = 8;
2823 string = heap_alloc(len_piece + 1);
2824 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2825 string[len_str] = '\0';
2827 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2828 string, -1, NULL, 0);
2829 if (!lengthInChars) {
2830 heap_free(string);
2831 return E_UNEXPECTED;
2834 tlbstr = heap_alloc(sizeof(TLBString));
2836 tlbstr->offset = offs;
2837 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2838 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2840 heap_free(string);
2842 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2844 offs += len_piece;
2848 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2850 TLBRefType *ref;
2851 int offs = 0;
2853 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2854 while (offs < pcx->pTblDir->pImpInfo.length) {
2855 MSFT_ImpInfo impinfo;
2856 TLBImpLib *pImpLib;
2858 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2860 ref = heap_alloc_zero(sizeof(TLBRefType));
2861 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2863 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2864 if(pImpLib->offset==impinfo.oImpFile)
2865 break;
2867 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2868 ref->reference = offs;
2869 ref->pImpTLInfo = pImpLib;
2870 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2871 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2872 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2873 ref->index = TLB_REF_USE_GUID;
2874 } else
2875 ref->index = impinfo.oGuid;
2876 }else{
2877 ERR("Cannot find a reference\n");
2878 ref->reference = -1;
2879 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2882 offs += sizeof(impinfo);
2885 return S_OK;
2888 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2889 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2890 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2891 * tradeoff here.
2893 static struct list tlb_cache = LIST_INIT(tlb_cache);
2894 static CRITICAL_SECTION cache_section;
2895 static CRITICAL_SECTION_DEBUG cache_section_debug =
2897 0, 0, &cache_section,
2898 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2899 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2901 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2904 typedef struct TLB_PEFile
2906 IUnknown IUnknown_iface;
2907 LONG refs;
2908 HMODULE dll;
2909 HRSRC typelib_resource;
2910 HGLOBAL typelib_global;
2911 LPVOID typelib_base;
2912 } TLB_PEFile;
2914 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2916 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2919 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2921 if (IsEqualIID(riid, &IID_IUnknown))
2923 *ppv = iface;
2924 IUnknown_AddRef(iface);
2925 return S_OK;
2927 *ppv = NULL;
2928 return E_NOINTERFACE;
2931 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2933 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2934 return InterlockedIncrement(&This->refs);
2937 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2939 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2940 ULONG refs = InterlockedDecrement(&This->refs);
2941 if (!refs)
2943 if (This->typelib_global)
2944 FreeResource(This->typelib_global);
2945 if (This->dll)
2946 FreeLibrary(This->dll);
2947 heap_free(This);
2949 return refs;
2952 static const IUnknownVtbl TLB_PEFile_Vtable =
2954 TLB_PEFile_QueryInterface,
2955 TLB_PEFile_AddRef,
2956 TLB_PEFile_Release
2959 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2961 TLB_PEFile *This;
2962 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2964 This = heap_alloc(sizeof(TLB_PEFile));
2965 if (!This)
2966 return E_OUTOFMEMORY;
2968 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2969 This->refs = 1;
2970 This->dll = NULL;
2971 This->typelib_resource = NULL;
2972 This->typelib_global = NULL;
2973 This->typelib_base = NULL;
2975 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2976 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2978 if (This->dll)
2980 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2981 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2982 if (This->typelib_resource)
2984 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2985 if (This->typelib_global)
2987 This->typelib_base = LockResource(This->typelib_global);
2989 if (This->typelib_base)
2991 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2992 *ppBase = This->typelib_base;
2993 *ppFile = &This->IUnknown_iface;
2994 return S_OK;
2999 TRACE("No TYPELIB resource found\n");
3000 hr = E_FAIL;
3003 TLB_PEFile_Release(&This->IUnknown_iface);
3004 return hr;
3007 typedef struct TLB_NEFile
3009 IUnknown IUnknown_iface;
3010 LONG refs;
3011 LPVOID typelib_base;
3012 } TLB_NEFile;
3014 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
3016 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
3019 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3021 if (IsEqualIID(riid, &IID_IUnknown))
3023 *ppv = iface;
3024 IUnknown_AddRef(iface);
3025 return S_OK;
3027 *ppv = NULL;
3028 return E_NOINTERFACE;
3031 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3033 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3034 return InterlockedIncrement(&This->refs);
3037 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3039 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3040 ULONG refs = InterlockedDecrement(&This->refs);
3041 if (!refs)
3043 heap_free(This->typelib_base);
3044 heap_free(This);
3046 return refs;
3049 static const IUnknownVtbl TLB_NEFile_Vtable =
3051 TLB_NEFile_QueryInterface,
3052 TLB_NEFile_AddRef,
3053 TLB_NEFile_Release
3056 /***********************************************************************
3057 * read_xx_header [internal]
3059 static int read_xx_header( HFILE lzfd )
3061 IMAGE_DOS_HEADER mzh;
3062 char magic[3];
3064 LZSeek( lzfd, 0, SEEK_SET );
3065 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3066 return 0;
3067 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3068 return 0;
3070 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3071 if ( 2 != LZRead( lzfd, magic, 2 ) )
3072 return 0;
3074 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3076 if ( magic[0] == 'N' && magic[1] == 'E' )
3077 return IMAGE_OS2_SIGNATURE;
3078 if ( magic[0] == 'P' && magic[1] == 'E' )
3079 return IMAGE_NT_SIGNATURE;
3081 magic[2] = '\0';
3082 WARN("Can't handle %s files.\n", magic );
3083 return 0;
3087 /***********************************************************************
3088 * find_ne_resource [internal]
3090 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3091 DWORD *resLen, DWORD *resOff )
3093 IMAGE_OS2_HEADER nehd;
3094 NE_TYPEINFO *typeInfo;
3095 NE_NAMEINFO *nameInfo;
3096 DWORD nehdoffset;
3097 LPBYTE resTab;
3098 DWORD resTabSize;
3099 int count;
3101 /* Read in NE header */
3102 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3103 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3105 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3106 if ( !resTabSize )
3108 TRACE("No resources in NE dll\n" );
3109 return FALSE;
3112 /* Read in resource table */
3113 resTab = heap_alloc( resTabSize );
3114 if ( !resTab ) return FALSE;
3116 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3117 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3119 heap_free( resTab );
3120 return FALSE;
3123 /* Find resource */
3124 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3126 if (!IS_INTRESOURCE(typeid)) /* named type */
3128 BYTE len = strlen( typeid );
3129 while (typeInfo->type_id)
3131 if (!(typeInfo->type_id & 0x8000))
3133 BYTE *p = resTab + typeInfo->type_id;
3134 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3136 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3137 typeInfo->count * sizeof(NE_NAMEINFO));
3140 else /* numeric type id */
3142 WORD id = LOWORD(typeid) | 0x8000;
3143 while (typeInfo->type_id)
3145 if (typeInfo->type_id == id) goto found_type;
3146 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3147 typeInfo->count * sizeof(NE_NAMEINFO));
3150 TRACE("No typeid entry found for %p\n", typeid );
3151 heap_free( resTab );
3152 return FALSE;
3154 found_type:
3155 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3157 if (!IS_INTRESOURCE(resid)) /* named resource */
3159 BYTE len = strlen( resid );
3160 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3162 BYTE *p = resTab + nameInfo->id;
3163 if (nameInfo->id & 0x8000) continue;
3164 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3167 else /* numeric resource id */
3169 WORD id = LOWORD(resid) | 0x8000;
3170 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3171 if (nameInfo->id == id) goto found_name;
3173 TRACE("No resid entry found for %p\n", typeid );
3174 heap_free( resTab );
3175 return FALSE;
3177 found_name:
3178 /* Return resource data */
3179 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3180 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3182 heap_free( resTab );
3183 return TRUE;
3186 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3188 HFILE lzfd = -1;
3189 OFSTRUCT ofs;
3190 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3191 TLB_NEFile *This;
3193 This = heap_alloc(sizeof(TLB_NEFile));
3194 if (!This) return E_OUTOFMEMORY;
3196 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3197 This->refs = 1;
3198 This->typelib_base = NULL;
3200 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3201 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3203 DWORD reslen, offset;
3204 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3206 This->typelib_base = heap_alloc(reslen);
3207 if( !This->typelib_base )
3208 hr = E_OUTOFMEMORY;
3209 else
3211 LZSeek( lzfd, offset, SEEK_SET );
3212 reslen = LZRead( lzfd, This->typelib_base, reslen );
3213 LZClose( lzfd );
3214 *ppBase = This->typelib_base;
3215 *pdwTLBLength = reslen;
3216 *ppFile = &This->IUnknown_iface;
3217 return S_OK;
3222 if( lzfd >= 0) LZClose( lzfd );
3223 TLB_NEFile_Release(&This->IUnknown_iface);
3224 return hr;
3227 typedef struct TLB_Mapping
3229 IUnknown IUnknown_iface;
3230 LONG refs;
3231 HANDLE file;
3232 HANDLE mapping;
3233 LPVOID typelib_base;
3234 } TLB_Mapping;
3236 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3238 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3241 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3243 if (IsEqualIID(riid, &IID_IUnknown))
3245 *ppv = iface;
3246 IUnknown_AddRef(iface);
3247 return S_OK;
3249 *ppv = NULL;
3250 return E_NOINTERFACE;
3253 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3255 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3256 return InterlockedIncrement(&This->refs);
3259 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3261 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3262 ULONG refs = InterlockedDecrement(&This->refs);
3263 if (!refs)
3265 if (This->typelib_base)
3266 UnmapViewOfFile(This->typelib_base);
3267 if (This->mapping)
3268 CloseHandle(This->mapping);
3269 if (This->file != INVALID_HANDLE_VALUE)
3270 CloseHandle(This->file);
3271 heap_free(This);
3273 return refs;
3276 static const IUnknownVtbl TLB_Mapping_Vtable =
3278 TLB_Mapping_QueryInterface,
3279 TLB_Mapping_AddRef,
3280 TLB_Mapping_Release
3283 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3285 TLB_Mapping *This;
3287 This = heap_alloc(sizeof(TLB_Mapping));
3288 if (!This)
3289 return E_OUTOFMEMORY;
3291 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3292 This->refs = 1;
3293 This->file = INVALID_HANDLE_VALUE;
3294 This->mapping = NULL;
3295 This->typelib_base = NULL;
3297 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3298 if (INVALID_HANDLE_VALUE != This->file)
3300 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3301 if (This->mapping)
3303 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3304 if(This->typelib_base)
3306 /* retrieve file size */
3307 *pdwTLBLength = GetFileSize(This->file, NULL);
3308 *ppBase = This->typelib_base;
3309 *ppFile = &This->IUnknown_iface;
3310 return S_OK;
3315 IUnknown_Release(&This->IUnknown_iface);
3316 return TYPE_E_CANTLOADLIBRARY;
3319 /****************************************************************************
3320 * TLB_ReadTypeLib
3322 * find the type of the typelib file and map the typelib resource into
3323 * the memory
3326 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3327 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3329 ITypeLibImpl *entry;
3330 HRESULT ret;
3331 INT index = 1;
3332 LPWSTR index_str, file = (LPWSTR)pszFileName;
3333 LPVOID pBase = NULL;
3334 DWORD dwTLBLength = 0;
3335 IUnknown *pFile = NULL;
3336 HANDLE h;
3338 *ppTypeLib = NULL;
3340 index_str = strrchrW(pszFileName, '\\');
3341 if(index_str && *++index_str != '\0')
3343 LPWSTR end_ptr;
3344 LONG idx = strtolW(index_str, &end_ptr, 10);
3345 if(*end_ptr == '\0')
3347 int str_len = index_str - pszFileName - 1;
3348 index = idx;
3349 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3350 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3351 file[str_len] = 0;
3355 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3357 if(strchrW(file, '\\'))
3359 lstrcpyW(pszPath, file);
3361 else
3363 int len = GetSystemDirectoryW(pszPath, cchPath);
3364 pszPath[len] = '\\';
3365 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3369 if(file != pszFileName) heap_free(file);
3371 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3372 if(h != INVALID_HANDLE_VALUE){
3373 FILE_NAME_INFORMATION *info;
3374 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3375 BOOL br;
3377 info = (FILE_NAME_INFORMATION*)data;
3378 /* GetFileInformationByHandleEx returns the path of the file without
3379 * WOW64 redirection */
3380 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3381 if(br){
3382 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3383 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3385 CloseHandle(h);
3388 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3390 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3391 EnterCriticalSection(&cache_section);
3392 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3394 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3396 TRACE("cache hit\n");
3397 *ppTypeLib = &entry->ITypeLib2_iface;
3398 ITypeLib2_AddRef(*ppTypeLib);
3399 LeaveCriticalSection(&cache_section);
3400 return S_OK;
3403 LeaveCriticalSection(&cache_section);
3405 /* now actually load and parse the typelib */
3407 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3408 if (ret == TYPE_E_CANTLOADLIBRARY)
3409 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3410 if (ret == TYPE_E_CANTLOADLIBRARY)
3411 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3412 if (SUCCEEDED(ret))
3414 if (dwTLBLength >= 4)
3416 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3417 if (dwSignature == MSFT_SIGNATURE)
3418 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3419 else if (dwSignature == SLTG_SIGNATURE)
3420 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3421 else
3423 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3424 ret = TYPE_E_CANTLOADLIBRARY;
3427 else
3428 ret = TYPE_E_CANTLOADLIBRARY;
3429 IUnknown_Release(pFile);
3432 if(*ppTypeLib) {
3433 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3435 TRACE("adding to cache\n");
3436 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3437 lstrcpyW(impl->path, pszPath);
3438 /* We should really canonicalise the path here. */
3439 impl->index = index;
3441 /* FIXME: check if it has added already in the meantime */
3442 EnterCriticalSection(&cache_section);
3443 list_add_head(&tlb_cache, &impl->entry);
3444 LeaveCriticalSection(&cache_section);
3445 ret = S_OK;
3447 else
3449 if(ret != E_FAIL)
3450 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3452 ret = TYPE_E_CANTLOADLIBRARY;
3456 return ret;
3459 /*================== ITypeLib(2) Methods ===================================*/
3461 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3463 ITypeLibImpl* pTypeLibImpl;
3465 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3466 if (!pTypeLibImpl) return NULL;
3468 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3469 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3470 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3471 pTypeLibImpl->ref = 1;
3473 list_init(&pTypeLibImpl->implib_list);
3474 list_init(&pTypeLibImpl->custdata_list);
3475 list_init(&pTypeLibImpl->name_list);
3476 list_init(&pTypeLibImpl->string_list);
3477 list_init(&pTypeLibImpl->guid_list);
3478 list_init(&pTypeLibImpl->ref_list);
3479 pTypeLibImpl->dispatch_href = -1;
3481 return pTypeLibImpl;
3484 /****************************************************************************
3485 * ITypeLib2_Constructor_MSFT
3487 * loading an MSFT typelib from an in-memory image
3489 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3491 TLBContext cx;
3492 LONG lPSegDir;
3493 MSFT_Header tlbHeader;
3494 MSFT_SegDir tlbSegDir;
3495 ITypeLibImpl * pTypeLibImpl;
3496 int i;
3498 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3500 pTypeLibImpl = TypeLibImpl_Constructor();
3501 if (!pTypeLibImpl) return NULL;
3503 /* get pointer to beginning of typelib data */
3504 cx.pos = 0;
3505 cx.oStart=0;
3506 cx.mapping = pLib;
3507 cx.pLibInfo = pTypeLibImpl;
3508 cx.length = dwTLBLength;
3510 /* read header */
3511 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3512 TRACE_(typelib)("header:\n");
3513 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3514 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3515 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3516 return NULL;
3518 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3520 /* there is a small amount of information here until the next important
3521 * part:
3522 * the segment directory . Try to calculate the amount of data */
3523 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3525 /* now read the segment directory */
3526 TRACE("read segment directory (at %d)\n",lPSegDir);
3527 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3528 cx.pTblDir = &tlbSegDir;
3530 /* just check two entries */
3531 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3533 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3534 heap_free(pTypeLibImpl);
3535 return NULL;
3538 MSFT_ReadAllNames(&cx);
3539 MSFT_ReadAllStrings(&cx);
3540 MSFT_ReadAllGuids(&cx);
3542 /* now fill our internal data */
3543 /* TLIBATTR fields */
3544 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3546 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3547 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3548 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3549 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3550 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3552 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3553 pTypeLibImpl->lcid = tlbHeader.lcid;
3555 /* name, eventually add to a hash table */
3556 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3558 /* help info */
3559 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3560 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3562 if( tlbHeader.varflags & HELPDLLFLAG)
3564 int offset;
3565 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3566 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3569 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3571 /* custom data */
3572 if(tlbHeader.CustomDataOffset >= 0)
3574 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3577 /* fill in type descriptions */
3578 if(tlbSegDir.pTypdescTab.length > 0)
3580 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3581 INT16 td[4];
3582 pTypeLibImpl->ctTypeDesc = cTD;
3583 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3584 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3585 for(i=0; i<cTD; )
3587 /* FIXME: add several sanity checks here */
3588 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3589 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3591 /* FIXME: check safearray */
3592 if(td[3] < 0)
3593 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3594 else
3595 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3597 else if(td[0] == VT_CARRAY)
3599 /* array descr table here */
3600 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3602 else if(td[0] == VT_USERDEFINED)
3604 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3606 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3609 /* second time around to fill the array subscript info */
3610 for(i=0;i<cTD;i++)
3612 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3613 if(tlbSegDir.pArrayDescriptions.offset>0)
3615 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3616 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3618 if(td[1]<0)
3619 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3620 else
3621 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3623 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3625 for(j = 0; j<td[2]; j++)
3627 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3628 sizeof(INT), &cx, DO_NOT_SEEK);
3629 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3630 sizeof(INT), &cx, DO_NOT_SEEK);
3633 else
3635 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3636 ERR("didn't find array description data\n");
3641 /* imported type libs */
3642 if(tlbSegDir.pImpFiles.offset>0)
3644 TLBImpLib *pImpLib;
3645 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3646 UINT16 size;
3648 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3650 char *name;
3652 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3653 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3654 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3656 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3657 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3658 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3659 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3661 size >>= 2;
3662 name = heap_alloc_zero(size+1);
3663 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3664 pImpLib->name = TLB_MultiByteToBSTR(name);
3665 heap_free(name);
3667 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3668 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3670 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3674 MSFT_ReadAllRefs(&cx);
3676 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3678 /* type infos */
3679 if(tlbHeader.nrtypeinfos >= 0 )
3681 ITypeInfoImpl **ppTI;
3683 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3685 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3687 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3689 ++ppTI;
3690 (pTypeLibImpl->TypeInfoCount)++;
3694 #ifdef _WIN64
3695 if(pTypeLibImpl->syskind == SYS_WIN32){
3696 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3697 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3699 #endif
3701 TRACE("(%p)\n", pTypeLibImpl);
3702 return &pTypeLibImpl->ITypeLib2_iface;
3706 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3708 char b[3];
3709 int i;
3710 short s;
3712 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3713 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3714 return FALSE;
3717 guid->Data4[0] = s >> 8;
3718 guid->Data4[1] = s & 0xff;
3720 b[2] = '\0';
3721 for(i = 0; i < 6; i++) {
3722 memcpy(b, str + 24 + 2 * i, 2);
3723 guid->Data4[i + 2] = strtol(b, NULL, 16);
3725 return TRUE;
3728 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3730 WORD bytelen;
3731 DWORD len;
3732 BSTR tmp_str;
3734 *pStr = NULL;
3735 bytelen = *(const WORD*)ptr;
3736 if(bytelen == 0xffff) return 2;
3738 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3739 tmp_str = SysAllocStringLen(NULL, len);
3740 if (tmp_str) {
3741 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3742 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3743 SysFreeString(tmp_str);
3745 return bytelen + 2;
3748 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3750 WORD bytelen;
3752 *str = NULL;
3753 bytelen = *(const WORD*)ptr;
3754 if(bytelen == 0xffff) return 2;
3755 *str = heap_alloc(bytelen + 1);
3756 memcpy(*str, ptr + 2, bytelen);
3757 (*str)[bytelen] = '\0';
3758 return bytelen + 2;
3761 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3763 BSTR tmp_str;
3764 TLBString *tlbstr;
3766 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3767 if (tlbstr->offset == offset)
3768 return tlbstr;
3771 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3772 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3773 SysFreeString(tmp_str);
3775 return tlbstr;
3778 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3780 char *ptr = pLibBlk;
3781 WORD w;
3783 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3784 FIXME("libblk magic = %04x\n", w);
3785 return 0;
3788 ptr += 6;
3789 if((w = *(WORD*)ptr) != 0xffff) {
3790 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3791 ptr += w;
3793 ptr += 2;
3795 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3797 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3799 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3800 ptr += 4;
3802 pTypeLibImpl->syskind = *(WORD*)ptr;
3803 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3804 ptr += 2;
3806 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3807 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3808 else
3809 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3810 ptr += 2;
3812 ptr += 4; /* skip res12 */
3814 pTypeLibImpl->libflags = *(WORD*)ptr;
3815 ptr += 2;
3817 pTypeLibImpl->ver_major = *(WORD*)ptr;
3818 ptr += 2;
3820 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3821 ptr += 2;
3823 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3824 ptr += sizeof(GUID);
3826 return ptr - (char*)pLibBlk;
3829 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3830 typedef struct
3832 unsigned int num;
3833 HREFTYPE refs[1];
3834 } sltg_ref_lookup_t;
3836 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3837 HREFTYPE *typelib_ref)
3839 if(table && typeinfo_ref < table->num)
3841 *typelib_ref = table->refs[typeinfo_ref];
3842 return S_OK;
3845 ERR_(typelib)("Unable to find reference\n");
3846 *typelib_ref = -1;
3847 return E_FAIL;
3850 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3852 BOOL done = FALSE;
3854 while(!done) {
3855 if((*pType & 0xe00) == 0xe00) {
3856 pTD->vt = VT_PTR;
3857 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3858 pTD = pTD->u.lptdesc;
3860 switch(*pType & 0x3f) {
3861 case VT_PTR:
3862 pTD->vt = VT_PTR;
3863 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3864 pTD = pTD->u.lptdesc;
3865 break;
3867 case VT_USERDEFINED:
3868 pTD->vt = VT_USERDEFINED;
3869 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3870 done = TRUE;
3871 break;
3873 case VT_CARRAY:
3875 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3876 array */
3878 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3880 pTD->vt = VT_CARRAY;
3881 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3882 pTD->u.lpadesc->cDims = pSA->cDims;
3883 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3884 pSA->cDims * sizeof(SAFEARRAYBOUND));
3886 pTD = &pTD->u.lpadesc->tdescElem;
3887 break;
3890 case VT_SAFEARRAY:
3892 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3893 useful? */
3895 pType++;
3896 pTD->vt = VT_SAFEARRAY;
3897 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3898 pTD = pTD->u.lptdesc;
3899 break;
3901 default:
3902 pTD->vt = *pType & 0x3f;
3903 done = TRUE;
3904 break;
3906 pType++;
3908 return pType;
3911 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3912 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3914 /* Handle [in/out] first */
3915 if((*pType & 0xc000) == 0xc000)
3916 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3917 else if(*pType & 0x8000)
3918 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3919 else if(*pType & 0x4000)
3920 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3921 else
3922 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3924 if(*pType & 0x2000)
3925 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3927 if(*pType & 0x80)
3928 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3930 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3934 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3935 char *pNameTable)
3937 unsigned int ref;
3938 char *name;
3939 TLBRefType *ref_type;
3940 sltg_ref_lookup_t *table;
3941 HREFTYPE typelib_ref;
3943 if(pRef->magic != SLTG_REF_MAGIC) {
3944 FIXME("Ref magic = %x\n", pRef->magic);
3945 return NULL;
3947 name = ( (char*)pRef->names + pRef->number);
3949 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3950 table->num = pRef->number >> 3;
3952 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3954 /* We don't want the first href to be 0 */
3955 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3957 for(ref = 0; ref < pRef->number >> 3; ref++) {
3958 char *refname;
3959 unsigned int lib_offs, type_num;
3961 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3963 name += SLTG_ReadStringA(name, &refname);
3964 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3965 FIXME_(typelib)("Can't sscanf ref\n");
3966 if(lib_offs != 0xffff) {
3967 TLBImpLib *import;
3969 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3970 if(import->offset == lib_offs)
3971 break;
3973 if(&import->entry == &pTL->implib_list) {
3974 char fname[MAX_PATH+1];
3975 int len;
3976 GUID tmpguid;
3978 import = heap_alloc_zero(sizeof(*import));
3979 import->offset = lib_offs;
3980 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3981 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3982 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3983 &import->wVersionMajor,
3984 &import->wVersionMinor,
3985 &import->lcid, fname) != 4) {
3986 FIXME_(typelib)("can't sscanf ref %s\n",
3987 pNameTable + lib_offs + 40);
3989 len = strlen(fname);
3990 if(fname[len-1] != '#')
3991 FIXME("fname = %s\n", fname);
3992 fname[len-1] = '\0';
3993 import->name = TLB_MultiByteToBSTR(fname);
3994 list_add_tail(&pTL->implib_list, &import->entry);
3996 ref_type->pImpTLInfo = import;
3998 /* Store a reference to IDispatch */
3999 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
4000 pTL->dispatch_href = typelib_ref;
4002 } else { /* internal ref */
4003 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
4005 ref_type->reference = typelib_ref;
4006 ref_type->index = type_num;
4008 heap_free(refname);
4009 list_add_tail(&pTL->ref_list, &ref_type->entry);
4011 table->refs[ref] = typelib_ref;
4012 typelib_ref += 4;
4014 if((BYTE)*name != SLTG_REF_MAGIC)
4015 FIXME_(typelib)("End of ref block magic = %x\n", *name);
4016 dump_TLBRefType(pTL);
4017 return table;
4020 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
4021 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
4023 SLTG_ImplInfo *info;
4024 TLBImplType *pImplType;
4025 /* I don't really get this structure, usually it's 0x16 bytes
4026 long, but iuser.tlb contains some that are 0x18 bytes long.
4027 That's ok because we can use the next ptr to jump to the next
4028 one. But how do we know the length of the last one? The WORD
4029 at offs 0x8 might be the clue. For now I'm just assuming that
4030 the last one is the regular 0x16 bytes. */
4032 info = (SLTG_ImplInfo*)pBlk;
4033 while(1){
4034 pTI->cImplTypes++;
4035 if(info->next == 0xffff)
4036 break;
4037 info = (SLTG_ImplInfo*)(pBlk + info->next);
4040 info = (SLTG_ImplInfo*)pBlk;
4041 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
4042 pImplType = pTI->impltypes;
4043 while(1) {
4044 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4045 pImplType->implflags = info->impltypeflags;
4046 ++pImplType;
4048 if(info->next == 0xffff)
4049 break;
4050 if(OneOnly)
4051 FIXME_(typelib)("Interface inheriting more than one interface\n");
4052 info = (SLTG_ImplInfo*)(pBlk + info->next);
4054 info++; /* see comment at top of function */
4055 return (char*)info;
4058 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4059 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4061 TLBVarDesc *pVarDesc;
4062 const TLBString *prevName = NULL;
4063 SLTG_Variable *pItem;
4064 unsigned short i;
4065 WORD *pType;
4067 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4069 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4070 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4072 pVarDesc->vardesc.memid = pItem->memid;
4074 if (pItem->magic != SLTG_VAR_MAGIC &&
4075 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4076 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4077 return;
4080 if (pItem->name == 0xfffe)
4081 pVarDesc->Name = prevName;
4082 else
4083 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4085 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4086 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4087 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4089 if(pItem->flags & 0x02)
4090 pType = &pItem->type;
4091 else
4092 pType = (WORD*)(pBlk + pItem->type);
4094 if (pItem->flags & ~0xda)
4095 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4097 SLTG_DoElem(pType, pBlk,
4098 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4100 if (TRACE_ON(typelib)) {
4101 char buf[300];
4102 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4103 TRACE_(typelib)("elemdescVar: %s\n", buf);
4106 if (pItem->flags & 0x40) {
4107 TRACE_(typelib)("VAR_DISPATCH\n");
4108 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4110 else if (pItem->flags & 0x10) {
4111 TRACE_(typelib)("VAR_CONST\n");
4112 pVarDesc->vardesc.varkind = VAR_CONST;
4113 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4114 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4115 if (pItem->flags & 0x08)
4116 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4117 else {
4118 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4120 case VT_LPSTR:
4121 case VT_LPWSTR:
4122 case VT_BSTR:
4124 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4125 BSTR str;
4126 TRACE_(typelib)("len = %u\n", len);
4127 if (len == 0xffff) {
4128 str = NULL;
4129 } else {
4130 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4131 str = SysAllocStringLen(NULL, alloc_len);
4132 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4134 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4135 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4136 break;
4138 case VT_I2:
4139 case VT_UI2:
4140 case VT_I4:
4141 case VT_UI4:
4142 case VT_INT:
4143 case VT_UINT:
4144 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4145 *(INT*)(pBlk + pItem->byte_offs);
4146 break;
4147 default:
4148 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4152 else {
4153 TRACE_(typelib)("VAR_PERINSTANCE\n");
4154 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4155 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4158 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4159 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4161 if (pItem->flags & 0x80)
4162 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4164 prevName = pVarDesc->Name;
4166 pTI->cVars = cVars;
4169 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4170 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4172 SLTG_Function *pFunc;
4173 unsigned short i;
4174 TLBFuncDesc *pFuncDesc;
4176 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4178 pFuncDesc = pTI->funcdescs;
4179 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4180 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4182 int param;
4183 WORD *pType, *pArg;
4185 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4186 case SLTG_FUNCTION_MAGIC:
4187 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4188 break;
4189 case SLTG_DISPATCH_FUNCTION_MAGIC:
4190 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4191 break;
4192 case SLTG_STATIC_FUNCTION_MAGIC:
4193 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4194 break;
4195 default:
4196 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4197 continue;
4199 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4201 pFuncDesc->funcdesc.memid = pFunc->dispid;
4202 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4203 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4204 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4205 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4206 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4208 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4209 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4211 if(pFunc->retnextopt & 0x80)
4212 pType = &pFunc->rettype;
4213 else
4214 pType = (WORD*)(pBlk + pFunc->rettype);
4216 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4218 pFuncDesc->funcdesc.lprgelemdescParam =
4219 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4220 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4222 pArg = (WORD*)(pBlk + pFunc->arg_off);
4224 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4225 char *paramName = pNameTable + *pArg;
4226 BOOL HaveOffs;
4227 /* If arg type follows then paramName points to the 2nd
4228 letter of the name, else the next WORD is an offset to
4229 the arg type and paramName points to the first letter.
4230 So let's take one char off paramName and see if we're
4231 pointing at an alpha-numeric char. However if *pArg is
4232 0xffff or 0xfffe then the param has no name, the former
4233 meaning that the next WORD is the type, the latter
4234 meaning that the next WORD is an offset to the type. */
4236 HaveOffs = FALSE;
4237 if(*pArg == 0xffff)
4238 paramName = NULL;
4239 else if(*pArg == 0xfffe) {
4240 paramName = NULL;
4241 HaveOffs = TRUE;
4243 else if(paramName[-1] && !isalnum(paramName[-1]))
4244 HaveOffs = TRUE;
4246 pArg++;
4248 if(HaveOffs) { /* the next word is an offset to type */
4249 pType = (WORD*)(pBlk + *pArg);
4250 SLTG_DoElem(pType, pBlk,
4251 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4252 pArg++;
4253 } else {
4254 if(paramName)
4255 paramName--;
4256 pArg = SLTG_DoElem(pArg, pBlk,
4257 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4260 /* Are we an optional param ? */
4261 if(pFuncDesc->funcdesc.cParams - param <=
4262 pFuncDesc->funcdesc.cParamsOpt)
4263 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4265 if(paramName) {
4266 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4267 paramName - pNameTable, pTI->pTypeLib);
4268 } else {
4269 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4273 pTI->cFuncs = cFuncs;
4276 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4277 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4278 SLTG_TypeInfoTail *pTITail)
4280 char *pFirstItem;
4281 sltg_ref_lookup_t *ref_lookup = NULL;
4283 if(pTIHeader->href_table != 0xffffffff) {
4284 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4285 pNameTable);
4288 pFirstItem = pBlk;
4290 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4291 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4293 heap_free(ref_lookup);
4297 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4298 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4299 const SLTG_TypeInfoTail *pTITail)
4301 char *pFirstItem;
4302 sltg_ref_lookup_t *ref_lookup = NULL;
4304 if(pTIHeader->href_table != 0xffffffff) {
4305 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4306 pNameTable);
4309 pFirstItem = pBlk;
4311 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4312 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4315 if (pTITail->funcs_off != 0xffff)
4316 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4318 heap_free(ref_lookup);
4320 if (TRACE_ON(typelib))
4321 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4324 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4325 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4326 const SLTG_TypeInfoTail *pTITail)
4328 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4331 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4332 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4333 const SLTG_TypeInfoTail *pTITail)
4335 WORD *pType;
4336 sltg_ref_lookup_t *ref_lookup = NULL;
4338 if (pTITail->simple_alias) {
4339 /* if simple alias, no more processing required */
4340 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4341 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4342 return;
4345 if(pTIHeader->href_table != 0xffffffff) {
4346 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4347 pNameTable);
4350 /* otherwise it is an offset to a type */
4351 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4353 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4354 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4356 heap_free(ref_lookup);
4359 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4360 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4361 const SLTG_TypeInfoTail *pTITail)
4363 sltg_ref_lookup_t *ref_lookup = NULL;
4364 if (pTIHeader->href_table != 0xffffffff)
4365 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4366 pNameTable);
4368 if (pTITail->vars_off != 0xffff)
4369 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4371 if (pTITail->funcs_off != 0xffff)
4372 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4374 if (pTITail->impls_off != 0xffff)
4375 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4377 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4378 * of dispinterface functions including the IDispatch ones, so
4379 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4380 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4382 heap_free(ref_lookup);
4383 if (TRACE_ON(typelib))
4384 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4387 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4388 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4389 const SLTG_TypeInfoTail *pTITail)
4391 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4394 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4395 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4396 const SLTG_TypeInfoTail *pTITail)
4398 sltg_ref_lookup_t *ref_lookup = NULL;
4399 if (pTIHeader->href_table != 0xffffffff)
4400 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4401 pNameTable);
4403 if (pTITail->vars_off != 0xffff)
4404 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4406 if (pTITail->funcs_off != 0xffff)
4407 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4408 heap_free(ref_lookup);
4409 if (TRACE_ON(typelib))
4410 dump_TypeInfo(pTI);
4413 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4414 manageable copy of it into this */
4415 typedef struct {
4416 WORD small_no;
4417 char *index_name;
4418 char *other_name;
4419 WORD res1a;
4420 WORD name_offs;
4421 WORD more_bytes;
4422 char *extra;
4423 WORD res20;
4424 DWORD helpcontext;
4425 WORD res26;
4426 GUID uuid;
4427 } SLTG_InternalOtherTypeInfo;
4429 /****************************************************************************
4430 * ITypeLib2_Constructor_SLTG
4432 * loading a SLTG typelib from an in-memory image
4434 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4436 ITypeLibImpl *pTypeLibImpl;
4437 SLTG_Header *pHeader;
4438 SLTG_BlkEntry *pBlkEntry;
4439 SLTG_Magic *pMagic;
4440 SLTG_Index *pIndex;
4441 SLTG_Pad9 *pPad9;
4442 LPVOID pBlk, pFirstBlk;
4443 SLTG_LibBlk *pLibBlk;
4444 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4445 char *pAfterOTIBlks = NULL;
4446 char *pNameTable, *ptr;
4447 int i;
4448 DWORD len, order;
4449 ITypeInfoImpl **ppTypeInfoImpl;
4451 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4454 pTypeLibImpl = TypeLibImpl_Constructor();
4455 if (!pTypeLibImpl) return NULL;
4457 pHeader = pLib;
4459 TRACE_(typelib)("header:\n");
4460 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4461 pHeader->nrOfFileBlks );
4462 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4463 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4464 pHeader->SLTG_magic);
4465 return NULL;
4468 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4469 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4471 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4472 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4474 /* Next we have a magic block */
4475 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4477 /* Let's see if we're still in sync */
4478 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4479 sizeof(SLTG_COMPOBJ_MAGIC))) {
4480 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4481 return NULL;
4483 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4484 sizeof(SLTG_DIR_MAGIC))) {
4485 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4486 return NULL;
4489 pIndex = (SLTG_Index*)(pMagic+1);
4491 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4493 pFirstBlk = pPad9 + 1;
4495 /* We'll set up a ptr to the main library block, which is the last one. */
4497 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4498 pBlkEntry[order].next != 0;
4499 order = pBlkEntry[order].next - 1, i++) {
4500 pBlk = (char*)pBlk + pBlkEntry[order].len;
4502 pLibBlk = pBlk;
4504 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4506 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4507 interspersed */
4509 len += 0x40;
4511 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4513 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4516 ptr = (char*)pLibBlk + len;
4518 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4519 WORD w, extra;
4520 len = 0;
4522 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4524 w = *(WORD*)(ptr + 2);
4525 if(w != 0xffff) {
4526 len += w;
4527 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4528 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4529 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4531 w = *(WORD*)(ptr + 4 + len);
4532 if(w != 0xffff) {
4533 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4534 len += w;
4535 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4536 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4537 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4539 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4540 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4541 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4542 if(extra) {
4543 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4544 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4545 len += extra;
4547 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4548 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4549 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4550 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4551 len += sizeof(SLTG_OtherTypeInfo);
4552 ptr += len;
4555 pAfterOTIBlks = ptr;
4557 /* Skip this WORD and get the next DWORD */
4558 len = *(DWORD*)(pAfterOTIBlks + 2);
4560 /* Now add this to pLibBLk look at what we're pointing at and
4561 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4562 dust and we should be pointing at the beginning of the name
4563 table */
4565 pNameTable = (char*)pLibBlk + len;
4567 switch(*(WORD*)pNameTable) {
4568 case 0xffff:
4569 break;
4570 case 0x0200:
4571 pNameTable += 0x20;
4572 break;
4573 default:
4574 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4575 break;
4578 pNameTable += 0x216;
4580 pNameTable += 2;
4582 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4584 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4587 /* Hopefully we now have enough ptrs set up to actually read in
4588 some TypeInfos. It's not clear which order to do them in, so
4589 I'll just follow the links along the BlkEntry chain and read
4590 them in the order in which they are in the file */
4592 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4593 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4595 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4596 pBlkEntry[order].next != 0;
4597 order = pBlkEntry[order].next - 1, i++) {
4599 SLTG_TypeInfoHeader *pTIHeader;
4600 SLTG_TypeInfoTail *pTITail;
4601 SLTG_MemberHeader *pMemHeader;
4603 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4604 FIXME_(typelib)("Index strings don't match\n");
4605 heap_free(pOtherTypeInfoBlks);
4606 return NULL;
4609 pTIHeader = pBlk;
4610 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4611 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4612 heap_free(pOtherTypeInfoBlks);
4613 return NULL;
4615 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4616 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4617 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4619 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4620 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4621 (*ppTypeInfoImpl)->index = i;
4622 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4623 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4624 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4625 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4626 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4627 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4628 (*ppTypeInfoImpl)->wTypeFlags =
4629 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4631 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4632 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4634 if((pTIHeader->typeflags1 & 7) != 2)
4635 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4636 if(pTIHeader->typeflags3 != 2)
4637 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4639 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4640 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4641 typekind_desc[pTIHeader->typekind],
4642 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4643 (*ppTypeInfoImpl)->wTypeFlags);
4645 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4647 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4649 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4650 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4651 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4653 switch(pTIHeader->typekind) {
4654 case TKIND_ENUM:
4655 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4656 pTIHeader, pTITail);
4657 break;
4659 case TKIND_RECORD:
4660 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4661 pTIHeader, pTITail);
4662 break;
4664 case TKIND_INTERFACE:
4665 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4666 pTIHeader, pTITail);
4667 break;
4669 case TKIND_COCLASS:
4670 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4671 pTIHeader, pTITail);
4672 break;
4674 case TKIND_ALIAS:
4675 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4676 pTIHeader, pTITail);
4677 break;
4679 case TKIND_DISPATCH:
4680 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4681 pTIHeader, pTITail);
4682 break;
4684 case TKIND_MODULE:
4685 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4686 pTIHeader, pTITail);
4687 break;
4689 default:
4690 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4691 break;
4695 /* could get cFuncs, cVars and cImplTypes from here
4696 but we've already set those */
4697 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4698 X(06);
4699 X(16);
4700 X(18);
4701 X(1a);
4702 X(1e);
4703 X(24);
4704 X(26);
4705 X(2a);
4706 X(2c);
4707 X(2e);
4708 X(30);
4709 X(32);
4710 X(34);
4711 #undef X
4712 ++ppTypeInfoImpl;
4713 pBlk = (char*)pBlk + pBlkEntry[order].len;
4716 if(i != pTypeLibImpl->TypeInfoCount) {
4717 FIXME("Somehow processed %d TypeInfos\n", i);
4718 heap_free(pOtherTypeInfoBlks);
4719 return NULL;
4722 heap_free(pOtherTypeInfoBlks);
4723 return &pTypeLibImpl->ITypeLib2_iface;
4726 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4728 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4730 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4732 if(IsEqualIID(riid, &IID_IUnknown) ||
4733 IsEqualIID(riid,&IID_ITypeLib)||
4734 IsEqualIID(riid,&IID_ITypeLib2))
4736 *ppv = &This->ITypeLib2_iface;
4738 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4739 IsEqualIID(riid, &IID_ICreateTypeLib2))
4741 *ppv = &This->ICreateTypeLib2_iface;
4743 else
4745 *ppv = NULL;
4746 TRACE("-- Interface: E_NOINTERFACE\n");
4747 return E_NOINTERFACE;
4750 IUnknown_AddRef((IUnknown*)*ppv);
4751 return S_OK;
4754 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4756 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4757 ULONG ref = InterlockedIncrement(&This->ref);
4759 TRACE("(%p) ref=%u\n", This, ref);
4761 return ref;
4764 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4766 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4767 ULONG ref = InterlockedDecrement(&This->ref);
4769 TRACE("(%p) ref=%u\n",This, ref);
4771 if (!ref)
4773 TLBImpLib *pImpLib, *pImpLibNext;
4774 TLBRefType *ref_type;
4775 TLBString *tlbstr, *tlbstr_next;
4776 TLBGuid *tlbguid, *tlbguid_next;
4777 void *cursor2;
4778 int i;
4780 /* remove cache entry */
4781 if(This->path)
4783 TRACE("removing from cache list\n");
4784 EnterCriticalSection(&cache_section);
4785 if(This->entry.next)
4786 list_remove(&This->entry);
4787 LeaveCriticalSection(&cache_section);
4788 heap_free(This->path);
4790 TRACE(" destroying ITypeLib(%p)\n",This);
4792 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4793 list_remove(&tlbstr->entry);
4794 SysFreeString(tlbstr->str);
4795 heap_free(tlbstr);
4798 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4799 list_remove(&tlbstr->entry);
4800 SysFreeString(tlbstr->str);
4801 heap_free(tlbstr);
4804 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4805 list_remove(&tlbguid->entry);
4806 heap_free(tlbguid);
4809 TLB_FreeCustData(&This->custdata_list);
4811 for (i = 0; i < This->ctTypeDesc; i++)
4812 if (This->pTypeDesc[i].vt == VT_CARRAY)
4813 heap_free(This->pTypeDesc[i].u.lpadesc);
4815 heap_free(This->pTypeDesc);
4817 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4819 if (pImpLib->pImpTypeLib)
4820 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4821 SysFreeString(pImpLib->name);
4823 list_remove(&pImpLib->entry);
4824 heap_free(pImpLib);
4827 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4829 list_remove(&ref_type->entry);
4830 heap_free(ref_type);
4833 for (i = 0; i < This->TypeInfoCount; ++i){
4834 heap_free(This->typeinfos[i]->tdescAlias);
4835 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4837 heap_free(This->typeinfos);
4838 heap_free(This);
4839 return 0;
4842 return ref;
4845 /* ITypeLib::GetTypeInfoCount
4847 * Returns the number of type descriptions in the type library
4849 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4851 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4852 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4853 return This->TypeInfoCount;
4856 /* ITypeLib::GetTypeInfo
4858 * retrieves the specified type description in the library.
4860 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4861 ITypeLib2 *iface,
4862 UINT index,
4863 ITypeInfo **ppTInfo)
4865 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4867 TRACE("%p %u %p\n", This, index, ppTInfo);
4869 if(!ppTInfo)
4870 return E_INVALIDARG;
4872 if(index >= This->TypeInfoCount)
4873 return TYPE_E_ELEMENTNOTFOUND;
4875 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4876 ITypeInfo_AddRef(*ppTInfo);
4878 return S_OK;
4882 /* ITypeLibs::GetTypeInfoType
4884 * Retrieves the type of a type description.
4886 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4887 ITypeLib2 *iface,
4888 UINT index,
4889 TYPEKIND *pTKind)
4891 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4893 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4895 if(!pTKind)
4896 return E_INVALIDARG;
4898 if(index >= This->TypeInfoCount)
4899 return TYPE_E_ELEMENTNOTFOUND;
4901 *pTKind = This->typeinfos[index]->typekind;
4903 return S_OK;
4906 /* ITypeLib::GetTypeInfoOfGuid
4908 * Retrieves the type description that corresponds to the specified GUID.
4911 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4912 ITypeLib2 *iface,
4913 REFGUID guid,
4914 ITypeInfo **ppTInfo)
4916 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4917 int i;
4919 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4921 for(i = 0; i < This->TypeInfoCount; ++i){
4922 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4923 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4924 ITypeInfo_AddRef(*ppTInfo);
4925 return S_OK;
4929 return TYPE_E_ELEMENTNOTFOUND;
4932 /* ITypeLib::GetLibAttr
4934 * Retrieves the structure that contains the library's attributes.
4937 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4938 ITypeLib2 *iface,
4939 LPTLIBATTR *attr)
4941 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4943 TRACE("(%p, %p)\n", This, attr);
4945 if (!attr) return E_INVALIDARG;
4947 *attr = heap_alloc(sizeof(**attr));
4948 if (!*attr) return E_OUTOFMEMORY;
4950 (*attr)->guid = *TLB_get_guid_null(This->guid);
4951 (*attr)->lcid = This->set_lcid;
4952 (*attr)->syskind = This->syskind;
4953 (*attr)->wMajorVerNum = This->ver_major;
4954 (*attr)->wMinorVerNum = This->ver_minor;
4955 (*attr)->wLibFlags = This->libflags;
4957 return S_OK;
4960 /* ITypeLib::GetTypeComp
4962 * Enables a client compiler to bind to a library's types, variables,
4963 * constants, and global functions.
4966 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4967 ITypeLib2 *iface,
4968 ITypeComp **ppTComp)
4970 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4972 TRACE("(%p)->(%p)\n",This,ppTComp);
4973 *ppTComp = &This->ITypeComp_iface;
4974 ITypeComp_AddRef(*ppTComp);
4976 return S_OK;
4979 /* ITypeLib::GetDocumentation
4981 * Retrieves the library's documentation string, the complete Help file name
4982 * and path, and the context identifier for the library Help topic in the Help
4983 * file.
4985 * On a successful return all non-null BSTR pointers will have been set,
4986 * possibly to NULL.
4988 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4989 ITypeLib2 *iface,
4990 INT index,
4991 BSTR *pBstrName,
4992 BSTR *pBstrDocString,
4993 DWORD *pdwHelpContext,
4994 BSTR *pBstrHelpFile)
4996 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4997 HRESULT result = E_INVALIDARG;
4998 ITypeInfo *pTInfo;
5000 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
5001 This, index,
5002 pBstrName, pBstrDocString,
5003 pdwHelpContext, pBstrHelpFile);
5005 if(index<0)
5007 /* documentation for the typelib */
5008 if(pBstrName)
5010 if (This->Name)
5012 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
5013 goto memerr1;
5015 else
5016 *pBstrName = NULL;
5018 if(pBstrDocString)
5020 if (This->DocString)
5022 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
5023 goto memerr2;
5025 else
5026 *pBstrDocString = NULL;
5028 if(pdwHelpContext)
5030 *pdwHelpContext = This->dwHelpContext;
5032 if(pBstrHelpFile)
5034 if (This->HelpFile)
5036 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5037 goto memerr3;
5039 else
5040 *pBstrHelpFile = NULL;
5043 result = S_OK;
5045 else
5047 /* for a typeinfo */
5048 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5050 if(SUCCEEDED(result))
5052 result = ITypeInfo_GetDocumentation(pTInfo,
5053 MEMBERID_NIL,
5054 pBstrName,
5055 pBstrDocString,
5056 pdwHelpContext, pBstrHelpFile);
5058 ITypeInfo_Release(pTInfo);
5061 return result;
5062 memerr3:
5063 if (pBstrDocString) SysFreeString (*pBstrDocString);
5064 memerr2:
5065 if (pBstrName) SysFreeString (*pBstrName);
5066 memerr1:
5067 return STG_E_INSUFFICIENTMEMORY;
5070 /* ITypeLib::IsName
5072 * Indicates whether a passed-in string contains the name of a type or member
5073 * described in the library.
5076 static HRESULT WINAPI ITypeLib2_fnIsName(
5077 ITypeLib2 *iface,
5078 LPOLESTR szNameBuf,
5079 ULONG lHashVal,
5080 BOOL *pfName)
5082 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5083 int tic;
5084 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5086 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5087 pfName);
5089 *pfName=TRUE;
5090 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5091 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5092 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5093 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5094 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5095 int pc;
5096 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5097 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5098 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5099 goto ITypeLib2_fnIsName_exit;
5102 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
5103 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5104 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5108 *pfName=FALSE;
5110 ITypeLib2_fnIsName_exit:
5111 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5112 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5114 return S_OK;
5117 /* ITypeLib::FindName
5119 * Finds occurrences of a type description in a type library. This may be used
5120 * to quickly verify that a name exists in a type library.
5123 static HRESULT WINAPI ITypeLib2_fnFindName(
5124 ITypeLib2 *iface,
5125 LPOLESTR name,
5126 ULONG hash,
5127 ITypeInfo **ppTInfo,
5128 MEMBERID *memid,
5129 UINT16 *found)
5131 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5132 int tic;
5133 UINT count = 0;
5134 UINT len;
5136 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5138 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5139 return E_INVALIDARG;
5141 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5142 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5143 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5144 TLBVarDesc *var;
5145 UINT fdc;
5147 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5148 memid[count] = MEMBERID_NIL;
5149 goto ITypeLib2_fnFindName_exit;
5152 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5153 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5155 if(!TLB_str_memcmp(name, func->Name, len)) {
5156 memid[count] = func->funcdesc.memid;
5157 goto ITypeLib2_fnFindName_exit;
5161 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
5162 if (var) {
5163 memid[count] = var->vardesc.memid;
5164 goto ITypeLib2_fnFindName_exit;
5167 continue;
5168 ITypeLib2_fnFindName_exit:
5169 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5170 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5171 count++;
5173 TRACE("found %d typeinfos\n", count);
5175 *found = count;
5177 return S_OK;
5180 /* ITypeLib::ReleaseTLibAttr
5182 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5185 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5186 ITypeLib2 *iface,
5187 TLIBATTR *pTLibAttr)
5189 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5190 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5191 heap_free(pTLibAttr);
5194 /* ITypeLib2::GetCustData
5196 * gets the custom data
5198 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5199 ITypeLib2 * iface,
5200 REFGUID guid,
5201 VARIANT *pVarVal)
5203 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5204 TLBCustData *pCData;
5206 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5208 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5209 if(!pCData)
5210 return TYPE_E_ELEMENTNOTFOUND;
5212 VariantInit(pVarVal);
5213 VariantCopy(pVarVal, &pCData->data);
5215 return S_OK;
5218 /* ITypeLib2::GetLibStatistics
5220 * Returns statistics about a type library that are required for efficient
5221 * sizing of hash tables.
5224 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5225 ITypeLib2 * iface,
5226 ULONG *pcUniqueNames,
5227 ULONG *pcchUniqueNames)
5229 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5231 FIXME("(%p): stub!\n", This);
5233 if(pcUniqueNames) *pcUniqueNames=1;
5234 if(pcchUniqueNames) *pcchUniqueNames=1;
5235 return S_OK;
5238 /* ITypeLib2::GetDocumentation2
5240 * Retrieves the library's documentation string, the complete Help file name
5241 * and path, the localization context to use, and the context ID for the
5242 * library Help topic in the Help file.
5245 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5246 ITypeLib2 * iface,
5247 INT index,
5248 LCID lcid,
5249 BSTR *pbstrHelpString,
5250 DWORD *pdwHelpStringContext,
5251 BSTR *pbstrHelpStringDll)
5253 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5254 HRESULT result;
5255 ITypeInfo *pTInfo;
5257 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5259 /* the help string should be obtained from the helpstringdll,
5260 * using the _DLLGetDocumentation function, based on the supplied
5261 * lcid. Nice to do sometime...
5263 if(index<0)
5265 /* documentation for the typelib */
5266 if(pbstrHelpString)
5267 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5268 if(pdwHelpStringContext)
5269 *pdwHelpStringContext=This->dwHelpContext;
5270 if(pbstrHelpStringDll)
5271 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5273 result = S_OK;
5275 else
5277 /* for a typeinfo */
5278 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5280 if(SUCCEEDED(result))
5282 ITypeInfo2 * pTInfo2;
5283 result = ITypeInfo_QueryInterface(pTInfo,
5284 &IID_ITypeInfo2,
5285 (LPVOID*) &pTInfo2);
5287 if(SUCCEEDED(result))
5289 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5290 MEMBERID_NIL,
5291 lcid,
5292 pbstrHelpString,
5293 pdwHelpStringContext,
5294 pbstrHelpStringDll);
5296 ITypeInfo2_Release(pTInfo2);
5299 ITypeInfo_Release(pTInfo);
5302 return result;
5305 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5307 TLBCustData *pCData;
5308 unsigned int ct;
5309 CUSTDATAITEM *cdi;
5311 ct = list_count(custdata_list);
5313 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5314 if(!pCustData->prgCustData)
5315 return E_OUTOFMEMORY;
5317 pCustData->cCustData = ct;
5319 cdi = pCustData->prgCustData;
5320 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5321 cdi->guid = *TLB_get_guid_null(pCData->guid);
5322 VariantCopy(&cdi->varValue, &pCData->data);
5323 ++cdi;
5326 return S_OK;
5330 /* ITypeLib2::GetAllCustData
5332 * Gets all custom data items for the library.
5335 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5336 ITypeLib2 * iface,
5337 CUSTDATA *pCustData)
5339 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5340 TRACE("(%p)->(%p)\n", This, pCustData);
5341 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5344 static const ITypeLib2Vtbl tlbvt = {
5345 ITypeLib2_fnQueryInterface,
5346 ITypeLib2_fnAddRef,
5347 ITypeLib2_fnRelease,
5348 ITypeLib2_fnGetTypeInfoCount,
5349 ITypeLib2_fnGetTypeInfo,
5350 ITypeLib2_fnGetTypeInfoType,
5351 ITypeLib2_fnGetTypeInfoOfGuid,
5352 ITypeLib2_fnGetLibAttr,
5353 ITypeLib2_fnGetTypeComp,
5354 ITypeLib2_fnGetDocumentation,
5355 ITypeLib2_fnIsName,
5356 ITypeLib2_fnFindName,
5357 ITypeLib2_fnReleaseTLibAttr,
5359 ITypeLib2_fnGetCustData,
5360 ITypeLib2_fnGetLibStatistics,
5361 ITypeLib2_fnGetDocumentation2,
5362 ITypeLib2_fnGetAllCustData
5366 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5368 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5370 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5373 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5375 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5377 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5380 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5382 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5384 return ITypeLib2_Release(&This->ITypeLib2_iface);
5387 static HRESULT WINAPI ITypeLibComp_fnBind(
5388 ITypeComp * iface,
5389 OLECHAR * szName,
5390 ULONG lHash,
5391 WORD wFlags,
5392 ITypeInfo ** ppTInfo,
5393 DESCKIND * pDescKind,
5394 BINDPTR * pBindPtr)
5396 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5397 BOOL typemismatch = FALSE;
5398 int i;
5400 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5402 *pDescKind = DESCKIND_NONE;
5403 pBindPtr->lptcomp = NULL;
5404 *ppTInfo = NULL;
5406 for(i = 0; i < This->TypeInfoCount; ++i){
5407 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5408 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5410 /* FIXME: check wFlags here? */
5411 /* FIXME: we should use a hash table to look this info up using lHash
5412 * instead of an O(n) search */
5413 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5414 (pTypeInfo->typekind == TKIND_MODULE))
5416 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5418 *pDescKind = DESCKIND_TYPECOMP;
5419 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5420 ITypeComp_AddRef(pBindPtr->lptcomp);
5421 TRACE("module or enum: %s\n", debugstr_w(szName));
5422 return S_OK;
5426 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5427 (pTypeInfo->typekind == TKIND_ENUM))
5429 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5430 HRESULT hr;
5432 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5433 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5435 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5436 return S_OK;
5438 else if (hr == TYPE_E_TYPEMISMATCH)
5439 typemismatch = TRUE;
5442 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5443 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5445 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5446 HRESULT hr;
5447 ITypeInfo *subtypeinfo;
5448 BINDPTR subbindptr;
5449 DESCKIND subdesckind;
5451 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5452 &subtypeinfo, &subdesckind, &subbindptr);
5453 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5455 TYPEDESC tdesc_appobject;
5456 const VARDESC vardesc_appobject =
5458 -2, /* memid */
5459 NULL, /* lpstrSchema */
5461 0 /* oInst */
5464 /* ELEMDESC */
5466 /* TYPEDESC */
5468 &tdesc_appobject
5470 VT_PTR
5473 0, /* wVarFlags */
5474 VAR_STATIC /* varkind */
5477 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5478 tdesc_appobject.vt = VT_USERDEFINED;
5480 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5482 /* cleanup things filled in by Bind call so we can put our
5483 * application object data in there instead */
5484 switch (subdesckind)
5486 case DESCKIND_FUNCDESC:
5487 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5488 break;
5489 case DESCKIND_VARDESC:
5490 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5491 break;
5492 default:
5493 break;
5495 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5497 if (pTypeInfo->hreftype == -1)
5498 FIXME("no hreftype for interface %p\n", pTypeInfo);
5500 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5501 if (FAILED(hr))
5502 return hr;
5504 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5505 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5506 ITypeInfo_AddRef(*ppTInfo);
5507 return S_OK;
5509 else if (hr == TYPE_E_TYPEMISMATCH)
5510 typemismatch = TRUE;
5514 if (typemismatch)
5516 TRACE("type mismatch %s\n", debugstr_w(szName));
5517 return TYPE_E_TYPEMISMATCH;
5519 else
5521 TRACE("name not found %s\n", debugstr_w(szName));
5522 return S_OK;
5526 static HRESULT WINAPI ITypeLibComp_fnBindType(
5527 ITypeComp * iface,
5528 OLECHAR * szName,
5529 ULONG lHash,
5530 ITypeInfo ** ppTInfo,
5531 ITypeComp ** ppTComp)
5533 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5534 ITypeInfoImpl *info;
5536 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5538 if(!szName || !ppTInfo || !ppTComp)
5539 return E_INVALIDARG;
5541 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5542 if(!info){
5543 *ppTInfo = NULL;
5544 *ppTComp = NULL;
5545 return S_OK;
5548 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5549 ITypeInfo_AddRef(*ppTInfo);
5550 *ppTComp = &info->ITypeComp_iface;
5551 ITypeComp_AddRef(*ppTComp);
5553 return S_OK;
5556 static const ITypeCompVtbl tlbtcvt =
5559 ITypeLibComp_fnQueryInterface,
5560 ITypeLibComp_fnAddRef,
5561 ITypeLibComp_fnRelease,
5563 ITypeLibComp_fnBind,
5564 ITypeLibComp_fnBindType
5567 /*================== ITypeInfo(2) Methods ===================================*/
5568 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5570 ITypeInfoImpl *pTypeInfoImpl;
5572 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5573 if (pTypeInfoImpl)
5575 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5576 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5577 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5578 pTypeInfoImpl->ref = 0;
5579 pTypeInfoImpl->hreftype = -1;
5580 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5581 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5582 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5583 list_init(pTypeInfoImpl->pcustdata_list);
5585 TRACE("(%p)\n", pTypeInfoImpl);
5586 return pTypeInfoImpl;
5589 /* ITypeInfo::QueryInterface
5591 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5592 ITypeInfo2 *iface,
5593 REFIID riid,
5594 VOID **ppvObject)
5596 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5598 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5600 *ppvObject=NULL;
5601 if(IsEqualIID(riid, &IID_IUnknown) ||
5602 IsEqualIID(riid,&IID_ITypeInfo)||
5603 IsEqualIID(riid,&IID_ITypeInfo2))
5604 *ppvObject = This;
5605 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5606 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5607 *ppvObject = &This->ICreateTypeInfo2_iface;
5609 if(*ppvObject){
5610 ITypeInfo2_AddRef(iface);
5611 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5612 return S_OK;
5614 TRACE("-- Interface: E_NOINTERFACE\n");
5615 return E_NOINTERFACE;
5618 /* ITypeInfo::AddRef
5620 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5622 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5623 ULONG ref = InterlockedIncrement(&This->ref);
5625 TRACE("(%p)->ref is %u\n",This, ref);
5627 if (ref == 1 /* incremented from 0 */)
5628 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5630 return ref;
5633 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5635 UINT i;
5637 TRACE("destroying ITypeInfo(%p)\n",This);
5639 for (i = 0; i < This->cFuncs; ++i)
5641 int j;
5642 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5643 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5645 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5646 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5647 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5648 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5650 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5651 heap_free(pFInfo->pParamDesc);
5652 TLB_FreeCustData(&pFInfo->custdata_list);
5654 heap_free(This->funcdescs);
5656 for(i = 0; i < This->cVars; ++i)
5658 TLBVarDesc *pVInfo = &This->vardescs[i];
5659 if (pVInfo->vardesc_create) {
5660 TLB_FreeVarDesc(pVInfo->vardesc_create);
5661 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5662 VariantClear(pVInfo->vardesc.u.lpvarValue);
5663 heap_free(pVInfo->vardesc.u.lpvarValue);
5665 TLB_FreeCustData(&pVInfo->custdata_list);
5667 heap_free(This->vardescs);
5669 if(This->impltypes){
5670 for (i = 0; i < This->cImplTypes; ++i){
5671 TLBImplType *pImpl = &This->impltypes[i];
5672 TLB_FreeCustData(&pImpl->custdata_list);
5674 heap_free(This->impltypes);
5677 TLB_FreeCustData(&This->custdata_list);
5679 heap_free(This);
5682 /* ITypeInfo::Release
5684 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5686 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5687 ULONG ref = InterlockedDecrement(&This->ref);
5689 TRACE("(%p)->(%u)\n",This, ref);
5691 if (!ref)
5693 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5694 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5695 if (not_attached_to_typelib)
5696 heap_free(This);
5697 /* otherwise This will be freed when typelib is freed */
5700 return ref;
5703 /* ITypeInfo::GetTypeAttr
5705 * Retrieves a TYPEATTR structure that contains the attributes of the type
5706 * description.
5709 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5710 LPTYPEATTR *ppTypeAttr)
5712 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5713 SIZE_T size;
5715 TRACE("(%p)\n",This);
5717 size = sizeof(**ppTypeAttr);
5718 if (This->typekind == TKIND_ALIAS && This->tdescAlias)
5719 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5721 *ppTypeAttr = heap_alloc(size);
5722 if (!*ppTypeAttr)
5723 return E_OUTOFMEMORY;
5725 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5726 (*ppTypeAttr)->lcid = This->lcid;
5727 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5728 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5729 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5730 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5731 (*ppTypeAttr)->typekind = This->typekind;
5732 (*ppTypeAttr)->cFuncs = This->cFuncs;
5733 (*ppTypeAttr)->cVars = This->cVars;
5734 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5735 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5736 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5737 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5738 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5739 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5740 (*ppTypeAttr)->idldescType = This->idldescType;
5742 if (This->tdescAlias)
5743 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5744 This->tdescAlias, *ppTypeAttr + 1);
5745 else{
5746 (*ppTypeAttr)->tdescAlias.vt = VT_EMPTY;
5747 (*ppTypeAttr)->tdescAlias.u.lptdesc = NULL;
5750 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5751 /* This should include all the inherited funcs */
5752 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5753 /* This is always the size of IDispatch's vtbl */
5754 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5755 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5757 return S_OK;
5760 /* ITypeInfo::GetTypeComp
5762 * Retrieves the ITypeComp interface for the type description, which enables a
5763 * client compiler to bind to the type description's members.
5766 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5767 ITypeComp * *ppTComp)
5769 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5771 TRACE("(%p)->(%p)\n", This, ppTComp);
5773 *ppTComp = &This->ITypeComp_iface;
5774 ITypeComp_AddRef(*ppTComp);
5775 return S_OK;
5778 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5780 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5781 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5782 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5783 return size;
5786 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5788 *dest = *src;
5789 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5790 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5792 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5793 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5794 *buffer += sizeof(PARAMDESCEX);
5795 *pparamdescex_dest = *pparamdescex_src;
5796 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5797 VariantInit(&pparamdescex_dest->varDefaultValue);
5798 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5799 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5801 else
5802 dest->u.paramdesc.pparamdescex = NULL;
5803 return S_OK;
5806 static HRESULT TLB_SanitizeBSTR(BSTR str)
5808 UINT len = SysStringLen(str), i;
5809 for (i = 0; i < len; ++i)
5810 if (str[i] > 0x7f)
5811 str[i] = '?';
5812 return S_OK;
5815 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5817 if (V_VT(var) == VT_INT)
5818 return VariantChangeType(var, var, 0, VT_I4);
5819 else if (V_VT(var) == VT_UINT)
5820 return VariantChangeType(var, var, 0, VT_UI4);
5821 else if (V_VT(var) == VT_BSTR)
5822 return TLB_SanitizeBSTR(V_BSTR(var));
5824 return S_OK;
5827 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5829 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5830 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5833 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5835 FUNCDESC *dest;
5836 char *buffer;
5837 SIZE_T size = sizeof(*src);
5838 SHORT i;
5839 HRESULT hr;
5841 size += sizeof(*src->lprgscode) * src->cScodes;
5842 size += TLB_SizeElemDesc(&src->elemdescFunc);
5843 for (i = 0; i < src->cParams; i++)
5845 size += sizeof(ELEMDESC);
5846 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5849 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5850 if (!dest) return E_OUTOFMEMORY;
5852 *dest = *src;
5853 if (dispinterface) /* overwrite funckind */
5854 dest->funckind = FUNC_DISPATCH;
5855 buffer = (char *)(dest + 1);
5857 dest->oVft = dest->oVft & 0xFFFC;
5859 if (dest->cScodes) {
5860 dest->lprgscode = (SCODE *)buffer;
5861 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5862 buffer += sizeof(*src->lprgscode) * src->cScodes;
5863 } else
5864 dest->lprgscode = NULL;
5866 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5867 if (FAILED(hr))
5869 SysFreeString((BSTR)dest);
5870 return hr;
5873 if (dest->cParams) {
5874 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5875 buffer += sizeof(ELEMDESC) * src->cParams;
5876 for (i = 0; i < src->cParams; i++)
5878 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5879 if (FAILED(hr))
5880 break;
5882 if (FAILED(hr))
5884 /* undo the above actions */
5885 for (i = i - 1; i >= 0; i--)
5886 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5887 TLB_FreeElemDesc(&dest->elemdescFunc);
5888 SysFreeString((BSTR)dest);
5889 return hr;
5891 } else
5892 dest->lprgelemdescParam = NULL;
5894 /* special treatment for dispinterfaces: this makes functions appear
5895 * to return their [retval] value when it is really returning an
5896 * HRESULT */
5897 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5899 if (dest->cParams &&
5900 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5902 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5903 if (elemdesc->tdesc.vt != VT_PTR)
5905 ERR("elemdesc should have started with VT_PTR instead of:\n");
5906 if (ERR_ON(ole))
5907 dump_ELEMDESC(elemdesc);
5908 return E_UNEXPECTED;
5911 /* copy last parameter to the return value. we are using a flat
5912 * buffer so there is no danger of leaking memory in
5913 * elemdescFunc */
5914 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5916 /* remove the last parameter */
5917 dest->cParams--;
5919 else
5920 /* otherwise this function is made to appear to have no return
5921 * value */
5922 dest->elemdescFunc.tdesc.vt = VT_VOID;
5926 *dest_ptr = dest;
5927 return S_OK;
5930 static void TLB_FreeVarDesc(VARDESC *var_desc)
5932 TLB_FreeElemDesc(&var_desc->elemdescVar);
5933 if (var_desc->varkind == VAR_CONST)
5934 VariantClear(var_desc->u.lpvarValue);
5935 SysFreeString((BSTR)var_desc);
5938 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5940 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5942 if (index >= This->cFuncs)
5943 return TYPE_E_ELEMENTNOTFOUND;
5945 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5946 return S_OK;
5949 /* internal function to make the inherited interfaces' methods appear
5950 * part of the interface */
5951 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5952 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5954 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5955 HRESULT hr;
5956 UINT implemented_funcs = 0;
5958 if (funcs)
5959 *funcs = 0;
5960 else
5961 *hrefoffset = DISPATCH_HREF_OFFSET;
5963 if(This->impltypes)
5965 ITypeInfo *pSubTypeInfo;
5966 UINT sub_funcs;
5968 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5969 if (FAILED(hr))
5970 return hr;
5972 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5973 index,
5974 ppFuncDesc,
5975 &sub_funcs, hrefoffset);
5976 implemented_funcs += sub_funcs;
5977 ITypeInfo_Release(pSubTypeInfo);
5978 if (SUCCEEDED(hr))
5979 return hr;
5980 *hrefoffset += DISPATCH_HREF_OFFSET;
5983 if (funcs)
5984 *funcs = implemented_funcs + This->cFuncs;
5985 else
5986 *hrefoffset = 0;
5988 if (index < implemented_funcs)
5989 return E_INVALIDARG;
5990 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5991 ppFuncDesc);
5994 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5996 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5997 while (TRUE)
5999 switch (pTypeDesc->vt)
6001 case VT_USERDEFINED:
6002 pTypeDesc->u.hreftype += hrefoffset;
6003 return;
6004 case VT_PTR:
6005 case VT_SAFEARRAY:
6006 pTypeDesc = pTypeDesc->u.lptdesc;
6007 break;
6008 case VT_CARRAY:
6009 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
6010 break;
6011 default:
6012 return;
6017 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
6019 SHORT i;
6020 for (i = 0; i < pFuncDesc->cParams; i++)
6021 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
6022 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
6025 /* ITypeInfo::GetFuncDesc
6027 * Retrieves the FUNCDESC structure that contains information about a
6028 * specified function.
6031 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
6032 LPFUNCDESC *ppFuncDesc)
6034 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6035 const FUNCDESC *internal_funcdesc;
6036 HRESULT hr;
6037 UINT hrefoffset = 0;
6039 TRACE("(%p) index %d\n", This, index);
6041 if (!ppFuncDesc)
6042 return E_INVALIDARG;
6044 if (This->needs_layout)
6045 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6047 if (This->typekind == TKIND_DISPATCH)
6048 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6049 &internal_funcdesc, NULL,
6050 &hrefoffset);
6051 else
6052 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6053 &internal_funcdesc);
6054 if (FAILED(hr))
6056 WARN("description for function %d not found\n", index);
6057 return hr;
6060 hr = TLB_AllocAndInitFuncDesc(
6061 internal_funcdesc,
6062 ppFuncDesc,
6063 This->typekind == TKIND_DISPATCH);
6065 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
6066 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6068 TRACE("-- 0x%08x\n", hr);
6069 return hr;
6072 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6074 VARDESC *dest;
6075 char *buffer;
6076 SIZE_T size = sizeof(*src);
6077 HRESULT hr;
6079 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6080 if (src->varkind == VAR_CONST)
6081 size += sizeof(VARIANT);
6082 size += TLB_SizeElemDesc(&src->elemdescVar);
6084 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6085 if (!dest) return E_OUTOFMEMORY;
6087 *dest = *src;
6088 buffer = (char *)(dest + 1);
6089 if (src->lpstrSchema)
6091 int len;
6092 dest->lpstrSchema = (LPOLESTR)buffer;
6093 len = strlenW(src->lpstrSchema);
6094 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6095 buffer += (len + 1) * sizeof(WCHAR);
6098 if (src->varkind == VAR_CONST)
6100 HRESULT hr;
6102 dest->u.lpvarValue = (VARIANT *)buffer;
6103 *dest->u.lpvarValue = *src->u.lpvarValue;
6104 buffer += sizeof(VARIANT);
6105 VariantInit(dest->u.lpvarValue);
6106 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6107 if (FAILED(hr))
6109 SysFreeString((BSTR)dest);
6110 return hr;
6113 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6114 if (FAILED(hr))
6116 if (src->varkind == VAR_CONST)
6117 VariantClear(dest->u.lpvarValue);
6118 SysFreeString((BSTR)dest);
6119 return hr;
6121 *dest_ptr = dest;
6122 return S_OK;
6125 /* ITypeInfo::GetVarDesc
6127 * Retrieves a VARDESC structure that describes the specified variable.
6130 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6131 LPVARDESC *ppVarDesc)
6133 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6134 const TLBVarDesc *pVDesc = &This->vardescs[index];
6136 TRACE("(%p) index %d\n", This, index);
6138 if(index >= This->cVars)
6139 return TYPE_E_ELEMENTNOTFOUND;
6141 if (This->needs_layout)
6142 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6144 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6147 /* ITypeInfo_GetNames
6149 * Retrieves the variable with the specified member ID (or the name of the
6150 * property or method and its parameters) that correspond to the specified
6151 * function ID.
6153 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6154 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6156 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6157 const TLBFuncDesc *pFDesc;
6158 const TLBVarDesc *pVDesc;
6159 int i;
6160 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6162 if(!rgBstrNames)
6163 return E_INVALIDARG;
6165 *pcNames = 0;
6167 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
6168 if(pFDesc)
6170 if(!cMaxNames || !pFDesc->Name)
6171 return S_OK;
6173 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6174 ++(*pcNames);
6176 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6177 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6178 return S_OK;
6179 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6180 ++(*pcNames);
6182 return S_OK;
6185 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
6186 if(pVDesc)
6188 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6189 *pcNames=1;
6191 else
6193 if(This->impltypes &&
6194 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
6195 /* recursive search */
6196 ITypeInfo *pTInfo;
6197 HRESULT result;
6198 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6199 if(SUCCEEDED(result))
6201 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6202 ITypeInfo_Release(pTInfo);
6203 return result;
6205 WARN("Could not search inherited interface!\n");
6207 else
6209 WARN("no names found\n");
6211 *pcNames=0;
6212 return TYPE_E_ELEMENTNOTFOUND;
6214 return S_OK;
6218 /* ITypeInfo::GetRefTypeOfImplType
6220 * If a type description describes a COM class, it retrieves the type
6221 * description of the implemented interface types. For an interface,
6222 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6223 * if any exist.
6226 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6227 ITypeInfo2 *iface,
6228 UINT index,
6229 HREFTYPE *pRefType)
6231 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6232 HRESULT hr = S_OK;
6234 TRACE("(%p) index %d\n", This, index);
6235 if (TRACE_ON(ole)) dump_TypeInfo(This);
6237 if(index==(UINT)-1)
6239 /* only valid on dual interfaces;
6240 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6243 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6245 *pRefType = -2;
6247 else
6249 hr = TYPE_E_ELEMENTNOTFOUND;
6252 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6254 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6255 *pRefType = This->pTypeLib->dispatch_href;
6257 else
6259 if(index >= This->cImplTypes)
6260 hr = TYPE_E_ELEMENTNOTFOUND;
6261 else{
6262 *pRefType = This->impltypes[index].hRef;
6263 if(This->typekind == TKIND_INTERFACE)
6264 *pRefType |= 0x2;
6268 if(TRACE_ON(ole))
6270 if(SUCCEEDED(hr))
6271 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6272 else
6273 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6276 return hr;
6279 /* ITypeInfo::GetImplTypeFlags
6281 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6282 * or base interface in a type description.
6284 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6285 UINT index, INT *pImplTypeFlags)
6287 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6289 TRACE("(%p) index %d\n", This, index);
6291 if(!pImplTypeFlags)
6292 return E_INVALIDARG;
6294 if(This->typekind == TKIND_DISPATCH && index == 0){
6295 *pImplTypeFlags = 0;
6296 return S_OK;
6299 if(index >= This->cImplTypes)
6300 return TYPE_E_ELEMENTNOTFOUND;
6302 *pImplTypeFlags = This->impltypes[index].implflags;
6304 return S_OK;
6307 /* GetIDsOfNames
6308 * Maps between member names and member IDs, and parameter names and
6309 * parameter IDs.
6311 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6312 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6314 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6315 const TLBVarDesc *pVDesc;
6316 HRESULT ret=S_OK;
6317 UINT i, fdc;
6319 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6320 cNames);
6322 /* init out parameters in case of failure */
6323 for (i = 0; i < cNames; i++)
6324 pMemId[i] = MEMBERID_NIL;
6326 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6327 int j;
6328 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6329 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6330 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6331 for(i=1; i < cNames; i++){
6332 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6333 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6334 break;
6335 if( j<pFDesc->funcdesc.cParams)
6336 pMemId[i]=j;
6337 else
6338 ret=DISP_E_UNKNOWNNAME;
6340 TRACE("-- 0x%08x\n", ret);
6341 return ret;
6344 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6345 if(pVDesc){
6346 if(cNames)
6347 *pMemId = pVDesc->vardesc.memid;
6348 return ret;
6350 /* not found, see if it can be found in an inherited interface */
6351 if(This->impltypes) {
6352 /* recursive search */
6353 ITypeInfo *pTInfo;
6354 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6355 if(SUCCEEDED(ret)){
6356 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6357 ITypeInfo_Release(pTInfo);
6358 return ret;
6360 WARN("Could not search inherited interface!\n");
6361 } else
6362 WARN("no names found\n");
6363 return DISP_E_UNKNOWNNAME;
6367 #ifdef __i386__
6369 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6370 __ASM_GLOBAL_FUNC( call_method,
6371 "pushl %ebp\n\t"
6372 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6373 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6374 "movl %esp,%ebp\n\t"
6375 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6376 "pushl %esi\n\t"
6377 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6378 "pushl %edi\n\t"
6379 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6380 "movl 12(%ebp),%edx\n\t"
6381 "movl %esp,%edi\n\t"
6382 "shll $2,%edx\n\t"
6383 "jz 1f\n\t"
6384 "subl %edx,%edi\n\t"
6385 "andl $~15,%edi\n\t"
6386 "movl %edi,%esp\n\t"
6387 "movl 12(%ebp),%ecx\n\t"
6388 "movl 16(%ebp),%esi\n\t"
6389 "cld\n\t"
6390 "rep; movsl\n"
6391 "1:\tcall *8(%ebp)\n\t"
6392 "subl %esp,%edi\n\t"
6393 "movl 20(%ebp),%ecx\n\t"
6394 "movl %edi,(%ecx)\n\t"
6395 "leal -8(%ebp),%esp\n\t"
6396 "popl %edi\n\t"
6397 __ASM_CFI(".cfi_same_value %edi\n\t")
6398 "popl %esi\n\t"
6399 __ASM_CFI(".cfi_same_value %esi\n\t")
6400 "popl %ebp\n\t"
6401 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6402 __ASM_CFI(".cfi_same_value %ebp\n\t")
6403 "ret" )
6405 /* same function but returning floating point */
6406 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6408 /* ITypeInfo::Invoke
6410 * Invokes a method, or accesses a property of an object, that implements the
6411 * interface described by the type description.
6413 DWORD
6414 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6415 DWORD res;
6416 int stack_offset;
6418 if (TRACE_ON(ole)) {
6419 int i;
6420 TRACE("Calling %p(",func);
6421 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6422 if (nrargs > 30) TRACE("...");
6423 TRACE(")\n");
6426 switch (callconv) {
6427 case CC_STDCALL:
6428 case CC_CDECL:
6429 res = call_method( func, nrargs, args, &stack_offset );
6430 break;
6431 default:
6432 FIXME("unsupported calling convention %d\n",callconv);
6433 res = -1;
6434 break;
6436 TRACE("returns %08x\n",res);
6437 return res;
6440 #elif defined(__x86_64__)
6442 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6443 __ASM_GLOBAL_FUNC( call_method,
6444 "pushq %rbp\n\t"
6445 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6446 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6447 "movq %rsp,%rbp\n\t"
6448 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6449 "pushq %rsi\n\t"
6450 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6451 "pushq %rdi\n\t"
6452 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6453 "movq %rcx,%rax\n\t"
6454 "movq $4,%rcx\n\t"
6455 "cmp %rcx,%rdx\n\t"
6456 "cmovgq %rdx,%rcx\n\t"
6457 "leaq 0(,%rcx,8),%rdx\n\t"
6458 "subq %rdx,%rsp\n\t"
6459 "andq $~15,%rsp\n\t"
6460 "movq %rsp,%rdi\n\t"
6461 "movq %r8,%rsi\n\t"
6462 "rep; movsq\n\t"
6463 "movq 0(%rsp),%rcx\n\t"
6464 "movq 8(%rsp),%rdx\n\t"
6465 "movq 16(%rsp),%r8\n\t"
6466 "movq 24(%rsp),%r9\n\t"
6467 "movq %rcx,%xmm0\n\t"
6468 "movq %rdx,%xmm1\n\t"
6469 "movq %r8,%xmm2\n\t"
6470 "movq %r9,%xmm3\n\t"
6471 "callq *%rax\n\t"
6472 "leaq -16(%rbp),%rsp\n\t"
6473 "popq %rdi\n\t"
6474 __ASM_CFI(".cfi_same_value %rdi\n\t")
6475 "popq %rsi\n\t"
6476 __ASM_CFI(".cfi_same_value %rsi\n\t")
6477 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6478 "popq %rbp\n\t"
6479 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6480 __ASM_CFI(".cfi_same_value %rbp\n\t")
6481 "ret")
6483 /* same function but returning floating point */
6484 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6486 #endif /* __x86_64__ */
6488 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6490 HRESULT hr = S_OK;
6491 ITypeInfo *tinfo2 = NULL;
6492 TYPEATTR *tattr = NULL;
6494 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6495 if (hr)
6497 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6498 "hr = 0x%08x\n",
6499 tdesc->u.hreftype, hr);
6500 return hr;
6502 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6503 if (hr)
6505 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6506 ITypeInfo_Release(tinfo2);
6507 return hr;
6510 switch (tattr->typekind)
6512 case TKIND_ENUM:
6513 *vt |= VT_I4;
6514 break;
6516 case TKIND_ALIAS:
6517 tdesc = &tattr->tdescAlias;
6518 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6519 break;
6521 case TKIND_INTERFACE:
6522 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6523 *vt |= VT_DISPATCH;
6524 else
6525 *vt |= VT_UNKNOWN;
6526 break;
6528 case TKIND_DISPATCH:
6529 *vt |= VT_DISPATCH;
6530 break;
6532 case TKIND_COCLASS:
6533 *vt |= VT_DISPATCH;
6534 break;
6536 case TKIND_RECORD:
6537 FIXME("TKIND_RECORD unhandled.\n");
6538 hr = E_NOTIMPL;
6539 break;
6541 case TKIND_UNION:
6542 FIXME("TKIND_UNION unhandled.\n");
6543 hr = E_NOTIMPL;
6544 break;
6546 default:
6547 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6548 hr = E_NOTIMPL;
6549 break;
6551 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6552 ITypeInfo_Release(tinfo2);
6553 return hr;
6556 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6558 HRESULT hr = S_OK;
6560 /* enforce only one level of pointer indirection */
6561 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6563 tdesc = tdesc->u.lptdesc;
6565 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6566 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6567 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6568 if ((tdesc->vt == VT_USERDEFINED) ||
6569 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6571 VARTYPE vt_userdefined = 0;
6572 const TYPEDESC *tdesc_userdefined = tdesc;
6573 if (tdesc->vt == VT_PTR)
6575 vt_userdefined = VT_BYREF;
6576 tdesc_userdefined = tdesc->u.lptdesc;
6578 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6579 if ((hr == S_OK) &&
6580 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6581 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6583 *vt |= vt_userdefined;
6584 return S_OK;
6587 *vt = VT_BYREF;
6590 switch (tdesc->vt)
6592 case VT_HRESULT:
6593 *vt |= VT_ERROR;
6594 break;
6595 case VT_USERDEFINED:
6596 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6597 break;
6598 case VT_VOID:
6599 case VT_CARRAY:
6600 case VT_PTR:
6601 case VT_LPSTR:
6602 case VT_LPWSTR:
6603 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6604 hr = DISP_E_BADVARTYPE;
6605 break;
6606 case VT_SAFEARRAY:
6607 *vt |= VT_ARRAY;
6608 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6609 break;
6610 case VT_INT:
6611 *vt |= VT_I4;
6612 break;
6613 case VT_UINT:
6614 *vt |= VT_UI4;
6615 break;
6616 default:
6617 *vt |= tdesc->vt;
6618 break;
6620 return hr;
6623 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6625 ITypeInfo *tinfo2;
6626 TYPEATTR *tattr;
6627 HRESULT hres;
6629 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6630 if(FAILED(hres))
6631 return hres;
6633 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6634 if(FAILED(hres)) {
6635 ITypeInfo_Release(tinfo2);
6636 return hres;
6639 switch(tattr->typekind) {
6640 case TKIND_ALIAS:
6641 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6642 break;
6644 case TKIND_INTERFACE:
6645 case TKIND_DISPATCH:
6646 *guid = tattr->guid;
6647 break;
6649 default:
6650 ERR("Unexpected typekind %d\n", tattr->typekind);
6651 hres = E_UNEXPECTED;
6654 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6655 ITypeInfo_Release(tinfo2);
6656 return hres;
6659 /***********************************************************************
6660 * DispCallFunc (OLEAUT32.@)
6662 * Invokes a function of the specified calling convention, passing the
6663 * specified arguments and returns the result.
6665 * PARAMS
6666 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6667 * oVft [I] The offset in the vtable. See notes.
6668 * cc [I] Calling convention of the function to call.
6669 * vtReturn [I] The return type of the function.
6670 * cActuals [I] Number of parameters.
6671 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6672 * prgpvarg [I] The arguments to pass.
6673 * pvargResult [O] The return value of the function. Can be NULL.
6675 * RETURNS
6676 * Success: S_OK.
6677 * Failure: HRESULT code.
6679 * NOTES
6680 * The HRESULT return value of this function is not affected by the return
6681 * value of the user supplied function, which is returned in pvargResult.
6683 * If pvInstance is NULL then a non-object function is to be called and oVft
6684 * is the address of the function to call.
6686 * The cc parameter can be one of the following values:
6687 *|CC_FASTCALL
6688 *|CC_CDECL
6689 *|CC_PASCAL
6690 *|CC_STDCALL
6691 *|CC_FPFASTCALL
6692 *|CC_SYSCALL
6693 *|CC_MPWCDECL
6694 *|CC_MPWPASCAL
6697 HRESULT WINAPI
6698 DispCallFunc(
6699 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6700 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6702 #ifdef __i386__
6703 int argspos, stack_offset;
6704 void *func;
6705 UINT i;
6706 DWORD *args;
6708 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6709 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6710 pvargResult, V_VT(pvargResult));
6712 if (cc != CC_STDCALL && cc != CC_CDECL)
6714 FIXME("unsupported calling convention %d\n",cc);
6715 return E_INVALIDARG;
6718 /* maximum size for an argument is sizeof(VARIANT) */
6719 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6721 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6722 argspos = 1;
6723 if (pvInstance)
6725 const FARPROC *vtable = *(FARPROC **)pvInstance;
6726 func = vtable[oVft/sizeof(void *)];
6727 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6729 else func = (void *)oVft;
6731 for (i = 0; i < cActuals; i++)
6733 VARIANT *arg = prgpvarg[i];
6735 switch (prgvt[i])
6737 case VT_EMPTY:
6738 break;
6739 case VT_I8:
6740 case VT_UI8:
6741 case VT_R8:
6742 case VT_DATE:
6743 case VT_CY:
6744 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6745 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6746 break;
6747 case VT_DECIMAL:
6748 case VT_VARIANT:
6749 memcpy( &args[argspos], arg, sizeof(*arg) );
6750 argspos += sizeof(*arg) / sizeof(DWORD);
6751 break;
6752 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6753 args[argspos++] = V_BOOL(arg);
6754 break;
6755 default:
6756 args[argspos++] = V_UI4(arg);
6757 break;
6759 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6762 switch (vtReturn)
6764 case VT_EMPTY:
6765 call_method( func, argspos - 1, args + 1, &stack_offset );
6766 break;
6767 case VT_R4:
6768 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6769 break;
6770 case VT_R8:
6771 case VT_DATE:
6772 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6773 break;
6774 case VT_DECIMAL:
6775 case VT_VARIANT:
6776 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6777 call_method( func, argspos, args, &stack_offset );
6778 break;
6779 case VT_I8:
6780 case VT_UI8:
6781 case VT_CY:
6782 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6783 break;
6784 case VT_HRESULT:
6785 WARN("invalid return type %u\n", vtReturn);
6786 heap_free( args );
6787 return E_INVALIDARG;
6788 default:
6789 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6790 break;
6792 heap_free( args );
6793 if (stack_offset && cc == CC_STDCALL)
6795 WARN( "stack pointer off by %d\n", stack_offset );
6796 return DISP_E_BADCALLEE;
6798 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6799 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6800 return S_OK;
6802 #elif defined(__x86_64__)
6803 int argspos;
6804 UINT i;
6805 DWORD_PTR *args;
6806 void *func;
6808 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6809 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6810 pvargResult, V_VT(pvargResult));
6812 if (cc != CC_STDCALL && cc != CC_CDECL)
6814 FIXME("unsupported calling convention %d\n",cc);
6815 return E_INVALIDARG;
6818 /* maximum size for an argument is sizeof(DWORD_PTR) */
6819 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6821 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6822 argspos = 1;
6823 if (pvInstance)
6825 const FARPROC *vtable = *(FARPROC **)pvInstance;
6826 func = vtable[oVft/sizeof(void *)];
6827 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6829 else func = (void *)oVft;
6831 for (i = 0; i < cActuals; i++)
6833 VARIANT *arg = prgpvarg[i];
6835 switch (prgvt[i])
6837 case VT_DECIMAL:
6838 case VT_VARIANT:
6839 args[argspos++] = (ULONG_PTR)arg;
6840 break;
6841 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6842 args[argspos++] = V_BOOL(arg);
6843 break;
6844 default:
6845 args[argspos++] = V_UI8(arg);
6846 break;
6848 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6851 switch (vtReturn)
6853 case VT_R4:
6854 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6855 break;
6856 case VT_R8:
6857 case VT_DATE:
6858 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6859 break;
6860 case VT_DECIMAL:
6861 case VT_VARIANT:
6862 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6863 call_method( func, argspos, args );
6864 break;
6865 case VT_HRESULT:
6866 WARN("invalid return type %u\n", vtReturn);
6867 heap_free( args );
6868 return E_INVALIDARG;
6869 default:
6870 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6871 break;
6873 heap_free( args );
6874 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6875 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6876 return S_OK;
6878 #else
6879 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6880 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6881 return E_NOTIMPL;
6882 #endif
6885 static inline BOOL func_restricted( const FUNCDESC *desc )
6887 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6890 #define INVBUF_ELEMENT_SIZE \
6891 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6892 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6893 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6894 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6895 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6896 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6897 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6898 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6900 static HRESULT WINAPI ITypeInfo_fnInvoke(
6901 ITypeInfo2 *iface,
6902 VOID *pIUnk,
6903 MEMBERID memid,
6904 UINT16 wFlags,
6905 DISPPARAMS *pDispParams,
6906 VARIANT *pVarResult,
6907 EXCEPINFO *pExcepInfo,
6908 UINT *pArgErr)
6910 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6911 int i;
6912 unsigned int var_index;
6913 TYPEKIND type_kind;
6914 HRESULT hres;
6915 const TLBFuncDesc *pFuncInfo;
6916 UINT fdc;
6918 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6919 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6922 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6923 return DISP_E_MEMBERNOTFOUND;
6925 if (!pDispParams)
6927 ERR("NULL pDispParams not allowed\n");
6928 return E_INVALIDARG;
6931 dump_DispParms(pDispParams);
6933 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6935 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6936 pDispParams->cNamedArgs, pDispParams->cArgs);
6937 return E_INVALIDARG;
6940 /* we do this instead of using GetFuncDesc since it will return a fake
6941 * FUNCDESC for dispinterfaces and we want the real function description */
6942 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6943 pFuncInfo = &This->funcdescs[fdc];
6944 if ((memid == pFuncInfo->funcdesc.memid) &&
6945 (wFlags & pFuncInfo->funcdesc.invkind) &&
6946 !func_restricted( &pFuncInfo->funcdesc ))
6947 break;
6950 if (fdc < This->cFuncs) {
6951 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6953 if (TRACE_ON(ole))
6955 TRACE("invoking:\n");
6956 dump_TLBFuncDescOne(pFuncInfo);
6959 switch (func_desc->funckind) {
6960 case FUNC_PUREVIRTUAL:
6961 case FUNC_VIRTUAL: {
6962 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6963 VARIANT varresult;
6964 VARIANT retval; /* pointer for storing byref retvals in */
6965 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6966 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6967 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6968 UINT cNamedArgs = pDispParams->cNamedArgs;
6969 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6970 UINT vargs_converted=0;
6972 hres = S_OK;
6974 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6976 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6978 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6979 hres = DISP_E_PARAMNOTFOUND;
6980 goto func_fail;
6984 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6986 ERR("functions with the vararg attribute do not support named arguments\n");
6987 hres = DISP_E_NONAMEDARGS;
6988 goto func_fail;
6991 for (i = 0; i < func_desc->cParams; i++)
6993 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6994 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6995 if (FAILED(hres))
6996 goto func_fail;
6999 TRACE("changing args\n");
7000 for (i = 0; i < func_desc->cParams; i++)
7002 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7003 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7004 VARIANTARG *src_arg;
7006 if (wParamFlags & PARAMFLAG_FLCID)
7008 VARIANTARG *arg;
7009 arg = prgpvarg[i] = &rgvarg[i];
7010 V_VT(arg) = VT_I4;
7011 V_I4(arg) = This->pTypeLib->lcid;
7012 continue;
7015 src_arg = NULL;
7017 if (cNamedArgs)
7019 USHORT j;
7020 for (j = 0; j < cNamedArgs; j++)
7021 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7023 src_arg = &pDispParams->rgvarg[j];
7024 break;
7028 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7030 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7031 vargs_converted++;
7034 if (wParamFlags & PARAMFLAG_FRETVAL)
7036 /* under most conditions the caller is not allowed to
7037 * pass in a dispparam arg in the index of what would be
7038 * the retval parameter. however, there is an exception
7039 * where the extra parameter is used in an extra
7040 * IDispatch::Invoke below */
7041 if ((i < pDispParams->cArgs) &&
7042 ((func_desc->cParams != 1) || !pVarResult ||
7043 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7045 hres = DISP_E_BADPARAMCOUNT;
7046 break;
7049 /* note: this check is placed so that if the caller passes
7050 * in a VARIANTARG for the retval we just ignore it, like
7051 * native does */
7052 if (i == func_desc->cParams - 1)
7054 VARIANTARG *arg;
7055 arg = prgpvarg[i] = &rgvarg[i];
7056 memset(arg, 0, sizeof(*arg));
7057 V_VT(arg) = rgvt[i];
7058 memset(&retval, 0, sizeof(retval));
7059 V_BYREF(arg) = &retval;
7061 else
7063 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7064 hres = E_UNEXPECTED;
7065 break;
7068 else if (src_arg)
7070 TRACE("%s\n", debugstr_variant(src_arg));
7072 if(rgvt[i]!=V_VT(src_arg))
7074 if (rgvt[i] == VT_VARIANT)
7075 hres = VariantCopy(&rgvarg[i], src_arg);
7076 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7078 if (rgvt[i] == V_VT(src_arg))
7079 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7080 else
7082 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7083 if (wParamFlags & PARAMFLAG_FIN)
7084 hres = VariantCopy(&missing_arg[i], src_arg);
7085 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7087 V_VT(&rgvarg[i]) = rgvt[i];
7089 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
7091 SAFEARRAY *a;
7092 SAFEARRAYBOUND bound;
7093 VARIANT *v;
7094 LONG j;
7095 bound.lLbound = 0;
7096 bound.cElements = pDispParams->cArgs-i;
7097 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7099 ERR("SafeArrayCreate failed\n");
7100 break;
7102 hres = SafeArrayAccessData(a, (LPVOID)&v);
7103 if (hres != S_OK)
7105 ERR("SafeArrayAccessData failed with %x\n", hres);
7106 SafeArrayDestroy(a);
7107 break;
7109 for (j = 0; j < bound.cElements; j++)
7110 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7111 hres = SafeArrayUnaccessData(a);
7112 if (hres != S_OK)
7114 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7115 SafeArrayDestroy(a);
7116 break;
7118 V_ARRAY(&rgvarg[i]) = a;
7119 V_VT(&rgvarg[i]) = rgvt[i];
7121 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7123 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7124 if (wParamFlags & PARAMFLAG_FIN)
7125 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7126 else
7127 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7128 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7129 V_VT(&rgvarg[i]) = rgvt[i];
7131 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7133 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7134 V_VT(&rgvarg[i]) = rgvt[i];
7136 else
7138 /* FIXME: this doesn't work for VT_BYREF arguments if
7139 * they are not the same type as in the paramdesc */
7140 V_VT(&rgvarg[i]) = V_VT(src_arg);
7141 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7142 V_VT(&rgvarg[i]) = rgvt[i];
7145 if (FAILED(hres))
7147 ERR("failed to convert param %d to %s from %s\n", i,
7148 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7149 break;
7151 prgpvarg[i] = &rgvarg[i];
7153 else
7155 prgpvarg[i] = src_arg;
7158 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7159 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7160 && V_UNKNOWN(prgpvarg[i])) {
7161 IUnknown *userdefined_iface;
7162 GUID guid;
7164 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7165 if(FAILED(hres))
7166 break;
7168 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7169 if(FAILED(hres)) {
7170 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7171 break;
7174 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7175 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7178 else if (wParamFlags & PARAMFLAG_FOPT)
7180 VARIANTARG *arg;
7181 arg = prgpvarg[i] = &rgvarg[i];
7182 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7184 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7185 if (FAILED(hres))
7186 break;
7188 else
7190 VARIANTARG *missing_arg;
7191 /* if the function wants a pointer to a variant then
7192 * set that up, otherwise just pass the VT_ERROR in
7193 * the argument by value */
7194 if (rgvt[i] & VT_BYREF)
7196 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7197 V_VT(arg) = VT_VARIANT | VT_BYREF;
7198 V_VARIANTREF(arg) = missing_arg;
7200 else
7201 missing_arg = arg;
7202 V_VT(missing_arg) = VT_ERROR;
7203 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7206 else
7208 hres = DISP_E_BADPARAMCOUNT;
7209 break;
7212 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7214 /* VT_VOID is a special case for return types, so it is not
7215 * handled in the general function */
7216 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7217 V_VT(&varresult) = VT_EMPTY;
7218 else
7220 V_VT(&varresult) = 0;
7221 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7222 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7225 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7226 V_VT(&varresult), func_desc->cParams, rgvt,
7227 prgpvarg, &varresult);
7229 vargs_converted = 0;
7231 for (i = 0; i < func_desc->cParams; i++)
7233 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7234 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7236 if (wParamFlags & PARAMFLAG_FLCID)
7237 continue;
7238 else if (wParamFlags & PARAMFLAG_FRETVAL)
7240 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7242 if (pVarResult)
7244 VariantInit(pVarResult);
7245 /* deref return value */
7246 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7249 VARIANT_ClearInd(prgpvarg[i]);
7251 else if (vargs_converted < pDispParams->cArgs)
7253 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7254 if (wParamFlags & PARAMFLAG_FOUT)
7256 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7258 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7260 if (FAILED(hres))
7262 ERR("failed to convert param %d to vt %d\n", i,
7263 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7264 break;
7268 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7269 func_desc->cParamsOpt < 0 &&
7270 i == func_desc->cParams-1)
7272 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7273 LONG j, ubound;
7274 VARIANT *v;
7275 hres = SafeArrayGetUBound(a, 1, &ubound);
7276 if (hres != S_OK)
7278 ERR("SafeArrayGetUBound failed with %x\n", hres);
7279 break;
7281 hres = SafeArrayAccessData(a, (LPVOID)&v);
7282 if (hres != S_OK)
7284 ERR("SafeArrayAccessData failed with %x\n", hres);
7285 break;
7287 for (j = 0; j <= ubound; j++)
7288 VariantClear(&v[j]);
7289 hres = SafeArrayUnaccessData(a);
7290 if (hres != S_OK)
7292 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7293 break;
7296 VariantClear(&rgvarg[i]);
7297 vargs_converted++;
7299 else if (wParamFlags & PARAMFLAG_FOPT)
7301 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7302 VariantClear(&rgvarg[i]);
7305 VariantClear(&missing_arg[i]);
7308 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7310 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7311 hres = DISP_E_EXCEPTION;
7312 if (pExcepInfo)
7314 IErrorInfo *pErrorInfo;
7315 pExcepInfo->scode = V_ERROR(&varresult);
7316 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7318 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7319 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7320 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7321 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7323 IErrorInfo_Release(pErrorInfo);
7327 if (V_VT(&varresult) != VT_ERROR)
7329 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7331 if (pVarResult)
7333 VariantClear(pVarResult);
7334 *pVarResult = varresult;
7336 else
7337 VariantClear(&varresult);
7340 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7341 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7342 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7343 (pDispParams->cArgs != 0))
7345 if (V_VT(pVarResult) == VT_DISPATCH)
7347 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7348 /* Note: not VariantClear; we still need the dispatch
7349 * pointer to be valid */
7350 VariantInit(pVarResult);
7351 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7352 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7353 pDispParams, pVarResult, pExcepInfo, pArgErr);
7354 IDispatch_Release(pDispatch);
7356 else
7358 VariantClear(pVarResult);
7359 hres = DISP_E_NOTACOLLECTION;
7363 func_fail:
7364 heap_free(buffer);
7365 break;
7367 case FUNC_DISPATCH: {
7368 IDispatch *disp;
7370 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7371 if (SUCCEEDED(hres)) {
7372 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7373 hres = IDispatch_Invoke(
7374 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7375 pVarResult,pExcepInfo,pArgErr
7377 if (FAILED(hres))
7378 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7379 IDispatch_Release(disp);
7380 } else
7381 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7382 break;
7384 default:
7385 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7386 hres = E_FAIL;
7387 break;
7390 TRACE("-- 0x%08x\n", hres);
7391 return hres;
7393 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7394 VARDESC *var_desc;
7396 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7397 if(FAILED(hres)) return hres;
7399 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7400 dump_VARDESC(var_desc);
7401 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7402 return E_NOTIMPL;
7405 /* not found, look for it in inherited interfaces */
7406 ITypeInfo2_GetTypeKind(iface, &type_kind);
7407 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7408 if(This->impltypes) {
7409 /* recursive search */
7410 ITypeInfo *pTInfo;
7411 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7412 if(SUCCEEDED(hres)){
7413 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7414 ITypeInfo_Release(pTInfo);
7415 return hres;
7417 WARN("Could not search inherited interface!\n");
7420 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7421 return DISP_E_MEMBERNOTFOUND;
7424 /* ITypeInfo::GetDocumentation
7426 * Retrieves the documentation string, the complete Help file name and path,
7427 * and the context ID for the Help topic for a specified type description.
7429 * (Can be tested by the Visual Basic Editor in Word for instance.)
7431 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7432 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7433 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7435 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7436 const TLBFuncDesc *pFDesc;
7437 const TLBVarDesc *pVDesc;
7438 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7439 " HelpContext(%p) HelpFile(%p)\n",
7440 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7441 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7442 if(pBstrName)
7443 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7444 if(pBstrDocString)
7445 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7446 if(pdwHelpContext)
7447 *pdwHelpContext=This->dwHelpContext;
7448 if(pBstrHelpFile)
7449 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7450 return S_OK;
7451 }else {/* for a member */
7452 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7453 if(pFDesc){
7454 if(pBstrName)
7455 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7456 if(pBstrDocString)
7457 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7458 if(pdwHelpContext)
7459 *pdwHelpContext=pFDesc->helpcontext;
7460 if(pBstrHelpFile)
7461 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7462 return S_OK;
7464 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7465 if(pVDesc){
7466 if(pBstrName)
7467 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7468 if(pBstrDocString)
7469 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7470 if(pdwHelpContext)
7471 *pdwHelpContext=pVDesc->HelpContext;
7472 if(pBstrHelpFile)
7473 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7474 return S_OK;
7478 if(This->impltypes &&
7479 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7480 /* recursive search */
7481 ITypeInfo *pTInfo;
7482 HRESULT result;
7483 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7484 if(SUCCEEDED(result)) {
7485 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7486 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7487 ITypeInfo_Release(pTInfo);
7488 return result;
7490 WARN("Could not search inherited interface!\n");
7493 WARN("member %d not found\n", memid);
7494 return TYPE_E_ELEMENTNOTFOUND;
7497 /* ITypeInfo::GetDllEntry
7499 * Retrieves a description or specification of an entry point for a function
7500 * in a DLL.
7502 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7503 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7504 WORD *pwOrdinal)
7506 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7507 const TLBFuncDesc *pFDesc;
7509 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7511 if (pBstrDllName) *pBstrDllName = NULL;
7512 if (pBstrName) *pBstrName = NULL;
7513 if (pwOrdinal) *pwOrdinal = 0;
7515 if (This->typekind != TKIND_MODULE)
7516 return TYPE_E_BADMODULEKIND;
7518 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7519 if(pFDesc){
7520 dump_TypeInfo(This);
7521 if (TRACE_ON(ole))
7522 dump_TLBFuncDescOne(pFDesc);
7524 if (pBstrDllName)
7525 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7527 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7528 if (pBstrName)
7529 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7530 if (pwOrdinal)
7531 *pwOrdinal = -1;
7532 return S_OK;
7534 if (pBstrName)
7535 *pBstrName = NULL;
7536 if (pwOrdinal)
7537 *pwOrdinal = LOWORD(pFDesc->Entry);
7538 return S_OK;
7540 return TYPE_E_ELEMENTNOTFOUND;
7543 /* internal function to make the inherited interfaces' methods appear
7544 * part of the interface */
7545 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7546 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7548 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7549 HRESULT hr;
7551 TRACE("%p, 0x%x\n", iface, *hRefType);
7553 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7555 ITypeInfo *pSubTypeInfo;
7557 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7558 if (FAILED(hr))
7559 return hr;
7561 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7562 hRefType, ppTInfo);
7563 ITypeInfo_Release(pSubTypeInfo);
7564 if (SUCCEEDED(hr))
7565 return hr;
7567 *hRefType -= DISPATCH_HREF_OFFSET;
7569 if (!(*hRefType & DISPATCH_HREF_MASK))
7570 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7571 else
7572 return E_FAIL;
7575 /* ITypeInfo::GetRefTypeInfo
7577 * If a type description references other type descriptions, it retrieves
7578 * the referenced type descriptions.
7580 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7581 ITypeInfo2 *iface,
7582 HREFTYPE hRefType,
7583 ITypeInfo **ppTInfo)
7585 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7586 HRESULT result = E_FAIL;
7588 if(!ppTInfo)
7589 return E_INVALIDARG;
7591 if ((INT)hRefType < 0) {
7592 ITypeInfoImpl *pTypeInfoImpl;
7594 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7595 !(This->typekind == TKIND_INTERFACE ||
7596 This->typekind == TKIND_DISPATCH))
7597 return TYPE_E_ELEMENTNOTFOUND;
7599 /* when we meet a DUAL typeinfo, we must create the alternate
7600 * version of it.
7602 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7604 *pTypeInfoImpl = *This;
7605 pTypeInfoImpl->ref = 0;
7606 list_init(&pTypeInfoImpl->custdata_list);
7608 if (This->typekind == TKIND_INTERFACE)
7609 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7610 else
7611 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7613 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7614 /* the AddRef implicitly adds a reference to the parent typelib, which
7615 * stops the copied data from being destroyed until the new typeinfo's
7616 * refcount goes to zero, but we need to signal to the new instance to
7617 * not free its data structures when it is destroyed */
7618 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7620 ITypeInfo_AddRef(*ppTInfo);
7622 result = S_OK;
7623 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7624 (This->typekind == TKIND_DISPATCH))
7626 HREFTYPE href_dispatch = hRefType;
7627 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7628 } else {
7629 TLBRefType *ref_type;
7630 ITypeLib *pTLib = NULL;
7631 UINT i;
7633 if(!(hRefType & 0x1)){
7634 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7636 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7638 result = S_OK;
7639 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7640 ITypeInfo_AddRef(*ppTInfo);
7641 goto end;
7646 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7648 if(ref_type->reference == (hRefType & (~0x3)))
7649 break;
7651 if(&ref_type->entry == &This->pTypeLib->ref_list)
7653 FIXME("Can't find pRefType for ref %x\n", hRefType);
7654 goto end;
7657 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7658 UINT Index;
7659 TRACE("internal reference\n");
7660 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7661 } else {
7662 if(ref_type->pImpTLInfo->pImpTypeLib) {
7663 TRACE("typeinfo in imported typelib that is already loaded\n");
7664 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7665 ITypeLib_AddRef(pTLib);
7666 result = S_OK;
7667 } else {
7668 BSTR libnam;
7670 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7672 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7673 ref_type->pImpTLInfo->wVersionMajor,
7674 ref_type->pImpTLInfo->wVersionMinor,
7675 This->pTypeLib->syskind,
7676 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7677 if(FAILED(result))
7678 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7680 result = LoadTypeLib(libnam, &pTLib);
7681 SysFreeString(libnam);
7683 if(SUCCEEDED(result)) {
7684 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7685 ITypeLib_AddRef(pTLib);
7689 if(SUCCEEDED(result)) {
7690 if(ref_type->index == TLB_REF_USE_GUID)
7691 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7692 else
7693 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7695 if (pTLib != NULL)
7696 ITypeLib_Release(pTLib);
7699 end:
7700 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7701 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7702 return result;
7705 /* ITypeInfo::AddressOfMember
7707 * Retrieves the addresses of static functions or variables, such as those
7708 * defined in a DLL.
7710 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7711 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7713 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7714 HRESULT hr;
7715 BSTR dll, entry;
7716 WORD ordinal;
7717 HMODULE module;
7719 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7721 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7722 if (FAILED(hr))
7723 return hr;
7725 module = LoadLibraryW(dll);
7726 if (!module)
7728 ERR("couldn't load %s\n", debugstr_w(dll));
7729 SysFreeString(dll);
7730 SysFreeString(entry);
7731 return STG_E_FILENOTFOUND;
7733 /* FIXME: store library somewhere where we can free it */
7735 if (entry)
7737 LPSTR entryA;
7738 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7739 entryA = heap_alloc(len);
7740 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7742 *ppv = GetProcAddress(module, entryA);
7743 if (!*ppv)
7744 ERR("function not found %s\n", debugstr_a(entryA));
7746 heap_free(entryA);
7748 else
7750 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7751 if (!*ppv)
7752 ERR("function not found %d\n", ordinal);
7755 SysFreeString(dll);
7756 SysFreeString(entry);
7758 if (!*ppv)
7759 return TYPE_E_DLLFUNCTIONNOTFOUND;
7761 return S_OK;
7764 /* ITypeInfo::CreateInstance
7766 * Creates a new instance of a type that describes a component object class
7767 * (coclass).
7769 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7770 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7772 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7773 HRESULT hr;
7774 TYPEATTR *pTA;
7776 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7778 *ppvObj = NULL;
7780 if(pOuterUnk)
7782 WARN("Not able to aggregate\n");
7783 return CLASS_E_NOAGGREGATION;
7786 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7787 if(FAILED(hr)) return hr;
7789 if(pTA->typekind != TKIND_COCLASS)
7791 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7792 hr = E_INVALIDARG;
7793 goto end;
7796 hr = S_FALSE;
7797 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7799 IUnknown *pUnk;
7800 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7801 TRACE("GetActiveObject rets %08x\n", hr);
7802 if(hr == S_OK)
7804 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7805 IUnknown_Release(pUnk);
7809 if(hr != S_OK)
7810 hr = CoCreateInstance(&pTA->guid, NULL,
7811 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7812 riid, ppvObj);
7814 end:
7815 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7816 return hr;
7819 /* ITypeInfo::GetMops
7821 * Retrieves marshalling information.
7823 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7824 BSTR *pBstrMops)
7826 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7827 FIXME("(%p %d) stub!\n", This, memid);
7828 *pBstrMops = NULL;
7829 return S_OK;
7832 /* ITypeInfo::GetContainingTypeLib
7834 * Retrieves the containing type library and the index of the type description
7835 * within that type library.
7837 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7838 ITypeLib * *ppTLib, UINT *pIndex)
7840 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7842 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7843 if (pIndex) {
7844 *pIndex=This->index;
7845 TRACE("returning pIndex=%d\n", *pIndex);
7848 if (ppTLib) {
7849 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7850 ITypeLib_AddRef(*ppTLib);
7851 TRACE("returning ppTLib=%p\n", *ppTLib);
7854 return S_OK;
7857 /* ITypeInfo::ReleaseTypeAttr
7859 * Releases a TYPEATTR previously returned by Get
7862 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7863 TYPEATTR* pTypeAttr)
7865 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7866 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7867 heap_free(pTypeAttr);
7870 /* ITypeInfo::ReleaseFuncDesc
7872 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7874 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7875 ITypeInfo2 *iface,
7876 FUNCDESC *pFuncDesc)
7878 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7879 SHORT i;
7881 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7883 for (i = 0; i < pFuncDesc->cParams; i++)
7884 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7885 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7887 SysFreeString((BSTR)pFuncDesc);
7890 /* ITypeInfo::ReleaseVarDesc
7892 * Releases a VARDESC previously returned by GetVarDesc.
7894 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7895 VARDESC *pVarDesc)
7897 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7898 TRACE("(%p)->(%p)\n", This, pVarDesc);
7900 TLB_FreeVarDesc(pVarDesc);
7903 /* ITypeInfo2::GetTypeKind
7905 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7908 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7909 TYPEKIND *pTypeKind)
7911 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7912 *pTypeKind=This->typekind;
7913 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7914 return S_OK;
7917 /* ITypeInfo2::GetTypeFlags
7919 * Returns the type flags without any allocations. This returns a DWORD type
7920 * flag, which expands the type flags without growing the TYPEATTR (type
7921 * attribute).
7924 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7926 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7927 *pTypeFlags=This->wTypeFlags;
7928 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7929 return S_OK;
7932 /* ITypeInfo2::GetFuncIndexOfMemId
7933 * Binds to a specific member based on a known DISPID, where the member name
7934 * is not known (for example, when binding to a default member).
7937 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7938 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7940 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7941 UINT fdc;
7942 HRESULT result;
7944 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7945 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7946 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7947 break;
7949 if(fdc < This->cFuncs) {
7950 *pFuncIndex = fdc;
7951 result = S_OK;
7952 } else
7953 result = TYPE_E_ELEMENTNOTFOUND;
7955 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7956 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7957 return result;
7960 /* TypeInfo2::GetVarIndexOfMemId
7962 * Binds to a specific member based on a known DISPID, where the member name
7963 * is not known (for example, when binding to a default member).
7966 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7967 MEMBERID memid, UINT *pVarIndex)
7969 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7970 TLBVarDesc *pVarInfo;
7972 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7974 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7975 if(!pVarInfo)
7976 return TYPE_E_ELEMENTNOTFOUND;
7978 *pVarIndex = (pVarInfo - This->vardescs);
7980 return S_OK;
7983 /* ITypeInfo2::GetCustData
7985 * Gets the custom data
7987 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7988 ITypeInfo2 * iface,
7989 REFGUID guid,
7990 VARIANT *pVarVal)
7992 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7993 TLBCustData *pCData;
7995 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7997 if(!guid || !pVarVal)
7998 return E_INVALIDARG;
8000 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8002 VariantInit( pVarVal);
8003 if (pCData)
8004 VariantCopy( pVarVal, &pCData->data);
8005 else
8006 VariantClear( pVarVal );
8007 return S_OK;
8010 /* ITypeInfo2::GetFuncCustData
8012 * Gets the custom data
8014 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8015 ITypeInfo2 * iface,
8016 UINT index,
8017 REFGUID guid,
8018 VARIANT *pVarVal)
8020 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8021 TLBCustData *pCData;
8022 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8024 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8026 if(index >= This->cFuncs)
8027 return TYPE_E_ELEMENTNOTFOUND;
8029 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8030 if(!pCData)
8031 return TYPE_E_ELEMENTNOTFOUND;
8033 VariantInit(pVarVal);
8034 VariantCopy(pVarVal, &pCData->data);
8036 return S_OK;
8039 /* ITypeInfo2::GetParamCustData
8041 * Gets the custom data
8043 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8044 ITypeInfo2 * iface,
8045 UINT indexFunc,
8046 UINT indexParam,
8047 REFGUID guid,
8048 VARIANT *pVarVal)
8050 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8051 TLBCustData *pCData;
8052 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8054 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8055 debugstr_guid(guid), pVarVal);
8057 if(indexFunc >= This->cFuncs)
8058 return TYPE_E_ELEMENTNOTFOUND;
8060 if(indexParam >= pFDesc->funcdesc.cParams)
8061 return TYPE_E_ELEMENTNOTFOUND;
8063 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8064 if(!pCData)
8065 return TYPE_E_ELEMENTNOTFOUND;
8067 VariantInit(pVarVal);
8068 VariantCopy(pVarVal, &pCData->data);
8070 return S_OK;
8073 /* ITypeInfo2::GetVarCustData
8075 * Gets the custom data
8077 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8078 ITypeInfo2 * iface,
8079 UINT index,
8080 REFGUID guid,
8081 VARIANT *pVarVal)
8083 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8084 TLBCustData *pCData;
8085 TLBVarDesc *pVDesc = &This->vardescs[index];
8087 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8089 if(index >= This->cVars)
8090 return TYPE_E_ELEMENTNOTFOUND;
8092 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8093 if(!pCData)
8094 return TYPE_E_ELEMENTNOTFOUND;
8096 VariantInit(pVarVal);
8097 VariantCopy(pVarVal, &pCData->data);
8099 return S_OK;
8102 /* ITypeInfo2::GetImplCustData
8104 * Gets the custom data
8106 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8107 ITypeInfo2 * iface,
8108 UINT index,
8109 REFGUID guid,
8110 VARIANT *pVarVal)
8112 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8113 TLBCustData *pCData;
8114 TLBImplType *pRDesc = &This->impltypes[index];
8116 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8118 if(index >= This->cImplTypes)
8119 return TYPE_E_ELEMENTNOTFOUND;
8121 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8122 if(!pCData)
8123 return TYPE_E_ELEMENTNOTFOUND;
8125 VariantInit(pVarVal);
8126 VariantCopy(pVarVal, &pCData->data);
8128 return S_OK;
8131 /* ITypeInfo2::GetDocumentation2
8133 * Retrieves the documentation string, the complete Help file name and path,
8134 * the localization context to use, and the context ID for the library Help
8135 * topic in the Help file.
8138 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8139 ITypeInfo2 * iface,
8140 MEMBERID memid,
8141 LCID lcid,
8142 BSTR *pbstrHelpString,
8143 DWORD *pdwHelpStringContext,
8144 BSTR *pbstrHelpStringDll)
8146 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8147 const TLBFuncDesc *pFDesc;
8148 const TLBVarDesc *pVDesc;
8149 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8150 "HelpStringContext(%p) HelpStringDll(%p)\n",
8151 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8152 pbstrHelpStringDll );
8153 /* the help string should be obtained from the helpstringdll,
8154 * using the _DLLGetDocumentation function, based on the supplied
8155 * lcid. Nice to do sometime...
8157 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8158 if(pbstrHelpString)
8159 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8160 if(pdwHelpStringContext)
8161 *pdwHelpStringContext=This->dwHelpStringContext;
8162 if(pbstrHelpStringDll)
8163 *pbstrHelpStringDll=
8164 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8165 return S_OK;
8166 }else {/* for a member */
8167 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
8168 if(pFDesc){
8169 if(pbstrHelpString)
8170 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8171 if(pdwHelpStringContext)
8172 *pdwHelpStringContext=pFDesc->HelpStringContext;
8173 if(pbstrHelpStringDll)
8174 *pbstrHelpStringDll=
8175 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8176 return S_OK;
8178 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8179 if(pVDesc){
8180 if(pbstrHelpString)
8181 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8182 if(pdwHelpStringContext)
8183 *pdwHelpStringContext=pVDesc->HelpStringContext;
8184 if(pbstrHelpStringDll)
8185 *pbstrHelpStringDll=
8186 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8187 return S_OK;
8190 return TYPE_E_ELEMENTNOTFOUND;
8193 /* ITypeInfo2::GetAllCustData
8195 * Gets all custom data items for the Type info.
8198 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8199 ITypeInfo2 * iface,
8200 CUSTDATA *pCustData)
8202 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8204 TRACE("%p %p\n", This, pCustData);
8206 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8209 /* ITypeInfo2::GetAllFuncCustData
8211 * Gets all custom data items for the specified Function
8214 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8215 ITypeInfo2 * iface,
8216 UINT index,
8217 CUSTDATA *pCustData)
8219 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8220 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8222 TRACE("%p %u %p\n", This, index, pCustData);
8224 if(index >= This->cFuncs)
8225 return TYPE_E_ELEMENTNOTFOUND;
8227 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8230 /* ITypeInfo2::GetAllParamCustData
8232 * Gets all custom data items for the Functions
8235 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8236 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8238 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8239 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8241 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8243 if(indexFunc >= This->cFuncs)
8244 return TYPE_E_ELEMENTNOTFOUND;
8246 if(indexParam >= pFDesc->funcdesc.cParams)
8247 return TYPE_E_ELEMENTNOTFOUND;
8249 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8252 /* ITypeInfo2::GetAllVarCustData
8254 * Gets all custom data items for the specified Variable
8257 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8258 UINT index, CUSTDATA *pCustData)
8260 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8261 TLBVarDesc * pVDesc = &This->vardescs[index];
8263 TRACE("%p %u %p\n", This, index, pCustData);
8265 if(index >= This->cVars)
8266 return TYPE_E_ELEMENTNOTFOUND;
8268 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8271 /* ITypeInfo2::GetAllImplCustData
8273 * Gets all custom data items for the specified implementation type
8276 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8277 ITypeInfo2 * iface,
8278 UINT index,
8279 CUSTDATA *pCustData)
8281 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8282 TLBImplType *pRDesc = &This->impltypes[index];
8284 TRACE("%p %u %p\n", This, index, pCustData);
8286 if(index >= This->cImplTypes)
8287 return TYPE_E_ELEMENTNOTFOUND;
8289 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8292 static const ITypeInfo2Vtbl tinfvt =
8295 ITypeInfo_fnQueryInterface,
8296 ITypeInfo_fnAddRef,
8297 ITypeInfo_fnRelease,
8299 ITypeInfo_fnGetTypeAttr,
8300 ITypeInfo_fnGetTypeComp,
8301 ITypeInfo_fnGetFuncDesc,
8302 ITypeInfo_fnGetVarDesc,
8303 ITypeInfo_fnGetNames,
8304 ITypeInfo_fnGetRefTypeOfImplType,
8305 ITypeInfo_fnGetImplTypeFlags,
8306 ITypeInfo_fnGetIDsOfNames,
8307 ITypeInfo_fnInvoke,
8308 ITypeInfo_fnGetDocumentation,
8309 ITypeInfo_fnGetDllEntry,
8310 ITypeInfo_fnGetRefTypeInfo,
8311 ITypeInfo_fnAddressOfMember,
8312 ITypeInfo_fnCreateInstance,
8313 ITypeInfo_fnGetMops,
8314 ITypeInfo_fnGetContainingTypeLib,
8315 ITypeInfo_fnReleaseTypeAttr,
8316 ITypeInfo_fnReleaseFuncDesc,
8317 ITypeInfo_fnReleaseVarDesc,
8319 ITypeInfo2_fnGetTypeKind,
8320 ITypeInfo2_fnGetTypeFlags,
8321 ITypeInfo2_fnGetFuncIndexOfMemId,
8322 ITypeInfo2_fnGetVarIndexOfMemId,
8323 ITypeInfo2_fnGetCustData,
8324 ITypeInfo2_fnGetFuncCustData,
8325 ITypeInfo2_fnGetParamCustData,
8326 ITypeInfo2_fnGetVarCustData,
8327 ITypeInfo2_fnGetImplTypeCustData,
8328 ITypeInfo2_fnGetDocumentation2,
8329 ITypeInfo2_fnGetAllCustData,
8330 ITypeInfo2_fnGetAllFuncCustData,
8331 ITypeInfo2_fnGetAllParamCustData,
8332 ITypeInfo2_fnGetAllVarCustData,
8333 ITypeInfo2_fnGetAllImplTypeCustData,
8336 /******************************************************************************
8337 * CreateDispTypeInfo [OLEAUT32.31]
8339 * Build type information for an object so it can be called through an
8340 * IDispatch interface.
8342 * RETURNS
8343 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8344 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8346 * NOTES
8347 * This call allows an objects methods to be accessed through IDispatch, by
8348 * building an ITypeInfo object that IDispatch can use to call through.
8350 HRESULT WINAPI CreateDispTypeInfo(
8351 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8352 LCID lcid, /* [I] Locale Id */
8353 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8355 ITypeInfoImpl *pTIClass, *pTIIface;
8356 ITypeLibImpl *pTypeLibImpl;
8357 unsigned int param, func;
8358 TLBFuncDesc *pFuncDesc;
8359 TLBRefType *ref;
8361 TRACE("\n");
8362 pTypeLibImpl = TypeLibImpl_Constructor();
8363 if (!pTypeLibImpl) return E_FAIL;
8365 pTypeLibImpl->TypeInfoCount = 2;
8366 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8368 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8369 pTIIface->pTypeLib = pTypeLibImpl;
8370 pTIIface->index = 0;
8371 pTIIface->Name = NULL;
8372 pTIIface->dwHelpContext = -1;
8373 pTIIface->guid = NULL;
8374 pTIIface->lcid = lcid;
8375 pTIIface->typekind = TKIND_INTERFACE;
8376 pTIIface->wMajorVerNum = 0;
8377 pTIIface->wMinorVerNum = 0;
8378 pTIIface->cbAlignment = 2;
8379 pTIIface->cbSizeInstance = -1;
8380 pTIIface->cbSizeVft = -1;
8381 pTIIface->cFuncs = 0;
8382 pTIIface->cImplTypes = 0;
8383 pTIIface->cVars = 0;
8384 pTIIface->wTypeFlags = 0;
8385 pTIIface->hreftype = 0;
8387 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8388 pFuncDesc = pTIIface->funcdescs;
8389 for(func = 0; func < pidata->cMembers; func++) {
8390 METHODDATA *md = pidata->pmethdata + func;
8391 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8392 pFuncDesc->funcdesc.memid = md->dispid;
8393 pFuncDesc->funcdesc.lprgscode = NULL;
8394 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8395 pFuncDesc->funcdesc.invkind = md->wFlags;
8396 pFuncDesc->funcdesc.callconv = md->cc;
8397 pFuncDesc->funcdesc.cParams = md->cArgs;
8398 pFuncDesc->funcdesc.cParamsOpt = 0;
8399 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8400 pFuncDesc->funcdesc.cScodes = 0;
8401 pFuncDesc->funcdesc.wFuncFlags = 0;
8402 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8403 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8404 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8405 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8406 md->cArgs * sizeof(ELEMDESC));
8407 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8408 for(param = 0; param < md->cArgs; param++) {
8409 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8410 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8412 pFuncDesc->helpcontext = 0;
8413 pFuncDesc->HelpStringContext = 0;
8414 pFuncDesc->HelpString = NULL;
8415 pFuncDesc->Entry = NULL;
8416 list_init(&pFuncDesc->custdata_list);
8417 pTIIface->cFuncs++;
8418 ++pFuncDesc;
8421 dump_TypeInfo(pTIIface);
8423 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8424 pTIClass->pTypeLib = pTypeLibImpl;
8425 pTIClass->index = 1;
8426 pTIClass->Name = NULL;
8427 pTIClass->dwHelpContext = -1;
8428 pTIClass->guid = NULL;
8429 pTIClass->lcid = lcid;
8430 pTIClass->typekind = TKIND_COCLASS;
8431 pTIClass->wMajorVerNum = 0;
8432 pTIClass->wMinorVerNum = 0;
8433 pTIClass->cbAlignment = 2;
8434 pTIClass->cbSizeInstance = -1;
8435 pTIClass->cbSizeVft = -1;
8436 pTIClass->cFuncs = 0;
8437 pTIClass->cImplTypes = 1;
8438 pTIClass->cVars = 0;
8439 pTIClass->wTypeFlags = 0;
8440 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8442 pTIClass->impltypes = TLBImplType_Alloc(1);
8444 ref = heap_alloc_zero(sizeof(*ref));
8445 ref->pImpTLInfo = TLB_REF_INTERNAL;
8446 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8448 dump_TypeInfo(pTIClass);
8450 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8452 ITypeInfo_AddRef(*pptinfo);
8453 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8455 return S_OK;
8459 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8461 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8463 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8466 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8468 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8470 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8473 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8475 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8477 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8480 static HRESULT WINAPI ITypeComp_fnBind(
8481 ITypeComp * iface,
8482 OLECHAR * szName,
8483 ULONG lHash,
8484 WORD wFlags,
8485 ITypeInfo ** ppTInfo,
8486 DESCKIND * pDescKind,
8487 BINDPTR * pBindPtr)
8489 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8490 const TLBFuncDesc *pFDesc;
8491 const TLBVarDesc *pVDesc;
8492 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8493 UINT fdc;
8495 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8497 *pDescKind = DESCKIND_NONE;
8498 pBindPtr->lpfuncdesc = NULL;
8499 *ppTInfo = NULL;
8501 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8502 pFDesc = &This->funcdescs[fdc];
8503 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8504 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8505 break;
8506 else
8507 /* name found, but wrong flags */
8508 hr = TYPE_E_TYPEMISMATCH;
8512 if (fdc < This->cFuncs)
8514 HRESULT hr = TLB_AllocAndInitFuncDesc(
8515 &pFDesc->funcdesc,
8516 &pBindPtr->lpfuncdesc,
8517 This->typekind == TKIND_DISPATCH);
8518 if (FAILED(hr))
8519 return hr;
8520 *pDescKind = DESCKIND_FUNCDESC;
8521 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8522 ITypeInfo_AddRef(*ppTInfo);
8523 return S_OK;
8524 } else {
8525 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8526 if(pVDesc){
8527 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8528 if (FAILED(hr))
8529 return hr;
8530 *pDescKind = DESCKIND_VARDESC;
8531 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8532 ITypeInfo_AddRef(*ppTInfo);
8533 return S_OK;
8537 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8538 /* recursive search */
8539 ITypeInfo *pTInfo;
8540 ITypeComp *pTComp;
8541 HRESULT hr;
8542 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8543 if (SUCCEEDED(hr))
8545 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8546 ITypeInfo_Release(pTInfo);
8548 if (SUCCEEDED(hr))
8550 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8551 ITypeComp_Release(pTComp);
8552 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8553 This->typekind == TKIND_DISPATCH)
8555 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8556 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8557 SysFreeString((BSTR)tmp);
8559 return hr;
8561 WARN("Could not search inherited interface!\n");
8563 if (hr == DISP_E_MEMBERNOTFOUND)
8564 hr = S_OK;
8565 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8566 return hr;
8569 static HRESULT WINAPI ITypeComp_fnBindType(
8570 ITypeComp * iface,
8571 OLECHAR * szName,
8572 ULONG lHash,
8573 ITypeInfo ** ppTInfo,
8574 ITypeComp ** ppTComp)
8576 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8578 /* strange behaviour (does nothing) but like the
8579 * original */
8581 if (!ppTInfo || !ppTComp)
8582 return E_POINTER;
8584 *ppTInfo = NULL;
8585 *ppTComp = NULL;
8587 return S_OK;
8590 static const ITypeCompVtbl tcompvt =
8593 ITypeComp_fnQueryInterface,
8594 ITypeComp_fnAddRef,
8595 ITypeComp_fnRelease,
8597 ITypeComp_fnBind,
8598 ITypeComp_fnBindType
8601 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8602 ICreateTypeLib2** ppctlib)
8604 ITypeLibImpl *This;
8605 HRESULT hres;
8607 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8609 if (!szFile) return E_INVALIDARG;
8611 This = TypeLibImpl_Constructor();
8612 if (!This)
8613 return E_OUTOFMEMORY;
8615 This->lcid = GetSystemDefaultLCID();
8616 This->syskind = syskind;
8617 This->ptr_size = get_ptr_size(syskind);
8619 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8620 if (!This->path) {
8621 ITypeLib2_Release(&This->ITypeLib2_iface);
8622 return E_OUTOFMEMORY;
8624 lstrcpyW(This->path, szFile);
8626 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8627 ITypeLib2_Release(&This->ITypeLib2_iface);
8628 return hres;
8631 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8632 REFIID riid, void **object)
8634 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8636 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8639 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8641 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8643 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8646 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8648 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8650 return ITypeLib2_Release(&This->ITypeLib2_iface);
8653 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8654 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8656 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8657 ITypeInfoImpl *info;
8658 HRESULT hres;
8660 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8662 if (!ctinfo || !name)
8663 return E_INVALIDARG;
8665 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8666 if (info)
8667 return TYPE_E_NAMECONFLICT;
8669 if (This->typeinfos)
8670 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8671 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8672 else
8673 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8675 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8677 info->pTypeLib = This;
8678 info->Name = TLB_append_str(&This->name_list, name);
8679 info->index = This->TypeInfoCount;
8680 info->typekind = kind;
8681 info->cbAlignment = 4;
8683 switch(info->typekind) {
8684 case TKIND_ENUM:
8685 case TKIND_INTERFACE:
8686 case TKIND_DISPATCH:
8687 case TKIND_COCLASS:
8688 info->cbSizeInstance = This->ptr_size;
8689 break;
8690 case TKIND_RECORD:
8691 case TKIND_UNION:
8692 info->cbSizeInstance = 0;
8693 break;
8694 case TKIND_MODULE:
8695 info->cbSizeInstance = 2;
8696 break;
8697 case TKIND_ALIAS:
8698 info->cbSizeInstance = -0x75;
8699 break;
8700 default:
8701 FIXME("unrecognized typekind %d\n", info->typekind);
8702 info->cbSizeInstance = 0xdeadbeef;
8703 break;
8706 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8707 &IID_ICreateTypeInfo, (void **)ctinfo);
8708 if (FAILED(hres)) {
8709 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8710 return hres;
8713 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8715 ++This->TypeInfoCount;
8717 return S_OK;
8720 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8721 LPOLESTR name)
8723 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8725 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8727 if (!name)
8728 return E_INVALIDARG;
8730 This->Name = TLB_append_str(&This->name_list, name);
8732 return S_OK;
8735 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8736 WORD majorVerNum, WORD minorVerNum)
8738 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8740 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8742 This->ver_major = majorVerNum;
8743 This->ver_minor = minorVerNum;
8745 return S_OK;
8748 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8749 REFGUID guid)
8751 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8753 TRACE("%p %s\n", This, debugstr_guid(guid));
8755 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8757 return S_OK;
8760 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8761 LPOLESTR doc)
8763 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8765 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8767 if (!doc)
8768 return E_INVALIDARG;
8770 This->DocString = TLB_append_str(&This->string_list, doc);
8772 return S_OK;
8775 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8776 LPOLESTR helpFileName)
8778 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8780 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8782 if (!helpFileName)
8783 return E_INVALIDARG;
8785 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8787 return S_OK;
8790 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8791 DWORD helpContext)
8793 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8795 TRACE("%p %d\n", This, helpContext);
8797 This->dwHelpContext = helpContext;
8799 return S_OK;
8802 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8803 LCID lcid)
8805 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8807 TRACE("%p %x\n", This, lcid);
8809 This->set_lcid = lcid;
8811 return S_OK;
8814 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8815 UINT libFlags)
8817 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8819 TRACE("%p %x\n", This, libFlags);
8821 This->libflags = libFlags;
8823 return S_OK;
8826 typedef struct tagWMSFT_SegContents {
8827 DWORD len;
8828 void *data;
8829 } WMSFT_SegContents;
8831 typedef struct tagWMSFT_TLBFile {
8832 MSFT_Header header;
8833 WMSFT_SegContents typeinfo_seg;
8834 WMSFT_SegContents impfile_seg;
8835 WMSFT_SegContents impinfo_seg;
8836 WMSFT_SegContents ref_seg;
8837 WMSFT_SegContents guidhash_seg;
8838 WMSFT_SegContents guid_seg;
8839 WMSFT_SegContents namehash_seg;
8840 WMSFT_SegContents name_seg;
8841 WMSFT_SegContents string_seg;
8842 WMSFT_SegContents typdesc_seg;
8843 WMSFT_SegContents arraydesc_seg;
8844 WMSFT_SegContents custdata_seg;
8845 WMSFT_SegContents cdguids_seg;
8846 MSFT_SegDir segdir;
8847 WMSFT_SegContents aux_seg;
8848 } WMSFT_TLBFile;
8850 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8851 WMSFT_TLBFile *file)
8853 TLBString *str;
8854 UINT last_offs;
8855 char *data;
8857 file->string_seg.len = 0;
8858 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8859 int size;
8861 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8862 if (size == 0)
8863 return E_UNEXPECTED;
8865 size += sizeof(INT16);
8866 if (size % 4)
8867 size = (size + 4) & ~0x3;
8868 if (size < 8)
8869 size = 8;
8871 file->string_seg.len += size;
8873 /* temporarily use str->offset to store the length of the aligned,
8874 * converted string */
8875 str->offset = size;
8878 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8880 last_offs = 0;
8881 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8882 int size;
8884 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8885 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8886 if (size == 0) {
8887 heap_free(file->string_seg.data);
8888 return E_UNEXPECTED;
8891 *((INT16*)data) = size;
8893 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8895 size = str->offset;
8896 data += size;
8897 str->offset = last_offs;
8898 last_offs += size;
8901 return S_OK;
8904 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8905 WMSFT_TLBFile *file)
8907 TLBString *str;
8908 UINT last_offs;
8909 char *data;
8910 MSFT_NameIntro *last_intro = NULL;
8912 file->header.nametablecount = 0;
8913 file->header.nametablechars = 0;
8915 file->name_seg.len = 0;
8916 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8917 int size;
8919 size = strlenW(str->str);
8920 file->header.nametablechars += size;
8921 file->header.nametablecount++;
8923 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8924 if (size == 0)
8925 return E_UNEXPECTED;
8927 size += sizeof(MSFT_NameIntro);
8928 if (size % 4)
8929 size = (size + 4) & ~0x3;
8930 if (size < 8)
8931 size = 8;
8933 file->name_seg.len += size;
8935 /* temporarily use str->offset to store the length of the aligned,
8936 * converted string */
8937 str->offset = size;
8940 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8941 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8943 last_offs = 0;
8944 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8945 int size, hash;
8946 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8948 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8949 data + sizeof(MSFT_NameIntro),
8950 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8951 if (size == 0) {
8952 heap_free(file->name_seg.data);
8953 return E_UNEXPECTED;
8955 data[sizeof(MSFT_NameIntro) + size] = '\0';
8957 intro->hreftype = -1; /* TODO? */
8958 intro->namelen = size & 0xFF;
8959 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8960 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
8961 intro->namelen |= hash << 16;
8962 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
8963 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
8965 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8966 str->offset - size - sizeof(MSFT_NameIntro));
8968 /* update str->offset to actual value to use in other
8969 * compilation functions that require positions within
8970 * the string table */
8971 last_intro = intro;
8972 size = str->offset;
8973 data += size;
8974 str->offset = last_offs;
8975 last_offs += size;
8978 if(last_intro)
8979 last_intro->hreftype = 0; /* last one is 0? */
8981 return S_OK;
8984 static inline int hash_guid(GUID *guid)
8986 int i, hash = 0;
8988 for (i = 0; i < 8; i ++)
8989 hash ^= ((const short *)guid)[i];
8991 return hash & 0x1f;
8994 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
8996 TLBGuid *guid;
8997 MSFT_GuidEntry *entry;
8998 DWORD offs;
8999 int hash_key, *guidhashtab;
9001 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9002 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9004 entry = file->guid_seg.data;
9005 offs = 0;
9006 guidhashtab = file->guidhash_seg.data;
9007 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9008 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9009 entry->hreftype = guid->hreftype;
9011 hash_key = hash_guid(&guid->guid);
9012 entry->next_hash = guidhashtab[hash_key];
9013 guidhashtab[hash_key] = offs;
9015 guid->offset = offs;
9016 offs += sizeof(MSFT_GuidEntry);
9017 ++entry;
9020 return S_OK;
9023 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9025 VARIANT v = *value;
9026 VARTYPE arg_type = V_VT(value);
9027 int mask = 0;
9028 HRESULT hres;
9029 DWORD ret = file->custdata_seg.len;
9031 if(arg_type == VT_INT)
9032 arg_type = VT_I4;
9033 if(arg_type == VT_UINT)
9034 arg_type = VT_UI4;
9036 v = *value;
9037 if(V_VT(value) != arg_type) {
9038 hres = VariantChangeType(&v, value, 0, arg_type);
9039 if(FAILED(hres)){
9040 ERR("VariantChangeType failed: %08x\n", hres);
9041 return -1;
9045 /* Check if default value can be stored in-place */
9046 switch(arg_type){
9047 case VT_I4:
9048 case VT_UI4:
9049 mask = 0x3ffffff;
9050 if(V_UI4(&v) > 0x3ffffff)
9051 break;
9052 /* fall through */
9053 case VT_I1:
9054 case VT_UI1:
9055 case VT_BOOL:
9056 if(!mask)
9057 mask = 0xff;
9058 /* fall through */
9059 case VT_I2:
9060 case VT_UI2:
9061 if(!mask)
9062 mask = 0xffff;
9063 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9066 /* have to allocate space in custdata_seg */
9067 switch(arg_type) {
9068 case VT_I4:
9069 case VT_R4:
9070 case VT_UI4:
9071 case VT_INT:
9072 case VT_UINT:
9073 case VT_HRESULT:
9074 case VT_PTR: {
9075 /* Construct the data to be allocated */
9076 int *data;
9078 if(file->custdata_seg.data){
9079 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9080 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9081 file->custdata_seg.len += sizeof(int) * 2;
9082 }else{
9083 file->custdata_seg.len = sizeof(int) * 2;
9084 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9087 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9088 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9090 /* TODO: Check if the encoded data is already present in custdata_seg */
9092 return ret;
9095 case VT_BSTR: {
9096 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9097 char *data;
9099 if(file->custdata_seg.data){
9100 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9101 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9102 file->custdata_seg.len += len;
9103 }else{
9104 file->custdata_seg.len = len;
9105 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9108 *((unsigned short *)data) = V_VT(value);
9109 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9110 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9111 if(V_BSTR(&v)[i] <= 0x7f)
9112 data[i+6] = V_BSTR(&v)[i];
9113 else
9114 data[i+6] = '?';
9116 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9117 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9118 data[i] = 0x57;
9120 /* TODO: Check if the encoded data is already present in custdata_seg */
9122 return ret;
9124 default:
9125 FIXME("Argument type not yet handled\n");
9126 return -1;
9130 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9132 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9134 DWORD offs = file->arraydesc_seg.len;
9135 DWORD *encoded;
9136 USHORT i;
9138 /* TODO: we should check for duplicates, but that's harder because each
9139 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9140 * at the library-level) */
9142 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9143 if(!file->arraydesc_seg.data)
9144 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9145 else
9146 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9147 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9149 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9150 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9151 for(i = 0; i < desc->cDims; ++i){
9152 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9153 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9156 return offs;
9159 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9161 DWORD junk;
9162 INT16 junk2;
9163 DWORD offs = 0;
9164 DWORD encoded[2];
9165 VARTYPE vt, subtype;
9166 char *data;
9168 if(!desc)
9169 return -1;
9171 if(!out_mix)
9172 out_mix = &junk;
9173 if(!out_size)
9174 out_size = &junk2;
9176 vt = desc->vt & VT_TYPEMASK;
9178 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9179 DWORD mix;
9180 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9181 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9182 *out_mix = 0x7FFF;
9183 *out_size += 2 * sizeof(DWORD);
9184 }else if(vt == VT_CARRAY){
9185 encoded[0] = desc->vt | (0x7FFE << 16);
9186 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9187 *out_mix = 0x7FFE;
9188 }else if(vt == VT_USERDEFINED){
9189 encoded[0] = desc->vt | (0x7FFF << 16);
9190 encoded[1] = desc->u.hreftype;
9191 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9192 }else{
9193 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9195 switch(vt){
9196 case VT_INT:
9197 subtype = VT_I4;
9198 break;
9199 case VT_UINT:
9200 subtype = VT_UI4;
9201 break;
9202 case VT_VOID:
9203 subtype = VT_EMPTY;
9204 break;
9205 default:
9206 subtype = vt;
9207 break;
9210 *out_mix = subtype;
9211 return 0x80000000 | (subtype << 16) | desc->vt;
9214 data = file->typdesc_seg.data;
9215 while(offs < file->typdesc_seg.len){
9216 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9217 return offs;
9218 offs += sizeof(encoded);
9221 file->typdesc_seg.len += sizeof(encoded);
9222 if(!file->typdesc_seg.data)
9223 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9224 else
9225 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9227 memcpy(&data[offs], encoded, sizeof(encoded));
9229 return offs;
9232 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9234 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9235 DWORD ret = cdguids_seg->len, offs;
9236 MSFT_CDGuid *cdguid = cdguids_seg->data;
9237 TLBCustData *cd;
9239 if(list_empty(custdata_list))
9240 return -1;
9242 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9243 if(!cdguids_seg->data){
9244 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9245 }else
9246 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9248 offs = ret + sizeof(MSFT_CDGuid);
9249 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9250 cdguid->GuidOffset = cd->guid->offset;
9251 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9252 cdguid->next = offs;
9253 offs += sizeof(MSFT_CDGuid);
9254 ++cdguid;
9257 --cdguid;
9258 cdguid->next = -1;
9260 return ret;
9263 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9264 WMSFT_TLBFile *file)
9266 WMSFT_SegContents *aux_seg = &file->aux_seg;
9267 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9268 MSFT_VarRecord *varrecord;
9269 MSFT_FuncRecord *funcrecord;
9270 MEMBERID *memid;
9271 DWORD *name, *offsets, offs;
9273 for(i = 0; i < info->cFuncs; ++i){
9274 TLBFuncDesc *desc = &info->funcdescs[i];
9276 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9278 /* optional fields */
9279 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9280 if(!list_empty(&desc->custdata_list))
9281 recorded_size += 7 * sizeof(INT);
9282 else if(desc->HelpStringContext != 0)
9283 recorded_size += 6 * sizeof(INT);
9284 /* res9? resA? */
9285 else if(desc->Entry)
9286 recorded_size += 3 * sizeof(INT);
9287 else if(desc->HelpString)
9288 recorded_size += 2 * sizeof(INT);
9289 else if(desc->helpcontext)
9290 recorded_size += sizeof(INT);
9292 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9294 for(j = 0; j < desc->funcdesc.cParams; ++j){
9295 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9296 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9297 break;
9301 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9304 for(i = 0; i < info->cVars; ++i){
9305 TLBVarDesc *desc = &info->vardescs[i];
9307 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9309 /* optional fields */
9310 if(desc->HelpStringContext != 0)
9311 recorded_size += 5 * sizeof(INT);
9312 else if(!list_empty(&desc->custdata_list))
9313 recorded_size += 4 * sizeof(INT);
9314 /* res9? */
9315 else if(desc->HelpString)
9316 recorded_size += 2 * sizeof(INT);
9317 else if(desc->HelpContext != 0)
9318 recorded_size += sizeof(INT);
9320 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9323 if(!recorded_size && !extra_size)
9324 return ret;
9326 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9328 aux_seg->len += recorded_size + extra_size;
9330 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9332 if(aux_seg->data)
9333 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9334 else
9335 aux_seg->data = heap_alloc(aux_seg->len);
9337 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9339 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9340 offs = 0;
9342 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9343 for(i = 0; i < info->cFuncs; ++i){
9344 TLBFuncDesc *desc = &info->funcdescs[i];
9345 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9347 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9348 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9349 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9350 funcrecord->VtableOffset = desc->funcdesc.oVft;
9352 /* FKCCIC:
9353 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9354 * ^^^funckind
9355 * ^^^ ^invkind
9356 * ^has_cust_data
9357 * ^^^^callconv
9358 * ^has_param_defaults
9359 * ^oEntry_is_intresource
9361 funcrecord->FKCCIC =
9362 desc->funcdesc.funckind |
9363 (desc->funcdesc.invkind << 3) |
9364 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9365 (desc->funcdesc.callconv << 8);
9367 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9368 funcrecord->FKCCIC |= 0x2000;
9370 for(j = 0; j < desc->funcdesc.cParams; ++j){
9371 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9372 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9373 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9376 if(paramdefault_size > 0)
9377 funcrecord->FKCCIC |= 0x1000;
9379 funcrecord->nrargs = desc->funcdesc.cParams;
9380 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9382 /* optional fields */
9383 /* res9? resA? */
9384 if(!list_empty(&desc->custdata_list)){
9385 size += 7 * sizeof(INT);
9386 funcrecord->HelpContext = desc->helpcontext;
9387 if(desc->HelpString)
9388 funcrecord->oHelpString = desc->HelpString->offset;
9389 else
9390 funcrecord->oHelpString = -1;
9391 if(!desc->Entry)
9392 funcrecord->oEntry = -1;
9393 else if(IS_INTRESOURCE(desc->Entry))
9394 funcrecord->oEntry = LOWORD(desc->Entry);
9395 else
9396 funcrecord->oEntry = desc->Entry->offset;
9397 funcrecord->res9 = -1;
9398 funcrecord->resA = -1;
9399 funcrecord->HelpStringContext = desc->HelpStringContext;
9400 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9401 }else if(desc->HelpStringContext != 0){
9402 size += 6 * sizeof(INT);
9403 funcrecord->HelpContext = desc->helpcontext;
9404 if(desc->HelpString)
9405 funcrecord->oHelpString = desc->HelpString->offset;
9406 else
9407 funcrecord->oHelpString = -1;
9408 if(!desc->Entry)
9409 funcrecord->oEntry = -1;
9410 else if(IS_INTRESOURCE(desc->Entry))
9411 funcrecord->oEntry = LOWORD(desc->Entry);
9412 else
9413 funcrecord->oEntry = desc->Entry->offset;
9414 funcrecord->res9 = -1;
9415 funcrecord->resA = -1;
9416 funcrecord->HelpStringContext = desc->HelpStringContext;
9417 }else if(desc->Entry){
9418 size += 3 * sizeof(INT);
9419 funcrecord->HelpContext = desc->helpcontext;
9420 if(desc->HelpString)
9421 funcrecord->oHelpString = desc->HelpString->offset;
9422 else
9423 funcrecord->oHelpString = -1;
9424 if(!desc->Entry)
9425 funcrecord->oEntry = -1;
9426 else if(IS_INTRESOURCE(desc->Entry))
9427 funcrecord->oEntry = LOWORD(desc->Entry);
9428 else
9429 funcrecord->oEntry = desc->Entry->offset;
9430 }else if(desc->HelpString){
9431 size += 2 * sizeof(INT);
9432 funcrecord->HelpContext = desc->helpcontext;
9433 funcrecord->oHelpString = desc->HelpString->offset;
9434 }else if(desc->helpcontext){
9435 size += sizeof(INT);
9436 funcrecord->HelpContext = desc->helpcontext;
9439 paramdefault = (DWORD*)((char *)funcrecord + size);
9440 size += paramdefault_size;
9442 for(j = 0; j < desc->funcdesc.cParams; ++j){
9443 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9445 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9446 if(desc->pParamDesc[j].Name)
9447 info->oName = desc->pParamDesc[j].Name->offset;
9448 else
9449 info->oName = -1;
9450 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9452 if(paramdefault_size){
9453 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9454 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9455 else if(paramdefault_size)
9456 *paramdefault = -1;
9457 ++paramdefault;
9460 size += sizeof(MSFT_ParameterInfo);
9463 funcrecord->Info = size | (i << 16); /* is it just the index? */
9465 *offsets = offs;
9466 offs += size;
9467 ++offsets;
9469 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9472 varrecord = (MSFT_VarRecord*)funcrecord;
9473 for(i = 0; i < info->cVars; ++i){
9474 TLBVarDesc *desc = &info->vardescs[i];
9475 DWORD size = 5 * sizeof(INT);
9477 varrecord->vardescsize = sizeof(desc->vardesc);
9478 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9479 varrecord->Flags = desc->vardesc.wVarFlags;
9480 varrecord->VarKind = desc->vardesc.varkind;
9482 if(desc->vardesc.varkind == VAR_CONST){
9483 varrecord->vardescsize += sizeof(VARIANT);
9484 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9485 }else
9486 varrecord->OffsValue = desc->vardesc.u.oInst;
9488 /* res9? */
9489 if(desc->HelpStringContext != 0){
9490 size += 5 * sizeof(INT);
9491 varrecord->HelpContext = desc->HelpContext;
9492 if(desc->HelpString)
9493 varrecord->HelpString = desc->HelpString->offset;
9494 else
9495 varrecord->HelpString = -1;
9496 varrecord->res9 = -1;
9497 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9498 varrecord->HelpStringContext = desc->HelpStringContext;
9499 }else if(!list_empty(&desc->custdata_list)){
9500 size += 4 * sizeof(INT);
9501 varrecord->HelpContext = desc->HelpContext;
9502 if(desc->HelpString)
9503 varrecord->HelpString = desc->HelpString->offset;
9504 else
9505 varrecord->HelpString = -1;
9506 varrecord->res9 = -1;
9507 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9508 }else if(desc->HelpString){
9509 size += 2 * sizeof(INT);
9510 varrecord->HelpContext = desc->HelpContext;
9511 if(desc->HelpString)
9512 varrecord->HelpString = desc->HelpString->offset;
9513 else
9514 varrecord->HelpString = -1;
9515 }else if(desc->HelpContext != 0){
9516 size += sizeof(INT);
9517 varrecord->HelpContext = desc->HelpContext;
9520 varrecord->Info = size | (i << 16);
9522 *offsets = offs;
9523 offs += size;
9524 ++offsets;
9526 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9529 memid = (MEMBERID*)varrecord;
9530 for(i = 0; i < info->cFuncs; ++i){
9531 TLBFuncDesc *desc = &info->funcdescs[i];
9532 *memid = desc->funcdesc.memid;
9533 ++memid;
9535 for(i = 0; i < info->cVars; ++i){
9536 TLBVarDesc *desc = &info->vardescs[i];
9537 *memid = desc->vardesc.memid;
9538 ++memid;
9541 name = (UINT*)memid;
9542 for(i = 0; i < info->cFuncs; ++i){
9543 TLBFuncDesc *desc = &info->funcdescs[i];
9544 if(desc->Name)
9545 *name = desc->Name->offset;
9546 else
9547 *name = -1;
9548 ++name;
9550 for(i = 0; i < info->cVars; ++i){
9551 TLBVarDesc *desc = &info->vardescs[i];
9552 if(desc->Name)
9553 *name = desc->Name->offset;
9554 else
9555 *name = -1;
9556 ++name;
9559 return ret;
9562 typedef struct tagWMSFT_RefChunk {
9563 DWORD href;
9564 DWORD res04;
9565 DWORD res08;
9566 DWORD next;
9567 } WMSFT_RefChunk;
9569 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9571 DWORD offs = file->ref_seg.len, i;
9572 WMSFT_RefChunk *chunk;
9574 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9575 if(!file->ref_seg.data)
9576 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9577 else
9578 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9580 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9582 for(i = 0; i < info->cImplTypes; ++i){
9583 chunk->href = info->impltypes[i].hRef;
9584 chunk->res04 = info->impltypes[i].implflags;
9585 chunk->res08 = -1;
9586 if(i < info->cImplTypes - 1)
9587 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9588 else
9589 chunk->next = -1;
9590 ++chunk;
9593 return offs;
9596 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9598 DWORD size;
9600 size = sizeof(MSFT_TypeInfoBase);
9602 if(data){
9603 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9604 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9605 base->typekind = TKIND_DISPATCH;
9606 else
9607 base->typekind = info->typekind;
9608 base->typekind |= index << 16; /* TODO: There are some other flags here */
9609 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9610 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9611 base->res2 = 0;
9612 base->res3 = 0;
9613 base->res4 = 3;
9614 base->res5 = 0;
9615 base->cElement = (info->cVars << 16) | info->cFuncs;
9616 base->res7 = 0;
9617 base->res8 = 0;
9618 base->res9 = 0;
9619 base->resA = 0;
9620 if(info->guid)
9621 base->posguid = info->guid->offset;
9622 else
9623 base->posguid = -1;
9624 base->flags = info->wTypeFlags;
9625 if(info->Name) {
9626 base->NameOffset = info->Name->offset;
9628 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9629 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9630 }else {
9631 base->NameOffset = -1;
9633 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9634 if(info->DocString)
9635 base->docstringoffs = info->DocString->offset;
9636 else
9637 base->docstringoffs = -1;
9638 base->helpstringcontext = info->dwHelpStringContext;
9639 base->helpcontext = info->dwHelpContext;
9640 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9641 base->cImplTypes = info->cImplTypes;
9642 base->cbSizeVft = info->cbSizeVft;
9643 base->size = info->cbSizeInstance;
9644 if(info->typekind == TKIND_COCLASS){
9645 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9646 }else if(info->typekind == TKIND_ALIAS){
9647 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9648 }else if(info->typekind == TKIND_MODULE){
9649 if(info->DllName)
9650 base->datatype1 = info->DllName->offset;
9651 else
9652 base->datatype1 = -1;
9653 }else{
9654 if(info->cImplTypes > 0)
9655 base->datatype1 = info->impltypes[0].hRef;
9656 else
9657 base->datatype1 = -1;
9659 base->datatype2 = index; /* FIXME: i think there's more here */
9660 base->res18 = 0;
9661 base->res19 = -1;
9664 return size;
9667 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9669 UINT i;
9671 file->typeinfo_seg.len = 0;
9672 for(i = 0; i < This->TypeInfoCount; ++i){
9673 ITypeInfoImpl *info = This->typeinfos[i];
9674 *junk = file->typeinfo_seg.len;
9675 ++junk;
9676 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9679 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9680 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9682 file->aux_seg.len = 0;
9683 file->aux_seg.data = NULL;
9685 file->typeinfo_seg.len = 0;
9686 for(i = 0; i < This->TypeInfoCount; ++i){
9687 ITypeInfoImpl *info = This->typeinfos[i];
9688 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9689 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9693 typedef struct tagWMSFT_ImpFile {
9694 INT guid_offs;
9695 LCID lcid;
9696 DWORD version;
9697 } WMSFT_ImpFile;
9699 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9701 TLBImpLib *implib;
9702 WMSFT_ImpFile *impfile;
9703 char *data;
9704 DWORD last_offs = 0;
9706 file->impfile_seg.len = 0;
9707 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9708 int size = 0;
9710 if(implib->name){
9711 WCHAR *path = strrchrW(implib->name, '\\');
9712 if(path)
9713 ++path;
9714 else
9715 path = implib->name;
9716 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9717 if (size == 0)
9718 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9721 size += sizeof(INT16);
9722 if (size % 4)
9723 size = (size + 4) & ~0x3;
9724 if (size < 8)
9725 size = 8;
9727 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9730 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9732 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9733 int strlen = 0, size;
9735 impfile = (WMSFT_ImpFile*)data;
9736 impfile->guid_offs = implib->guid->offset;
9737 impfile->lcid = implib->lcid;
9738 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9740 data += sizeof(WMSFT_ImpFile);
9742 if(implib->name){
9743 WCHAR *path= strrchrW(implib->name, '\\');
9744 if(path)
9745 ++path;
9746 else
9747 path = implib->name;
9748 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9749 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9750 if (strlen == 0)
9751 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9754 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9756 size = strlen + sizeof(INT16);
9757 if (size % 4)
9758 size = (size + 4) & ~0x3;
9759 if (size < 8)
9760 size = 8;
9761 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9763 data += size;
9764 implib->offset = last_offs;
9765 last_offs += size + sizeof(WMSFT_ImpFile);
9769 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9771 MSFT_ImpInfo *info;
9772 TLBRefType *ref_type;
9773 UINT i = 0;
9775 WMSFT_compile_impfile(This, file);
9777 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9778 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9780 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9781 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9782 if(ref_type->index == TLB_REF_USE_GUID){
9783 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9784 info->oGuid = ref_type->guid->offset;
9785 }else
9786 info->oGuid = ref_type->index;
9787 info->oImpFile = ref_type->pImpTLInfo->offset;
9788 ++i;
9789 ++info;
9793 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9795 file->guidhash_seg.len = 0x80;
9796 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9797 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9800 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9802 file->namehash_seg.len = 0x200;
9803 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9804 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9807 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9809 if(contents && contents->len){
9810 segdir->offset = *running_offset;
9811 segdir->length = contents->len;
9812 *running_offset += segdir->length;
9813 }else{
9814 segdir->offset = -1;
9815 segdir->length = 0;
9818 /* TODO: do these ever change? */
9819 segdir->res08 = -1;
9820 segdir->res0c = 0xf;
9823 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9825 DWORD written;
9826 if(segment)
9827 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9830 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9831 DWORD file_len)
9833 DWORD i;
9834 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9836 for(i = 0; i < This->TypeInfoCount; ++i){
9837 base->memoffset += file_len;
9838 ++base;
9841 return S_OK;
9844 static void WMSFT_free_file(WMSFT_TLBFile *file)
9846 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9847 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9848 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9849 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9850 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9851 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9852 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9853 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9854 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9855 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9856 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9857 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9858 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9859 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9862 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9864 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9865 WMSFT_TLBFile file;
9866 DWORD written, junk_size, junk_offs, running_offset;
9867 BOOL br;
9868 HANDLE outfile;
9869 HRESULT hres;
9870 DWORD *junk;
9871 UINT i;
9873 TRACE("%p\n", This);
9875 for(i = 0; i < This->TypeInfoCount; ++i)
9876 if(This->typeinfos[i]->needs_layout)
9877 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9879 memset(&file, 0, sizeof(file));
9881 file.header.magic1 = 0x5446534D;
9882 file.header.magic2 = 0x00010002;
9883 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9884 file.header.lcid2 = This->set_lcid;
9885 file.header.varflags = 0x40 | This->syskind;
9886 if (This->HelpFile)
9887 file.header.varflags |= 0x10;
9888 if (This->HelpStringDll)
9889 file.header.varflags |= HELPDLLFLAG;
9890 file.header.version = (This->ver_minor << 16) | This->ver_major;
9891 file.header.flags = This->libflags;
9892 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9893 file.header.helpcontext = This->dwHelpContext;
9894 file.header.res44 = 0x20;
9895 file.header.res48 = 0x80;
9896 file.header.dispatchpos = This->dispatch_href;
9898 WMSFT_compile_namehash(This, &file);
9899 /* do name and string compilation to get offsets for other compilations */
9900 hres = WMSFT_compile_names(This, &file);
9901 if (FAILED(hres)){
9902 WMSFT_free_file(&file);
9903 return hres;
9906 hres = WMSFT_compile_strings(This, &file);
9907 if (FAILED(hres)){
9908 WMSFT_free_file(&file);
9909 return hres;
9912 WMSFT_compile_guidhash(This, &file);
9913 hres = WMSFT_compile_guids(This, &file);
9914 if (FAILED(hres)){
9915 WMSFT_free_file(&file);
9916 return hres;
9919 if(This->HelpFile)
9920 file.header.helpfile = This->HelpFile->offset;
9921 else
9922 file.header.helpfile = -1;
9924 if(This->DocString)
9925 file.header.helpstring = This->DocString->offset;
9926 else
9927 file.header.helpstring = -1;
9929 /* do some more segment compilation */
9930 file.header.nimpinfos = list_count(&This->ref_list);
9931 file.header.nrtypeinfos = This->TypeInfoCount;
9933 if(This->Name)
9934 file.header.NameOffset = This->Name->offset;
9935 else
9936 file.header.NameOffset = -1;
9938 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9940 if(This->guid)
9941 file.header.posguid = This->guid->offset;
9942 else
9943 file.header.posguid = -1;
9945 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9946 if(file.header.varflags & HELPDLLFLAG)
9947 junk_size += sizeof(DWORD);
9948 if(junk_size){
9949 junk = heap_alloc_zero(junk_size);
9950 if(file.header.varflags & HELPDLLFLAG){
9951 *junk = This->HelpStringDll->offset;
9952 junk_offs = 1;
9953 }else
9954 junk_offs = 0;
9955 }else{
9956 junk = NULL;
9957 junk_offs = 0;
9960 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9961 WMSFT_compile_impinfo(This, &file);
9963 running_offset = 0;
9965 TRACE("header at: 0x%x\n", running_offset);
9966 running_offset += sizeof(file.header);
9968 TRACE("junk at: 0x%x\n", running_offset);
9969 running_offset += junk_size;
9971 TRACE("segdir at: 0x%x\n", running_offset);
9972 running_offset += sizeof(file.segdir);
9974 TRACE("typeinfo at: 0x%x\n", running_offset);
9975 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
9977 TRACE("guidhashtab at: 0x%x\n", running_offset);
9978 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
9980 TRACE("guidtab at: 0x%x\n", running_offset);
9981 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
9983 TRACE("reftab at: 0x%x\n", running_offset);
9984 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
9986 TRACE("impinfo at: 0x%x\n", running_offset);
9987 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
9989 TRACE("impfiles at: 0x%x\n", running_offset);
9990 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
9992 TRACE("namehashtab at: 0x%x\n", running_offset);
9993 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
9995 TRACE("nametab at: 0x%x\n", running_offset);
9996 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
9998 TRACE("stringtab at: 0x%x\n", running_offset);
9999 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10001 TRACE("typdesc at: 0x%x\n", running_offset);
10002 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10004 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10005 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10007 TRACE("custdata at: 0x%x\n", running_offset);
10008 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10010 TRACE("cdguids at: 0x%x\n", running_offset);
10011 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10013 TRACE("res0e at: 0x%x\n", running_offset);
10014 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10016 TRACE("res0f at: 0x%x\n", running_offset);
10017 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10019 TRACE("aux_seg at: 0x%x\n", running_offset);
10021 WMSFT_fixup_typeinfos(This, &file, running_offset);
10023 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10024 FILE_ATTRIBUTE_NORMAL, 0);
10025 if (outfile == INVALID_HANDLE_VALUE){
10026 WMSFT_free_file(&file);
10027 heap_free(junk);
10028 return TYPE_E_IOERROR;
10031 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10032 if (!br) {
10033 WMSFT_free_file(&file);
10034 CloseHandle(outfile);
10035 heap_free(junk);
10036 return TYPE_E_IOERROR;
10039 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10040 heap_free(junk);
10041 if (!br) {
10042 WMSFT_free_file(&file);
10043 CloseHandle(outfile);
10044 return TYPE_E_IOERROR;
10047 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10048 if (!br) {
10049 WMSFT_free_file(&file);
10050 CloseHandle(outfile);
10051 return TYPE_E_IOERROR;
10054 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10055 WMSFT_write_segment(outfile, &file.guidhash_seg);
10056 WMSFT_write_segment(outfile, &file.guid_seg);
10057 WMSFT_write_segment(outfile, &file.ref_seg);
10058 WMSFT_write_segment(outfile, &file.impinfo_seg);
10059 WMSFT_write_segment(outfile, &file.impfile_seg);
10060 WMSFT_write_segment(outfile, &file.namehash_seg);
10061 WMSFT_write_segment(outfile, &file.name_seg);
10062 WMSFT_write_segment(outfile, &file.string_seg);
10063 WMSFT_write_segment(outfile, &file.typdesc_seg);
10064 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10065 WMSFT_write_segment(outfile, &file.custdata_seg);
10066 WMSFT_write_segment(outfile, &file.cdguids_seg);
10067 WMSFT_write_segment(outfile, &file.aux_seg);
10069 WMSFT_free_file(&file);
10071 CloseHandle(outfile);
10073 return S_OK;
10076 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10077 LPOLESTR name)
10079 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10080 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10081 return E_NOTIMPL;
10084 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10085 REFGUID guid, VARIANT *varVal)
10087 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10088 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
10089 return E_NOTIMPL;
10092 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10093 ULONG helpStringContext)
10095 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10096 FIXME("%p %u - stub\n", This, helpStringContext);
10097 return E_NOTIMPL;
10100 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10101 LPOLESTR filename)
10103 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10104 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10106 if (!filename)
10107 return E_INVALIDARG;
10109 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10111 return S_OK;
10114 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10115 ICreateTypeLib2_fnQueryInterface,
10116 ICreateTypeLib2_fnAddRef,
10117 ICreateTypeLib2_fnRelease,
10118 ICreateTypeLib2_fnCreateTypeInfo,
10119 ICreateTypeLib2_fnSetName,
10120 ICreateTypeLib2_fnSetVersion,
10121 ICreateTypeLib2_fnSetGuid,
10122 ICreateTypeLib2_fnSetDocString,
10123 ICreateTypeLib2_fnSetHelpFileName,
10124 ICreateTypeLib2_fnSetHelpContext,
10125 ICreateTypeLib2_fnSetLcid,
10126 ICreateTypeLib2_fnSetLibFlags,
10127 ICreateTypeLib2_fnSaveAllChanges,
10128 ICreateTypeLib2_fnDeleteTypeInfo,
10129 ICreateTypeLib2_fnSetCustData,
10130 ICreateTypeLib2_fnSetHelpStringContext,
10131 ICreateTypeLib2_fnSetHelpStringDll
10134 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10135 REFIID riid, void **object)
10137 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10139 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10142 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10144 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10146 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10149 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10151 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10153 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10156 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10157 REFGUID guid)
10159 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10161 TRACE("%p %s\n", This, debugstr_guid(guid));
10163 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10165 return S_OK;
10168 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10169 UINT typeFlags)
10171 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10172 WORD old_flags;
10173 HRESULT hres;
10175 TRACE("%p %x\n", This, typeFlags);
10177 if (typeFlags & TYPEFLAG_FDUAL) {
10178 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10179 ITypeLib *stdole;
10180 ITypeInfo *dispatch;
10181 HREFTYPE hreftype;
10182 HRESULT hres;
10184 hres = LoadTypeLib(stdole2tlb, &stdole);
10185 if(FAILED(hres))
10186 return hres;
10188 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10189 ITypeLib_Release(stdole);
10190 if(FAILED(hres))
10191 return hres;
10193 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10194 ITypeInfo_Release(dispatch);
10195 if(FAILED(hres))
10196 return hres;
10199 old_flags = This->wTypeFlags;
10200 This->wTypeFlags = typeFlags;
10202 hres = ICreateTypeInfo2_LayOut(iface);
10203 if (FAILED(hres)) {
10204 This->wTypeFlags = old_flags;
10205 return hres;
10208 return S_OK;
10211 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10212 LPOLESTR doc)
10214 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10216 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10218 if (!doc)
10219 return E_INVALIDARG;
10221 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10223 return S_OK;
10226 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10227 DWORD helpContext)
10229 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10231 TRACE("%p %d\n", This, helpContext);
10233 This->dwHelpContext = helpContext;
10235 return S_OK;
10238 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10239 WORD majorVerNum, WORD minorVerNum)
10241 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10243 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10245 This->wMajorVerNum = majorVerNum;
10246 This->wMinorVerNum = minorVerNum;
10248 return S_OK;
10251 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10252 ITypeInfo *typeInfo, HREFTYPE *refType)
10254 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10255 UINT index;
10256 ITypeLib *container;
10257 TLBRefType *ref_type;
10258 TLBImpLib *implib;
10259 TYPEATTR *typeattr;
10260 TLIBATTR *libattr;
10261 HRESULT hres;
10263 TRACE("%p %p %p\n", This, typeInfo, refType);
10265 if (!typeInfo || !refType)
10266 return E_INVALIDARG;
10268 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10269 if (FAILED(hres))
10270 return hres;
10272 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10273 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10275 ITypeLib_Release(container);
10277 *refType = target->hreftype;
10279 return S_OK;
10282 hres = ITypeLib_GetLibAttr(container, &libattr);
10283 if (FAILED(hres)) {
10284 ITypeLib_Release(container);
10285 return hres;
10288 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10289 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10290 implib->lcid == libattr->lcid &&
10291 implib->wVersionMajor == libattr->wMajorVerNum &&
10292 implib->wVersionMinor == libattr->wMinorVerNum)
10293 break;
10296 if(&implib->entry == &This->pTypeLib->implib_list){
10297 implib = heap_alloc_zero(sizeof(TLBImpLib));
10299 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10300 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10301 implib->name = SysAllocString(our_container->path);
10302 }else{
10303 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10304 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10305 if(FAILED(hres)){
10306 implib->name = NULL;
10307 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10311 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10312 implib->lcid = libattr->lcid;
10313 implib->wVersionMajor = libattr->wMajorVerNum;
10314 implib->wVersionMinor = libattr->wMinorVerNum;
10316 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10319 ITypeLib_ReleaseTLibAttr(container, libattr);
10320 ITypeLib_Release(container);
10322 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10323 if (FAILED(hres))
10324 return hres;
10326 index = 0;
10327 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10328 if(ref_type->index == TLB_REF_USE_GUID &&
10329 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10330 ref_type->tkind == typeattr->typekind)
10331 break;
10332 ++index;
10335 if(&ref_type->entry == &This->pTypeLib->ref_list){
10336 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10338 ref_type->tkind = typeattr->typekind;
10339 ref_type->pImpTLInfo = implib;
10340 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10342 ref_type->index = TLB_REF_USE_GUID;
10344 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10346 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10349 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10351 *refType = ref_type->reference | 0x1;
10353 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10354 This->pTypeLib->dispatch_href = *refType;
10356 return S_OK;
10359 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10360 UINT index, FUNCDESC *funcDesc)
10362 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10363 TLBFuncDesc tmp_func_desc, *func_desc;
10364 int buf_size, i;
10365 char *buffer;
10366 HRESULT hres;
10368 TRACE("%p %u %p\n", This, index, funcDesc);
10370 if (!funcDesc || funcDesc->oVft & 3)
10371 return E_INVALIDARG;
10373 switch (This->typekind) {
10374 case TKIND_MODULE:
10375 if (funcDesc->funckind != FUNC_STATIC)
10376 return TYPE_E_BADMODULEKIND;
10377 break;
10378 case TKIND_DISPATCH:
10379 if (funcDesc->funckind != FUNC_DISPATCH)
10380 return TYPE_E_BADMODULEKIND;
10381 break;
10382 default:
10383 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10384 return TYPE_E_BADMODULEKIND;
10387 if (index > This->cFuncs)
10388 return TYPE_E_ELEMENTNOTFOUND;
10390 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10391 !funcDesc->cParams)
10392 return TYPE_E_INCONSISTENTPROPFUNCS;
10394 #ifdef _WIN64
10395 if(This->pTypeLib->syskind == SYS_WIN64 &&
10396 funcDesc->oVft % 8 != 0)
10397 return E_INVALIDARG;
10398 #endif
10400 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10401 TLBFuncDesc_Constructor(&tmp_func_desc);
10403 tmp_func_desc.funcdesc = *funcDesc;
10405 if (tmp_func_desc.funcdesc.oVft != 0)
10406 tmp_func_desc.funcdesc.oVft |= 1;
10408 if (funcDesc->cScodes) {
10409 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10410 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10411 } else
10412 tmp_func_desc.funcdesc.lprgscode = NULL;
10414 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10415 for (i = 0; i < funcDesc->cParams; ++i) {
10416 buf_size += sizeof(ELEMDESC);
10417 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10419 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10420 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10422 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10423 if (FAILED(hres)) {
10424 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10425 heap_free(tmp_func_desc.funcdesc.lprgscode);
10426 return hres;
10429 for (i = 0; i < funcDesc->cParams; ++i) {
10430 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10431 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10432 if (FAILED(hres)) {
10433 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10434 heap_free(tmp_func_desc.funcdesc.lprgscode);
10435 return hres;
10437 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10438 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10439 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10440 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10441 if (FAILED(hres)) {
10442 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10443 heap_free(tmp_func_desc.funcdesc.lprgscode);
10444 return hres;
10449 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10451 if (This->funcdescs) {
10452 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10453 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10455 if (index < This->cFuncs) {
10456 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10457 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10458 func_desc = This->funcdescs + index;
10459 } else
10460 func_desc = This->funcdescs + This->cFuncs;
10462 /* move custdata lists to the new memory location */
10463 for(i = 0; i < This->cFuncs + 1; ++i){
10464 if(index != i){
10465 TLBFuncDesc *fd = &This->funcdescs[i];
10466 if(fd->custdata_list.prev == fd->custdata_list.next)
10467 list_init(&fd->custdata_list);
10468 else{
10469 fd->custdata_list.prev->next = &fd->custdata_list;
10470 fd->custdata_list.next->prev = &fd->custdata_list;
10474 } else
10475 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10477 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10478 list_init(&func_desc->custdata_list);
10480 ++This->cFuncs;
10482 This->needs_layout = TRUE;
10484 return S_OK;
10487 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10488 UINT index, HREFTYPE refType)
10490 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10491 TLBImplType *impl_type;
10492 HRESULT hres;
10494 TRACE("%p %u %d\n", This, index, refType);
10496 switch(This->typekind){
10497 case TKIND_COCLASS: {
10498 if (index == -1) {
10499 FIXME("Unhandled index: -1\n");
10500 return E_NOTIMPL;
10503 if(index != This->cImplTypes)
10504 return TYPE_E_ELEMENTNOTFOUND;
10506 break;
10508 case TKIND_INTERFACE:
10509 case TKIND_DISPATCH:
10510 if (index != 0 || This->cImplTypes)
10511 return TYPE_E_ELEMENTNOTFOUND;
10512 break;
10513 default:
10514 FIXME("Unimplemented typekind: %d\n", This->typekind);
10515 return E_NOTIMPL;
10518 if (This->impltypes){
10519 UINT i;
10521 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10522 sizeof(TLBImplType) * (This->cImplTypes + 1));
10524 if (index < This->cImplTypes) {
10525 memmove(This->impltypes + index + 1, This->impltypes + index,
10526 (This->cImplTypes - index) * sizeof(TLBImplType));
10527 impl_type = This->impltypes + index;
10528 } else
10529 impl_type = This->impltypes + This->cImplTypes;
10531 /* move custdata lists to the new memory location */
10532 for(i = 0; i < This->cImplTypes + 1; ++i){
10533 if(index != i){
10534 TLBImplType *it = &This->impltypes[i];
10535 if(it->custdata_list.prev == it->custdata_list.next)
10536 list_init(&it->custdata_list);
10537 else{
10538 it->custdata_list.prev->next = &it->custdata_list;
10539 it->custdata_list.next->prev = &it->custdata_list;
10543 } else
10544 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10546 memset(impl_type, 0, sizeof(TLBImplType));
10547 TLBImplType_Constructor(impl_type);
10548 impl_type->hRef = refType;
10550 ++This->cImplTypes;
10552 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10553 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10555 hres = ICreateTypeInfo2_LayOut(iface);
10556 if (FAILED(hres))
10557 return hres;
10559 return S_OK;
10562 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10563 UINT index, INT implTypeFlags)
10565 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10566 TLBImplType *impl_type = &This->impltypes[index];
10568 TRACE("%p %u %x\n", This, index, implTypeFlags);
10570 if (This->typekind != TKIND_COCLASS)
10571 return TYPE_E_BADMODULEKIND;
10573 if (index >= This->cImplTypes)
10574 return TYPE_E_ELEMENTNOTFOUND;
10576 impl_type->implflags = implTypeFlags;
10578 return S_OK;
10581 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10582 WORD alignment)
10584 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10586 TRACE("%p %d\n", This, alignment);
10588 This->cbAlignment = alignment;
10590 return S_OK;
10593 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10594 LPOLESTR schema)
10596 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10598 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10600 if (!schema)
10601 return E_INVALIDARG;
10603 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10605 This->lpstrSchema = This->Schema->str;
10607 return S_OK;
10610 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10611 UINT index, VARDESC *varDesc)
10613 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10614 TLBVarDesc *var_desc;
10616 TRACE("%p %u %p\n", This, index, varDesc);
10618 if (This->vardescs){
10619 UINT i;
10621 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10622 sizeof(TLBVarDesc) * (This->cVars + 1));
10624 if (index < This->cVars) {
10625 memmove(This->vardescs + index + 1, This->vardescs + index,
10626 (This->cVars - index) * sizeof(TLBVarDesc));
10627 var_desc = This->vardescs + index;
10628 } else
10629 var_desc = This->vardescs + This->cVars;
10631 /* move custdata lists to the new memory location */
10632 for(i = 0; i < This->cVars + 1; ++i){
10633 if(index != i){
10634 TLBVarDesc *var = &This->vardescs[i];
10635 if(var->custdata_list.prev == var->custdata_list.next)
10636 list_init(&var->custdata_list);
10637 else{
10638 var->custdata_list.prev->next = &var->custdata_list;
10639 var->custdata_list.next->prev = &var->custdata_list;
10643 } else
10644 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10646 TLBVarDesc_Constructor(var_desc);
10647 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10648 var_desc->vardesc = *var_desc->vardesc_create;
10650 ++This->cVars;
10652 This->needs_layout = TRUE;
10654 return S_OK;
10657 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10658 UINT index, LPOLESTR *names, UINT numNames)
10660 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10661 TLBFuncDesc *func_desc = &This->funcdescs[index];
10662 int i;
10664 TRACE("%p %u %p %u\n", This, index, names, numNames);
10666 if (!names)
10667 return E_INVALIDARG;
10669 if (index >= This->cFuncs || numNames == 0)
10670 return TYPE_E_ELEMENTNOTFOUND;
10672 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10673 if(numNames > func_desc->funcdesc.cParams)
10674 return TYPE_E_ELEMENTNOTFOUND;
10675 } else
10676 if(numNames > func_desc->funcdesc.cParams + 1)
10677 return TYPE_E_ELEMENTNOTFOUND;
10679 for(i = 0; i < This->cFuncs; ++i) {
10680 TLBFuncDesc *iter = &This->funcdescs[i];
10681 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10682 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10683 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10684 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10685 continue;
10686 return TYPE_E_AMBIGUOUSNAME;
10690 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10692 for (i = 1; i < numNames; ++i) {
10693 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10694 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10697 return S_OK;
10700 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10701 UINT index, LPOLESTR name)
10703 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10705 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10707 if(!name)
10708 return E_INVALIDARG;
10710 if(index >= This->cVars)
10711 return TYPE_E_ELEMENTNOTFOUND;
10713 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10714 return S_OK;
10717 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10718 TYPEDESC *tdescAlias)
10720 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10721 HRESULT hr;
10723 TRACE("%p %p\n", This, tdescAlias);
10725 if(!tdescAlias)
10726 return E_INVALIDARG;
10728 if(This->typekind != TKIND_ALIAS)
10729 return TYPE_E_BADMODULEKIND;
10731 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->cbSizeInstance, &This->cbAlignment);
10732 if(FAILED(hr))
10733 return hr;
10735 heap_free(This->tdescAlias);
10736 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10737 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10739 return S_OK;
10742 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10743 UINT index, LPOLESTR dllName, LPOLESTR procName)
10745 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10746 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10747 return E_NOTIMPL;
10750 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10751 UINT index, LPOLESTR docString)
10753 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10754 TLBFuncDesc *func_desc = &This->funcdescs[index];
10756 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10758 if(!docString)
10759 return E_INVALIDARG;
10761 if(index >= This->cFuncs)
10762 return TYPE_E_ELEMENTNOTFOUND;
10764 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10766 return S_OK;
10769 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10770 UINT index, LPOLESTR docString)
10772 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10773 TLBVarDesc *var_desc = &This->vardescs[index];
10775 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10777 if(!docString)
10778 return E_INVALIDARG;
10780 if(index >= This->cVars)
10781 return TYPE_E_ELEMENTNOTFOUND;
10783 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10785 return S_OK;
10788 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10789 UINT index, DWORD helpContext)
10791 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10792 TLBFuncDesc *func_desc = &This->funcdescs[index];
10794 TRACE("%p %u %d\n", This, index, helpContext);
10796 if(index >= This->cFuncs)
10797 return TYPE_E_ELEMENTNOTFOUND;
10799 func_desc->helpcontext = helpContext;
10801 return S_OK;
10804 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10805 UINT index, DWORD helpContext)
10807 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10808 TLBVarDesc *var_desc = &This->vardescs[index];
10810 TRACE("%p %u %d\n", This, index, helpContext);
10812 if(index >= This->cVars)
10813 return TYPE_E_ELEMENTNOTFOUND;
10815 var_desc->HelpContext = helpContext;
10817 return S_OK;
10820 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10821 UINT index, BSTR bstrMops)
10823 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10824 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10825 return E_NOTIMPL;
10828 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10829 IDLDESC *idlDesc)
10831 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10833 TRACE("%p %p\n", This, idlDesc);
10835 if (!idlDesc)
10836 return E_INVALIDARG;
10838 This->idldescType.dwReserved = idlDesc->dwReserved;
10839 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10841 return S_OK;
10844 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10846 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10847 ITypeInfo *tinfo;
10848 TLBFuncDesc *func_desc;
10849 UINT user_vft = 0, i, depth = 0;
10850 HRESULT hres = S_OK;
10852 TRACE("%p\n", This);
10854 This->needs_layout = FALSE;
10856 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10857 if (FAILED(hres))
10858 return hres;
10860 if (This->typekind == TKIND_INTERFACE) {
10861 ITypeInfo *inh;
10862 TYPEATTR *attr;
10863 HREFTYPE inh_href;
10865 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10867 if (SUCCEEDED(hres)) {
10868 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10870 if (SUCCEEDED(hres)) {
10871 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10872 if (FAILED(hres)) {
10873 ITypeInfo_Release(inh);
10874 ITypeInfo_Release(tinfo);
10875 return hres;
10877 This->cbSizeVft = attr->cbSizeVft;
10878 ITypeInfo_ReleaseTypeAttr(inh, attr);
10881 ++depth;
10882 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10883 if(SUCCEEDED(hres)){
10884 ITypeInfo *next;
10885 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10886 if(SUCCEEDED(hres)){
10887 ITypeInfo_Release(inh);
10888 inh = next;
10891 }while(SUCCEEDED(hres));
10892 hres = S_OK;
10894 ITypeInfo_Release(inh);
10895 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10896 This->cbSizeVft = 0;
10897 hres = S_OK;
10898 } else {
10899 ITypeInfo_Release(tinfo);
10900 return hres;
10902 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10903 This->cbSizeVft = 0;
10904 hres = S_OK;
10905 } else {
10906 ITypeInfo_Release(tinfo);
10907 return hres;
10909 } else if (This->typekind == TKIND_DISPATCH)
10910 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10911 else
10912 This->cbSizeVft = 0;
10914 func_desc = This->funcdescs;
10915 i = 0;
10916 while (i < This->cFuncs) {
10917 if (!(func_desc->funcdesc.oVft & 0x1))
10918 func_desc->funcdesc.oVft = This->cbSizeVft;
10920 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10921 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10923 This->cbSizeVft += This->pTypeLib->ptr_size;
10925 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10926 TLBFuncDesc *iter;
10927 UINT j = 0;
10928 BOOL reset = FALSE;
10930 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10932 iter = This->funcdescs;
10933 while (j < This->cFuncs) {
10934 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10935 if (!reset) {
10936 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10937 reset = TRUE;
10938 } else
10939 ++func_desc->funcdesc.memid;
10940 iter = This->funcdescs;
10941 j = 0;
10942 } else {
10943 ++iter;
10944 ++j;
10949 ++func_desc;
10950 ++i;
10953 if (user_vft > This->cbSizeVft)
10954 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10956 for(i = 0; i < This->cVars; ++i){
10957 TLBVarDesc *var_desc = &This->vardescs[i];
10958 if(var_desc->vardesc.memid == MEMBERID_NIL){
10959 UINT j = 0;
10960 BOOL reset = FALSE;
10961 TLBVarDesc *iter;
10963 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
10965 iter = This->vardescs;
10966 while (j < This->cVars) {
10967 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
10968 if (!reset) {
10969 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->cVars;
10970 reset = TRUE;
10971 } else
10972 ++var_desc->vardesc.memid;
10973 iter = This->vardescs;
10974 j = 0;
10975 } else {
10976 ++iter;
10977 ++j;
10983 ITypeInfo_Release(tinfo);
10984 return hres;
10987 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
10988 UINT index)
10990 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10991 FIXME("%p %u - stub\n", This, index);
10992 return E_NOTIMPL;
10995 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
10996 MEMBERID memid, INVOKEKIND invKind)
10998 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10999 FIXME("%p %x %d - stub\n", This, memid, invKind);
11000 return E_NOTIMPL;
11003 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11004 UINT index)
11006 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11007 FIXME("%p %u - stub\n", This, index);
11008 return E_NOTIMPL;
11011 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11012 MEMBERID memid)
11014 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11015 FIXME("%p %x - stub\n", This, memid);
11016 return E_NOTIMPL;
11019 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11020 UINT index)
11022 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11023 FIXME("%p %u - stub\n", This, index);
11024 return E_NOTIMPL;
11027 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11028 REFGUID guid, VARIANT *varVal)
11030 TLBGuid *tlbguid;
11032 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11034 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11036 if (!guid || !varVal)
11037 return E_INVALIDARG;
11039 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11041 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11044 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11045 UINT index, REFGUID guid, VARIANT *varVal)
11047 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11048 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11049 return E_NOTIMPL;
11052 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11053 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11055 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11056 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11057 return E_NOTIMPL;
11060 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11061 UINT index, REFGUID guid, VARIANT *varVal)
11063 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11064 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11065 return E_NOTIMPL;
11068 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11069 UINT index, REFGUID guid, VARIANT *varVal)
11071 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11072 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11073 return E_NOTIMPL;
11076 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11077 ULONG helpStringContext)
11079 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11081 TRACE("%p %u\n", This, helpStringContext);
11083 This->dwHelpStringContext = helpStringContext;
11085 return S_OK;
11088 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11089 UINT index, ULONG helpStringContext)
11091 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11092 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11093 return E_NOTIMPL;
11096 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11097 UINT index, ULONG helpStringContext)
11099 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11100 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11101 return E_NOTIMPL;
11104 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11106 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11107 FIXME("%p - stub\n", This);
11108 return E_NOTIMPL;
11111 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11112 LPOLESTR name)
11114 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11116 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11118 if (!name)
11119 return E_INVALIDARG;
11121 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11123 return S_OK;
11126 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11127 ICreateTypeInfo2_fnQueryInterface,
11128 ICreateTypeInfo2_fnAddRef,
11129 ICreateTypeInfo2_fnRelease,
11130 ICreateTypeInfo2_fnSetGuid,
11131 ICreateTypeInfo2_fnSetTypeFlags,
11132 ICreateTypeInfo2_fnSetDocString,
11133 ICreateTypeInfo2_fnSetHelpContext,
11134 ICreateTypeInfo2_fnSetVersion,
11135 ICreateTypeInfo2_fnAddRefTypeInfo,
11136 ICreateTypeInfo2_fnAddFuncDesc,
11137 ICreateTypeInfo2_fnAddImplType,
11138 ICreateTypeInfo2_fnSetImplTypeFlags,
11139 ICreateTypeInfo2_fnSetAlignment,
11140 ICreateTypeInfo2_fnSetSchema,
11141 ICreateTypeInfo2_fnAddVarDesc,
11142 ICreateTypeInfo2_fnSetFuncAndParamNames,
11143 ICreateTypeInfo2_fnSetVarName,
11144 ICreateTypeInfo2_fnSetTypeDescAlias,
11145 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11146 ICreateTypeInfo2_fnSetFuncDocString,
11147 ICreateTypeInfo2_fnSetVarDocString,
11148 ICreateTypeInfo2_fnSetFuncHelpContext,
11149 ICreateTypeInfo2_fnSetVarHelpContext,
11150 ICreateTypeInfo2_fnSetMops,
11151 ICreateTypeInfo2_fnSetTypeIdldesc,
11152 ICreateTypeInfo2_fnLayOut,
11153 ICreateTypeInfo2_fnDeleteFuncDesc,
11154 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11155 ICreateTypeInfo2_fnDeleteVarDesc,
11156 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11157 ICreateTypeInfo2_fnDeleteImplType,
11158 ICreateTypeInfo2_fnSetCustData,
11159 ICreateTypeInfo2_fnSetFuncCustData,
11160 ICreateTypeInfo2_fnSetParamCustData,
11161 ICreateTypeInfo2_fnSetVarCustData,
11162 ICreateTypeInfo2_fnSetImplTypeCustData,
11163 ICreateTypeInfo2_fnSetHelpStringContext,
11164 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11165 ICreateTypeInfo2_fnSetVarHelpStringContext,
11166 ICreateTypeInfo2_fnInvalidate,
11167 ICreateTypeInfo2_fnSetName
11170 /******************************************************************************
11171 * ClearCustData (OLEAUT32.171)
11173 * Clear a custom data type's data.
11175 * PARAMS
11176 * lpCust [I] The custom data type instance
11178 * RETURNS
11179 * Nothing.
11181 void WINAPI ClearCustData(CUSTDATA *lpCust)
11183 if (lpCust && lpCust->cCustData)
11185 if (lpCust->prgCustData)
11187 DWORD i;
11189 for (i = 0; i < lpCust->cCustData; i++)
11190 VariantClear(&lpCust->prgCustData[i].varValue);
11192 CoTaskMemFree(lpCust->prgCustData);
11193 lpCust->prgCustData = NULL;
11195 lpCust->cCustData = 0;