services: Check for services without lpBinaryPathName in get_winedevice_process.
[wine.git] / dlls / oleaut32 / typelib.c
blob4fdfbeb54429e806b60a15ffa5f33cd29ed9459b
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
45 * behaviour.
46 * -. lousy fatal error handling
50 #include "config.h"
51 #include "wine/port.h"
53 #include <stdlib.h>
54 #include <string.h>
55 #include <stdarg.h>
56 #include <stdio.h>
57 #include <ctype.h>
59 #define COBJMACROS
60 #define NONAMELESSUNION
62 #include "winerror.h"
63 #include "windef.h"
64 #include "winbase.h"
65 #include "winnls.h"
66 #include "winreg.h"
67 #include "winuser.h"
68 #include "winternl.h"
69 #include "lzexpand.h"
71 #include "wine/unicode.h"
72 #include "objbase.h"
73 #include "typelib.h"
74 #include "wine/debug.h"
75 #include "variant.h"
76 #include "wine/list.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib);
81 typedef struct
83 WORD offset;
84 WORD length;
85 WORD flags;
86 WORD id;
87 WORD handle;
88 WORD usage;
89 } NE_NAMEINFO;
91 typedef struct
93 WORD type_id; /* Type identifier */
94 WORD count; /* Number of resources of this type */
95 DWORD resloader; /* SetResourceHandler() */
97 * Name info array.
99 } NE_TYPEINFO;
101 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
102 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
103 static void TLB_FreeVarDesc(VARDESC*);
105 /****************************************************************************
106 * FromLExxx
108 * Takes p_iVal (which is in little endian) and returns it
109 * in the host machine's byte order.
111 #ifdef WORDS_BIGENDIAN
112 static WORD FromLEWord(WORD p_iVal)
114 return (((p_iVal & 0x00FF) << 8) |
115 ((p_iVal & 0xFF00) >> 8));
119 static DWORD FromLEDWord(DWORD p_iVal)
121 return (((p_iVal & 0x000000FF) << 24) |
122 ((p_iVal & 0x0000FF00) << 8) |
123 ((p_iVal & 0x00FF0000) >> 8) |
124 ((p_iVal & 0xFF000000) >> 24));
126 #else
127 #define FromLEWord(X) (X)
128 #define FromLEDWord(X) (X)
129 #endif
131 #define DISPATCH_HREF_OFFSET 0x01000000
132 #define DISPATCH_HREF_MASK 0xff000000
134 /****************************************************************************
135 * FromLExxx
137 * Fix byte order in any structure if necessary
139 #ifdef WORDS_BIGENDIAN
140 static void FromLEWords(void *p_Val, int p_iSize)
142 WORD *Val = p_Val;
144 p_iSize /= sizeof(WORD);
146 while (p_iSize) {
147 *Val = FromLEWord(*Val);
148 Val++;
149 p_iSize--;
154 static void FromLEDWords(void *p_Val, int p_iSize)
156 DWORD *Val = p_Val;
158 p_iSize /= sizeof(DWORD);
160 while (p_iSize) {
161 *Val = FromLEDWord(*Val);
162 Val++;
163 p_iSize--;
166 #else
167 #define FromLEWords(X,Y) /*nothing*/
168 #define FromLEDWords(X,Y) /*nothing*/
169 #endif
172 * Find a typelib key which matches a requested maj.min version.
174 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
176 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
177 WCHAR buffer[60];
178 char key_name[16];
179 DWORD len, i;
180 INT best_maj = -1, best_min = -1;
181 HKEY hkey;
183 memcpy( buffer, typelibW, sizeof(typelibW) );
184 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
186 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
187 return FALSE;
189 len = sizeof(key_name);
190 i = 0;
191 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
193 INT v_maj, v_min;
195 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
197 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
199 if (*wMaj == 0xffff && *wMin == 0xffff)
201 if (v_maj > best_maj) best_maj = v_maj;
202 if (v_min > best_min) best_min = v_min;
204 else if (*wMaj == v_maj)
206 best_maj = v_maj;
208 if (*wMin == v_min)
210 best_min = v_min;
211 break; /* exact match */
213 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
216 len = sizeof(key_name);
218 RegCloseKey( hkey );
220 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
222 if (*wMaj == 0xffff && *wMin == 0xffff)
224 if (best_maj >= 0 && best_min >= 0)
226 *wMaj = best_maj;
227 *wMin = best_min;
228 return TRUE;
232 if (*wMaj == best_maj && best_min >= 0)
234 *wMin = best_min;
235 return TRUE;
237 return FALSE;
240 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
241 /* buffer must be at least 60 characters long */
242 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
244 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
245 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
247 memcpy( buffer, TypelibW, sizeof(TypelibW) );
248 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
249 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
250 return buffer;
253 /* get the path of an interface key, in the form "Interface\\<guid>" */
254 /* buffer must be at least 50 characters long */
255 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
257 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
259 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
260 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
261 return buffer;
264 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
265 /* buffer must be at least 16 characters long */
266 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
268 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
269 static const WCHAR win16W[] = {'w','i','n','1','6',0};
270 static const WCHAR win32W[] = {'w','i','n','3','2',0};
271 static const WCHAR win64W[] = {'w','i','n','6','4',0};
273 sprintfW( buffer, LcidFormatW, lcid );
274 switch(syskind)
276 case SYS_WIN16: strcatW( buffer, win16W ); break;
277 case SYS_WIN32: strcatW( buffer, win32W ); break;
278 case SYS_WIN64: strcatW( buffer, win64W ); break;
279 default:
280 TRACE("Typelib is for unsupported syskind %i\n", syskind);
281 return NULL;
283 return buffer;
286 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
288 struct tlibredirect_data
290 ULONG size;
291 DWORD res;
292 ULONG name_len;
293 ULONG name_offset;
294 LANGID langid;
295 WORD flags;
296 ULONG help_len;
297 ULONG help_offset;
298 WORD major_version;
299 WORD minor_version;
302 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
303 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
304 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
306 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
307 LCID myLCID = lcid;
308 HKEY hkey;
309 WCHAR buffer[60];
310 WCHAR Path[MAX_PATH];
311 LONG res;
313 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
315 if (redir)
317 ACTCTX_SECTION_KEYED_DATA data;
319 data.cbSize = sizeof(data);
320 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
322 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
323 WCHAR *nameW;
324 DWORD len;
326 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
327 return TYPE_E_LIBNOTREGISTERED;
329 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
330 len = SearchPathW( NULL, nameW, NULL, sizeof(Path)/sizeof(WCHAR), Path, NULL );
331 if (!len) return TYPE_E_LIBNOTREGISTERED;
333 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
334 *path = SysAllocString( Path );
335 return S_OK;
339 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
340 get_typelib_key( guid, wMaj, wMin, buffer );
342 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
343 if (res == ERROR_FILE_NOT_FOUND)
345 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
346 return TYPE_E_LIBNOTREGISTERED;
348 else if (res != ERROR_SUCCESS)
350 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
351 return TYPE_E_REGISTRYACCESS;
354 while (hr != S_OK)
356 LONG dwPathLen = sizeof(Path);
358 get_lcid_subkey( myLCID, syskind, buffer );
360 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
362 if (!lcid)
363 break;
364 else if (myLCID == lcid)
366 /* try with sub-langid */
367 myLCID = SUBLANGID(lcid);
369 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
371 /* try with system langid */
372 myLCID = 0;
374 else
376 break;
379 else
381 *path = SysAllocString( Path );
382 hr = S_OK;
385 RegCloseKey( hkey );
386 TRACE_(typelib)("-- 0x%08x\n", hr);
387 return hr;
390 /****************************************************************************
391 * QueryPathOfRegTypeLib [OLEAUT32.164]
393 * Gets the path to a registered type library.
395 * PARAMS
396 * guid [I] referenced guid
397 * wMaj [I] major version
398 * wMin [I] minor version
399 * lcid [I] locale id
400 * path [O] path of typelib
402 * RETURNS
403 * Success: S_OK.
404 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
405 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
406 * opened.
408 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
410 BOOL redir = TRUE;
411 #ifdef _WIN64
412 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
413 if(SUCCEEDED(hres))
414 return hres;
415 redir = FALSE;
416 #endif
417 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
420 /******************************************************************************
421 * CreateTypeLib [OLEAUT32.160] creates a typelib
423 * RETURNS
424 * Success: S_OK
425 * Failure: Status
427 HRESULT WINAPI CreateTypeLib(
428 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
430 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
431 return E_FAIL;
434 /******************************************************************************
435 * LoadTypeLib [OLEAUT32.161]
437 * Loads a type library
439 * PARAMS
440 * szFile [I] Name of file to load from.
441 * pptLib [O] Pointer that receives ITypeLib object on success.
443 * RETURNS
444 * Success: S_OK
445 * Failure: Status
447 * SEE
448 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
450 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
452 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
453 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
456 /******************************************************************************
457 * LoadTypeLibEx [OLEAUT32.183]
459 * Loads and optionally registers a type library
461 * RETURNS
462 * Success: S_OK
463 * Failure: Status
465 HRESULT WINAPI LoadTypeLibEx(
466 LPCOLESTR szFile, /* [in] Name of file to load from */
467 REGKIND regkind, /* [in] Specify kind of registration */
468 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
470 WCHAR szPath[MAX_PATH+1];
471 HRESULT res;
473 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
475 *pptLib = NULL;
477 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
479 if (SUCCEEDED(res))
480 switch(regkind)
482 case REGKIND_DEFAULT:
483 /* don't register typelibs supplied with full path. Experimentation confirms the following */
484 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
485 (szFile[0] && (szFile[1] == ':'))) break;
486 /* else fall-through */
488 case REGKIND_REGISTER:
489 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
491 ITypeLib_Release(*pptLib);
492 *pptLib = 0;
494 break;
495 case REGKIND_NONE:
496 break;
499 TRACE(" returns %08x\n",res);
500 return res;
503 /******************************************************************************
504 * LoadRegTypeLib [OLEAUT32.162]
506 * Loads a registered type library.
508 * PARAMS
509 * rguid [I] GUID of the registered type library.
510 * wVerMajor [I] major version.
511 * wVerMinor [I] minor version.
512 * lcid [I] locale ID.
513 * ppTLib [O] pointer that receives an ITypeLib object on success.
515 * RETURNS
516 * Success: S_OK.
517 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
518 * LoadTypeLib.
520 HRESULT WINAPI LoadRegTypeLib(
521 REFGUID rguid,
522 WORD wVerMajor,
523 WORD wVerMinor,
524 LCID lcid,
525 ITypeLib **ppTLib)
527 BSTR bstr=NULL;
528 HRESULT res;
530 *ppTLib = NULL;
532 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
534 if(SUCCEEDED(res))
536 res= LoadTypeLib(bstr, ppTLib);
537 SysFreeString(bstr);
539 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
541 TLIBATTR *attr;
543 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
544 if (res == S_OK)
546 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
547 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
549 if (mismatch)
551 ITypeLib_Release(*ppTLib);
552 *ppTLib = NULL;
553 res = TYPE_E_LIBNOTREGISTERED;
559 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
561 return res;
565 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
566 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
567 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
568 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
569 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
570 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
572 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
574 WCHAR keyName[60];
575 HKEY key, subKey;
577 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
578 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
579 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
581 get_interface_key( &tattr->guid, keyName );
582 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
583 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
585 if (name)
586 RegSetValueExW(key, NULL, 0, REG_SZ,
587 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
589 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
590 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
591 RegSetValueExW(subKey, NULL, 0, REG_SZ,
592 (const BYTE *)PSOA, sizeof PSOA);
593 RegCloseKey(subKey);
596 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
597 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
598 RegSetValueExW(subKey, NULL, 0, REG_SZ,
599 (const BYTE *)PSOA, sizeof PSOA);
600 RegCloseKey(subKey);
603 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
604 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
606 WCHAR buffer[40];
607 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
608 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
610 StringFromGUID2(&libattr->guid, buffer, 40);
611 RegSetValueExW(subKey, NULL, 0, REG_SZ,
612 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
613 sprintfW(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
614 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
615 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
616 RegCloseKey(subKey);
619 RegCloseKey(key);
623 /******************************************************************************
624 * RegisterTypeLib [OLEAUT32.163]
625 * Adds information about a type library to the System Registry
626 * NOTES
627 * Docs: ITypeLib FAR * ptlib
628 * Docs: OLECHAR FAR* szFullPath
629 * Docs: OLECHAR FAR* szHelpDir
631 * RETURNS
632 * Success: S_OK
633 * Failure: Status
635 HRESULT WINAPI RegisterTypeLib(
636 ITypeLib * ptlib, /* [in] Pointer to the library*/
637 OLECHAR * szFullPath, /* [in] full Path of the library*/
638 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
639 may be NULL*/
641 HRESULT res;
642 TLIBATTR *attr;
643 WCHAR keyName[60];
644 WCHAR tmp[16];
645 HKEY key, subKey;
646 UINT types, tidx;
647 TYPEKIND kind;
648 DWORD disposition;
650 if (ptlib == NULL || szFullPath == NULL)
651 return E_INVALIDARG;
653 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
654 return E_FAIL;
656 #ifndef _WIN64
657 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
658 #endif
660 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
662 res = S_OK;
663 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
664 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
666 LPOLESTR doc;
668 /* Set the human-readable name of the typelib */
669 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
670 res = E_FAIL;
671 else if (doc)
673 if (RegSetValueExW(key, NULL, 0, REG_SZ,
674 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
675 res = E_FAIL;
677 SysFreeString(doc);
680 /* Make up the name of the typelib path subkey */
681 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
683 /* Create the typelib path subkey */
684 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
685 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
687 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
688 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
689 res = E_FAIL;
691 RegCloseKey(subKey);
693 else
694 res = E_FAIL;
696 /* Create the flags subkey */
697 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
698 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
700 /* FIXME: is %u correct? */
701 static const WCHAR formatW[] = {'%','u',0};
702 WCHAR buf[20];
703 sprintfW(buf, formatW, attr->wLibFlags);
704 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
705 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
706 res = E_FAIL;
708 RegCloseKey(subKey);
710 else
711 res = E_FAIL;
713 /* create the helpdir subkey */
714 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
715 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
717 BOOL freeHelpDir = FALSE;
718 OLECHAR* pIndexStr;
720 /* if we created a new key, and helpDir was null, set the helpdir
721 to the directory which contains the typelib. However,
722 if we just opened an existing key, we leave the helpdir alone */
723 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
724 szHelpDir = SysAllocString(szFullPath);
725 pIndexStr = strrchrW(szHelpDir, '\\');
726 if (pIndexStr) {
727 *pIndexStr = 0;
729 freeHelpDir = TRUE;
732 /* if we have an szHelpDir, set it! */
733 if (szHelpDir != NULL) {
734 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
735 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
736 res = E_FAIL;
740 /* tidy up */
741 if (freeHelpDir) SysFreeString(szHelpDir);
742 RegCloseKey(subKey);
744 } else {
745 res = E_FAIL;
748 RegCloseKey(key);
750 else
751 res = E_FAIL;
753 /* register OLE Automation-compatible interfaces for this typelib */
754 types = ITypeLib_GetTypeInfoCount(ptlib);
755 for (tidx=0; tidx<types; tidx++) {
756 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
757 LPOLESTR name = NULL;
758 ITypeInfo *tinfo = NULL;
760 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
762 switch (kind) {
763 case TKIND_INTERFACE:
764 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
765 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
766 break;
768 case TKIND_DISPATCH:
769 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
770 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
771 break;
773 default:
774 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
775 break;
778 if (tinfo) {
779 TYPEATTR *tattr = NULL;
780 ITypeInfo_GetTypeAttr(tinfo, &tattr);
782 if (tattr) {
783 TRACE_(typelib)("guid=%s, flags=%04x (",
784 debugstr_guid(&tattr->guid),
785 tattr->wTypeFlags);
787 if (TRACE_ON(typelib)) {
788 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
789 XX(FAPPOBJECT);
790 XX(FCANCREATE);
791 XX(FLICENSED);
792 XX(FPREDECLID);
793 XX(FHIDDEN);
794 XX(FCONTROL);
795 XX(FDUAL);
796 XX(FNONEXTENSIBLE);
797 XX(FOLEAUTOMATION);
798 XX(FRESTRICTED);
799 XX(FAGGREGATABLE);
800 XX(FREPLACEABLE);
801 XX(FDISPATCHABLE);
802 XX(FREVERSEBIND);
803 XX(FPROXY);
804 #undef XX
805 MESSAGE("\n");
808 /* Register all dispinterfaces (which includes dual interfaces) and
809 oleautomation interfaces */
810 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
811 kind == TKIND_DISPATCH)
813 BOOL is_wow64;
814 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
816 /* register interface<->typelib coupling */
817 TLB_register_interface(attr, name, tattr, 0);
819 /* register TLBs into the opposite registry view, too */
820 if(opposite == KEY_WOW64_32KEY ||
821 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
822 TLB_register_interface(attr, name, tattr, opposite);
825 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
828 ITypeInfo_Release(tinfo);
831 SysFreeString(name);
835 ITypeLib_ReleaseTLibAttr(ptlib, attr);
837 return res;
840 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
842 WCHAR subKeyName[50];
843 HKEY subKey;
845 /* the path to the type */
846 get_interface_key( guid, subKeyName );
848 /* Delete its bits */
849 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
850 return;
852 RegDeleteKeyW(subKey, ProxyStubClsidW);
853 RegDeleteKeyW(subKey, ProxyStubClsid32W);
854 RegDeleteKeyW(subKey, TypeLibW);
855 RegCloseKey(subKey);
856 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
859 /******************************************************************************
860 * UnRegisterTypeLib [OLEAUT32.186]
861 * Removes information about a type library from the System Registry
862 * NOTES
864 * RETURNS
865 * Success: S_OK
866 * Failure: Status
868 HRESULT WINAPI UnRegisterTypeLib(
869 REFGUID libid, /* [in] Guid of the library */
870 WORD wVerMajor, /* [in] major version */
871 WORD wVerMinor, /* [in] minor version */
872 LCID lcid, /* [in] locale id */
873 SYSKIND syskind)
875 BSTR tlibPath = NULL;
876 DWORD tmpLength;
877 WCHAR keyName[60];
878 WCHAR subKeyName[50];
879 int result = S_OK;
880 DWORD i = 0;
881 BOOL deleteOtherStuff;
882 HKEY key = NULL;
883 TYPEATTR* typeAttr = NULL;
884 TYPEKIND kind;
885 ITypeInfo* typeInfo = NULL;
886 ITypeLib* typeLib = NULL;
887 int numTypes;
889 TRACE("(IID: %s)\n",debugstr_guid(libid));
891 /* Create the path to the key */
892 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
894 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
896 TRACE("Unsupported syskind %i\n", syskind);
897 result = E_INVALIDARG;
898 goto end;
901 /* get the path to the typelib on disk */
902 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
903 result = E_INVALIDARG;
904 goto end;
907 /* Try and open the key to the type library. */
908 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
909 result = E_INVALIDARG;
910 goto end;
913 /* Try and load the type library */
914 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
915 result = TYPE_E_INVALIDSTATE;
916 goto end;
919 /* remove any types registered with this typelib */
920 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
921 for (i=0; i<numTypes; i++) {
922 /* get the kind of type */
923 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
924 goto enddeleteloop;
927 /* skip non-interfaces, and get type info for the type */
928 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
929 goto enddeleteloop;
931 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
932 goto enddeleteloop;
934 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
935 goto enddeleteloop;
938 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
939 kind == TKIND_DISPATCH)
941 BOOL is_wow64;
942 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
944 TLB_unregister_interface(&typeAttr->guid, 0);
946 /* unregister TLBs into the opposite registry view, too */
947 if(opposite == KEY_WOW64_32KEY ||
948 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
949 TLB_unregister_interface(&typeAttr->guid, opposite);
953 enddeleteloop:
954 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
955 typeAttr = NULL;
956 if (typeInfo) ITypeInfo_Release(typeInfo);
957 typeInfo = NULL;
960 /* Now, delete the type library path subkey */
961 get_lcid_subkey( lcid, syskind, subKeyName );
962 RegDeleteKeyW(key, subKeyName);
963 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
964 RegDeleteKeyW(key, subKeyName);
966 /* check if there is anything besides the FLAGS/HELPDIR keys.
967 If there is, we don't delete them */
968 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
969 deleteOtherStuff = TRUE;
970 i = 0;
971 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
972 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
974 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
975 if (!strcmpW(subKeyName, FLAGSW)) continue;
976 if (!strcmpW(subKeyName, HELPDIRW)) continue;
977 deleteOtherStuff = FALSE;
978 break;
981 /* only delete the other parts of the key if we're absolutely sure */
982 if (deleteOtherStuff) {
983 RegDeleteKeyW(key, FLAGSW);
984 RegDeleteKeyW(key, HELPDIRW);
985 RegCloseKey(key);
986 key = NULL;
988 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
989 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
990 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
993 end:
994 SysFreeString(tlibPath);
995 if (typeLib) ITypeLib_Release(typeLib);
996 if (key) RegCloseKey(key);
997 return result;
1000 /******************************************************************************
1001 * RegisterTypeLibForUser [OLEAUT32.442]
1002 * Adds information about a type library to the user registry
1003 * NOTES
1004 * Docs: ITypeLib FAR * ptlib
1005 * Docs: OLECHAR FAR* szFullPath
1006 * Docs: OLECHAR FAR* szHelpDir
1008 * RETURNS
1009 * Success: S_OK
1010 * Failure: Status
1012 HRESULT WINAPI RegisterTypeLibForUser(
1013 ITypeLib * ptlib, /* [in] Pointer to the library*/
1014 OLECHAR * szFullPath, /* [in] full Path of the library*/
1015 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1016 may be NULL*/
1018 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1019 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1020 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1023 /******************************************************************************
1024 * UnRegisterTypeLibForUser [OLEAUT32.443]
1025 * Removes information about a type library from the user registry
1027 * RETURNS
1028 * Success: S_OK
1029 * Failure: Status
1031 HRESULT WINAPI UnRegisterTypeLibForUser(
1032 REFGUID libid, /* [in] GUID of the library */
1033 WORD wVerMajor, /* [in] major version */
1034 WORD wVerMinor, /* [in] minor version */
1035 LCID lcid, /* [in] locale id */
1036 SYSKIND syskind)
1038 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1039 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1040 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1043 /*======================= ITypeLib implementation =======================*/
1045 typedef struct tagTLBGuid {
1046 GUID guid;
1047 INT hreftype;
1048 UINT offset;
1049 struct list entry;
1050 } TLBGuid;
1052 typedef struct tagTLBCustData
1054 TLBGuid *guid;
1055 VARIANT data;
1056 struct list entry;
1057 } TLBCustData;
1059 /* data structure for import typelibs */
1060 typedef struct tagTLBImpLib
1062 int offset; /* offset in the file (MSFT)
1063 offset in nametable (SLTG)
1064 just used to identify library while reading
1065 data from file */
1066 TLBGuid *guid; /* libid */
1067 BSTR name; /* name */
1069 LCID lcid; /* lcid of imported typelib */
1071 WORD wVersionMajor; /* major version number */
1072 WORD wVersionMinor; /* minor version number */
1074 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1075 NULL if not yet loaded */
1076 struct list entry;
1077 } TLBImpLib;
1079 typedef struct tagTLBString {
1080 BSTR str;
1081 UINT offset;
1082 struct list entry;
1083 } TLBString;
1085 /* internal ITypeLib data */
1086 typedef struct tagITypeLibImpl
1088 ITypeLib2 ITypeLib2_iface;
1089 ITypeComp ITypeComp_iface;
1090 ICreateTypeLib2 ICreateTypeLib2_iface;
1091 LONG ref;
1092 TLBGuid *guid;
1093 LCID lcid;
1094 SYSKIND syskind;
1095 int ptr_size;
1096 WORD ver_major;
1097 WORD ver_minor;
1098 WORD libflags;
1099 LCID set_lcid;
1101 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1102 * exported to the application as a UNICODE string.
1104 struct list string_list;
1105 struct list name_list;
1106 struct list guid_list;
1108 const TLBString *Name;
1109 const TLBString *DocString;
1110 const TLBString *HelpFile;
1111 const TLBString *HelpStringDll;
1112 DWORD dwHelpContext;
1113 int TypeInfoCount; /* nr of typeinfo's in librarry */
1114 struct tagITypeInfoImpl **typeinfos;
1115 struct list custdata_list;
1116 struct list implib_list;
1117 int ctTypeDesc; /* number of items in type desc array */
1118 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1119 library. Only used while reading MSFT
1120 typelibs */
1121 struct list ref_list; /* list of ref types in this typelib */
1122 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1125 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1126 struct list entry;
1127 WCHAR *path;
1128 INT index;
1129 } ITypeLibImpl;
1131 static const ITypeLib2Vtbl tlbvt;
1132 static const ITypeCompVtbl tlbtcvt;
1133 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1135 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1137 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1140 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1142 return impl_from_ITypeLib2((ITypeLib2*)iface);
1145 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1147 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1150 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1152 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1155 /* ITypeLib methods */
1156 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1157 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1159 /*======================= ITypeInfo implementation =======================*/
1161 /* data for referenced types */
1162 typedef struct tagTLBRefType
1164 INT index; /* Type index for internal ref or for external ref
1165 it the format is SLTG. -2 indicates to
1166 use guid */
1168 TYPEKIND tkind;
1169 TLBGuid *guid; /* guid of the referenced type */
1170 /* if index == TLB_REF_USE_GUID */
1172 HREFTYPE reference; /* The href of this ref */
1173 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1174 TLB_REF_INTERNAL for internal refs
1175 TLB_REF_NOT_FOUND for broken refs */
1177 struct list entry;
1178 } TLBRefType;
1180 #define TLB_REF_USE_GUID -2
1182 #define TLB_REF_INTERNAL (void*)-2
1183 #define TLB_REF_NOT_FOUND (void*)-1
1185 /* internal Parameter data */
1186 typedef struct tagTLBParDesc
1188 const TLBString *Name;
1189 struct list custdata_list;
1190 } TLBParDesc;
1192 /* internal Function data */
1193 typedef struct tagTLBFuncDesc
1195 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1196 const TLBString *Name; /* the name of this function */
1197 TLBParDesc *pParamDesc; /* array with param names and custom data */
1198 int helpcontext;
1199 int HelpStringContext;
1200 const TLBString *HelpString;
1201 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1202 struct list custdata_list;
1203 } TLBFuncDesc;
1205 /* internal Variable data */
1206 typedef struct tagTLBVarDesc
1208 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1209 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1210 const TLBString *Name; /* the name of this variable */
1211 int HelpContext;
1212 int HelpStringContext;
1213 const TLBString *HelpString;
1214 struct list custdata_list;
1215 } TLBVarDesc;
1217 /* internal implemented interface data */
1218 typedef struct tagTLBImplType
1220 HREFTYPE hRef; /* hRef of interface */
1221 int implflags; /* IMPLFLAG_*s */
1222 struct list custdata_list;
1223 } TLBImplType;
1225 /* internal TypeInfo data */
1226 typedef struct tagITypeInfoImpl
1228 ITypeInfo2 ITypeInfo2_iface;
1229 ITypeComp ITypeComp_iface;
1230 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1231 LONG ref;
1232 BOOL not_attached_to_typelib;
1233 BOOL needs_layout;
1235 TLBGuid *guid;
1236 TYPEATTR typeattr;
1237 TYPEDESC *tdescAlias;
1239 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1240 int index; /* index in this typelib; */
1241 HREFTYPE hreftype; /* hreftype for app object binding */
1242 /* type libs seem to store the doc strings in ascii
1243 * so why should we do it in unicode?
1245 const TLBString *Name;
1246 const TLBString *DocString;
1247 const TLBString *DllName;
1248 const TLBString *Schema;
1249 DWORD dwHelpContext;
1250 DWORD dwHelpStringContext;
1252 /* functions */
1253 TLBFuncDesc *funcdescs;
1255 /* variables */
1256 TLBVarDesc *vardescs;
1258 /* Implemented Interfaces */
1259 TLBImplType *impltypes;
1261 struct list *pcustdata_list;
1262 struct list custdata_list;
1263 } ITypeInfoImpl;
1265 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1267 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1270 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1272 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1275 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1277 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1280 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1282 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1285 static const ITypeInfo2Vtbl tinfvt;
1286 static const ITypeCompVtbl tcompvt;
1287 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1289 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1290 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1292 typedef struct tagTLBContext
1294 unsigned int oStart; /* start of TLB in file */
1295 unsigned int pos; /* current pos */
1296 unsigned int length; /* total length */
1297 void *mapping; /* memory mapping */
1298 MSFT_SegDir * pTblDir;
1299 ITypeLibImpl* pLibInfo;
1300 } TLBContext;
1303 static inline BSTR TLB_get_bstr(const TLBString *str)
1305 return str != NULL ? str->str : NULL;
1308 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1310 if(!str)
1311 return 1;
1312 return memcmp(left, str->str, len);
1315 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1317 return guid != NULL ? &guid->guid : NULL;
1320 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1322 return guid != NULL ? &guid->guid : &GUID_NULL;
1325 static int get_ptr_size(SYSKIND syskind)
1327 switch(syskind){
1328 case SYS_WIN64:
1329 return 8;
1330 case SYS_WIN32:
1331 case SYS_MAC:
1332 case SYS_WIN16:
1333 return 4;
1335 WARN("Unhandled syskind: 0x%x\n", syskind);
1336 return 4;
1340 debug
1342 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1343 if (pTD->vt & VT_RESERVED)
1344 szVarType += strlen(strcpy(szVarType, "reserved | "));
1345 if (pTD->vt & VT_BYREF)
1346 szVarType += strlen(strcpy(szVarType, "ref to "));
1347 if (pTD->vt & VT_ARRAY)
1348 szVarType += strlen(strcpy(szVarType, "array of "));
1349 if (pTD->vt & VT_VECTOR)
1350 szVarType += strlen(strcpy(szVarType, "vector of "));
1351 switch(pTD->vt & VT_TYPEMASK) {
1352 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1353 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1354 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1355 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1356 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1357 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1358 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1359 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1360 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1361 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1362 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1363 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1364 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1365 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1366 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1367 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1368 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1369 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1370 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1371 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1372 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1373 pTD->u.hreftype); break;
1374 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1375 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1376 case VT_PTR: sprintf(szVarType, "ptr to ");
1377 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1378 break;
1379 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1380 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1381 break;
1382 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1383 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1384 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1385 break;
1387 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1391 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1392 char buf[200];
1393 USHORT flags = edesc->u.paramdesc.wParamFlags;
1394 dump_TypeDesc(&edesc->tdesc,buf);
1395 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1396 MESSAGE("\t\tu.paramdesc.wParamFlags");
1397 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1398 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1399 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1400 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1401 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1402 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1403 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1404 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1405 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1407 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1408 int i;
1409 MESSAGE("memid is %08x\n",funcdesc->memid);
1410 for (i=0;i<funcdesc->cParams;i++) {
1411 MESSAGE("Param %d:\n",i);
1412 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1414 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1415 switch (funcdesc->funckind) {
1416 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1417 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1418 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1419 case FUNC_STATIC: MESSAGE("static");break;
1420 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1421 default: MESSAGE("unknown");break;
1423 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1424 switch (funcdesc->invkind) {
1425 case INVOKE_FUNC: MESSAGE("func");break;
1426 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1427 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1428 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1430 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1431 switch (funcdesc->callconv) {
1432 case CC_CDECL: MESSAGE("cdecl");break;
1433 case CC_PASCAL: MESSAGE("pascal");break;
1434 case CC_STDCALL: MESSAGE("stdcall");break;
1435 case CC_SYSCALL: MESSAGE("syscall");break;
1436 default:break;
1438 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1439 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1440 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1442 MESSAGE("\telemdescFunc (return value type):\n");
1443 dump_ELEMDESC(&funcdesc->elemdescFunc);
1446 static const char * const typekind_desc[] =
1448 "TKIND_ENUM",
1449 "TKIND_RECORD",
1450 "TKIND_MODULE",
1451 "TKIND_INTERFACE",
1452 "TKIND_DISPATCH",
1453 "TKIND_COCLASS",
1454 "TKIND_ALIAS",
1455 "TKIND_UNION",
1456 "TKIND_MAX"
1459 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1461 int i;
1462 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1463 for (i=0;i<pfd->funcdesc.cParams;i++)
1464 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1467 dump_FUNCDESC(&(pfd->funcdesc));
1469 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1470 if(pfd->Entry == NULL)
1471 MESSAGE("\tentry: (null)\n");
1472 else if(pfd->Entry == (void*)-1)
1473 MESSAGE("\tentry: invalid\n");
1474 else if(IS_INTRESOURCE(pfd->Entry))
1475 MESSAGE("\tentry: %p\n", pfd->Entry);
1476 else
1477 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1479 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1481 while (n)
1483 dump_TLBFuncDescOne(pfd);
1484 ++pfd;
1485 --n;
1488 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1490 while (n)
1492 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1493 ++pvd;
1494 --n;
1498 static void dump_TLBImpLib(const TLBImpLib *import)
1500 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1501 debugstr_w(import->name));
1502 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1503 import->wVersionMinor, import->lcid, import->offset);
1506 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1508 TLBRefType *ref;
1510 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1512 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1513 if(ref->index == -1)
1514 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1515 else
1516 TRACE_(typelib)("type no: %d\n", ref->index);
1518 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1520 TRACE_(typelib)("in lib\n");
1521 dump_TLBImpLib(ref->pImpTLInfo);
1526 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1528 if(!impl)
1529 return;
1530 while (n) {
1531 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1532 impl->hRef, impl->implflags);
1533 ++impl;
1534 --n;
1538 static void dump_DispParms(const DISPPARAMS * pdp)
1540 unsigned int index;
1542 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1544 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1546 TRACE("named args:\n");
1547 for (index = 0; index < pdp->cNamedArgs; index++)
1548 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1551 if (pdp->cArgs && pdp->rgvarg)
1553 TRACE("args:\n");
1554 for (index = 0; index < pdp->cArgs; index++)
1555 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1559 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1561 TRACE("%p ref=%u\n", pty, pty->ref);
1562 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1563 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1564 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1565 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1566 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1567 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1568 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1569 if (TRACE_ON(ole))
1570 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1571 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1572 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1575 static void dump_VARDESC(const VARDESC *v)
1577 MESSAGE("memid %d\n",v->memid);
1578 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1579 MESSAGE("oInst %d\n",v->u.oInst);
1580 dump_ELEMDESC(&(v->elemdescVar));
1581 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1582 MESSAGE("varkind %d\n",v->varkind);
1585 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1587 /* VT_LPWSTR is largest type that, may appear in type description */
1588 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1589 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1590 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1591 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1592 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1593 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1594 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1595 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1598 static void TLB_abort(void)
1600 DebugBreak();
1603 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1605 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1606 if (!ret) ERR("cannot allocate memory\n");
1607 return ret;
1610 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1612 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1613 if (!ret) ERR("cannot allocate memory\n");
1614 return ret;
1617 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1619 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1622 void heap_free(void *ptr)
1624 HeapFree(GetProcessHeap(), 0, ptr);
1627 /* returns the size required for a deep copy of a typedesc into a
1628 * flat buffer */
1629 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1631 SIZE_T size = 0;
1633 if (alloc_initial_space)
1634 size += sizeof(TYPEDESC);
1636 switch (tdesc->vt)
1638 case VT_PTR:
1639 case VT_SAFEARRAY:
1640 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1641 break;
1642 case VT_CARRAY:
1643 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1644 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1645 break;
1647 return size;
1650 /* deep copy a typedesc into a flat buffer */
1651 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1653 if (!dest)
1655 dest = buffer;
1656 buffer = (char *)buffer + sizeof(TYPEDESC);
1659 *dest = *src;
1661 switch (src->vt)
1663 case VT_PTR:
1664 case VT_SAFEARRAY:
1665 dest->u.lptdesc = buffer;
1666 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1667 break;
1668 case VT_CARRAY:
1669 dest->u.lpadesc = buffer;
1670 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1671 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1672 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1673 break;
1675 return buffer;
1678 /* free custom data allocated by MSFT_CustData */
1679 static inline void TLB_FreeCustData(struct list *custdata_list)
1681 TLBCustData *cd, *cdn;
1682 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1684 list_remove(&cd->entry);
1685 VariantClear(&cd->data);
1686 heap_free(cd);
1690 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1692 DWORD len;
1693 BSTR ret;
1695 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1696 ret = SysAllocStringLen(NULL, len - 1);
1697 if (!ret) return ret;
1698 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1699 return ret;
1702 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1703 UINT n, MEMBERID memid)
1705 while(n){
1706 if(funcdescs->funcdesc.memid == memid)
1707 return funcdescs;
1708 ++funcdescs;
1709 --n;
1711 return NULL;
1714 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1715 UINT n, MEMBERID memid)
1717 while(n){
1718 if(vardescs->vardesc.memid == memid)
1719 return vardescs;
1720 ++vardescs;
1721 --n;
1723 return NULL;
1726 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1727 UINT n, const OLECHAR *name)
1729 while(n){
1730 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1731 return vardescs;
1732 ++vardescs;
1733 --n;
1735 return NULL;
1738 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1740 TLBCustData *cust_data;
1741 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1742 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1743 return cust_data;
1744 return NULL;
1747 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1748 UINT n, const OLECHAR *name)
1750 while(n){
1751 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1752 return *typeinfos;
1753 ++typeinfos;
1754 --n;
1756 return NULL;
1759 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1761 list_init(&var_desc->custdata_list);
1764 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1766 TLBVarDesc *ret;
1768 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1769 if(!ret)
1770 return NULL;
1772 while(n){
1773 TLBVarDesc_Constructor(&ret[n-1]);
1774 --n;
1777 return ret;
1780 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1782 TLBParDesc *ret;
1784 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1785 if(!ret)
1786 return NULL;
1788 while(n){
1789 list_init(&ret[n-1].custdata_list);
1790 --n;
1793 return ret;
1796 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1798 list_init(&func_desc->custdata_list);
1801 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1803 TLBFuncDesc *ret;
1805 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1806 if(!ret)
1807 return NULL;
1809 while(n){
1810 TLBFuncDesc_Constructor(&ret[n-1]);
1811 --n;
1814 return ret;
1817 static void TLBImplType_Constructor(TLBImplType *impl)
1819 list_init(&impl->custdata_list);
1822 static TLBImplType *TLBImplType_Alloc(UINT n)
1824 TLBImplType *ret;
1826 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1827 if(!ret)
1828 return NULL;
1830 while(n){
1831 TLBImplType_Constructor(&ret[n-1]);
1832 --n;
1835 return ret;
1838 static TLBGuid *TLB_append_guid(struct list *guid_list,
1839 const GUID *new_guid, HREFTYPE hreftype)
1841 TLBGuid *guid;
1843 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1844 if (IsEqualGUID(&guid->guid, new_guid))
1845 return guid;
1848 guid = heap_alloc(sizeof(TLBGuid));
1849 if (!guid)
1850 return NULL;
1852 memcpy(&guid->guid, new_guid, sizeof(GUID));
1853 guid->hreftype = hreftype;
1855 list_add_tail(guid_list, &guid->entry);
1857 return guid;
1860 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1862 TLBCustData *cust_data;
1864 switch(V_VT(var)){
1865 case VT_I4:
1866 case VT_R4:
1867 case VT_UI4:
1868 case VT_INT:
1869 case VT_UINT:
1870 case VT_HRESULT:
1871 case VT_BSTR:
1872 break;
1873 default:
1874 return DISP_E_BADVARTYPE;
1877 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1879 if (!cust_data) {
1880 cust_data = heap_alloc(sizeof(TLBCustData));
1881 if (!cust_data)
1882 return E_OUTOFMEMORY;
1884 cust_data->guid = tlbguid;
1885 VariantInit(&cust_data->data);
1887 list_add_tail(custdata_list, &cust_data->entry);
1888 }else
1889 VariantClear(&cust_data->data);
1891 return VariantCopy(&cust_data->data, var);
1894 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1896 TLBString *str;
1898 if(!new_str)
1899 return NULL;
1901 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1902 if (strcmpW(str->str, new_str) == 0)
1903 return str;
1906 str = heap_alloc(sizeof(TLBString));
1907 if (!str)
1908 return NULL;
1910 str->str = SysAllocString(new_str);
1911 if (!str->str) {
1912 heap_free(str);
1913 return NULL;
1916 list_add_tail(string_list, &str->entry);
1918 return str;
1921 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1922 ULONG *size, WORD *align)
1924 ITypeInfo *other;
1925 TYPEATTR *attr;
1926 HRESULT hr;
1928 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1929 if(FAILED(hr))
1930 return hr;
1932 hr = ITypeInfo_GetTypeAttr(other, &attr);
1933 if(FAILED(hr)){
1934 ITypeInfo_Release(other);
1935 return hr;
1938 if(size)
1939 *size = attr->cbSizeInstance;
1940 if(align)
1941 *align = attr->cbAlignment;
1943 ITypeInfo_ReleaseTypeAttr(other, attr);
1944 ITypeInfo_Release(other);
1946 return S_OK;
1949 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1950 TYPEDESC *tdesc, ULONG *size, WORD *align)
1952 ULONG i, sub, ptr_size;
1953 HRESULT hr;
1955 ptr_size = get_ptr_size(sys);
1957 switch(tdesc->vt){
1958 case VT_VOID:
1959 *size = 0;
1960 break;
1961 case VT_I1:
1962 case VT_UI1:
1963 *size = 1;
1964 break;
1965 case VT_I2:
1966 case VT_BOOL:
1967 case VT_UI2:
1968 *size = 2;
1969 break;
1970 case VT_I4:
1971 case VT_R4:
1972 case VT_ERROR:
1973 case VT_UI4:
1974 case VT_INT:
1975 case VT_UINT:
1976 case VT_HRESULT:
1977 *size = 4;
1978 break;
1979 case VT_R8:
1980 case VT_I8:
1981 case VT_UI8:
1982 *size = 8;
1983 break;
1984 case VT_BSTR:
1985 case VT_DISPATCH:
1986 case VT_UNKNOWN:
1987 case VT_PTR:
1988 case VT_SAFEARRAY:
1989 case VT_LPSTR:
1990 case VT_LPWSTR:
1991 *size = ptr_size;
1992 break;
1993 case VT_DATE:
1994 *size = sizeof(DATE);
1995 break;
1996 case VT_VARIANT:
1997 *size = sizeof(VARIANT);
1998 #ifdef _WIN64
1999 if(sys == SYS_WIN32)
2000 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2001 #endif
2002 break;
2003 case VT_DECIMAL:
2004 *size = sizeof(DECIMAL);
2005 break;
2006 case VT_CY:
2007 *size = sizeof(CY);
2008 break;
2009 case VT_CARRAY:
2010 *size = 0;
2011 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2012 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2013 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2014 if(FAILED(hr))
2015 return hr;
2016 *size *= sub;
2017 return S_OK;
2018 case VT_USERDEFINED:
2019 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2020 default:
2021 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2022 return E_FAIL;
2025 if(align){
2026 if(*size < 4)
2027 *align = *size;
2028 else
2029 *align = 4;
2032 return S_OK;
2035 /**********************************************************************
2037 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2040 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2042 if (where != DO_NOT_SEEK)
2044 where += pcx->oStart;
2045 if (where > pcx->length)
2047 /* FIXME */
2048 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2049 TLB_abort();
2051 pcx->pos = where;
2055 /* read function */
2056 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2058 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2059 pcx->pos, count, pcx->oStart, pcx->length, where);
2061 MSFT_Seek(pcx, where);
2062 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2063 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2064 pcx->pos += count;
2065 return count;
2068 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2069 LONG where )
2071 DWORD ret;
2073 ret = MSFT_Read(buffer, count, pcx, where);
2074 FromLEDWords(buffer, ret);
2076 return ret;
2079 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2080 LONG where )
2082 DWORD ret;
2084 ret = MSFT_Read(buffer, count, pcx, where);
2085 FromLEWords(buffer, ret);
2087 return ret;
2090 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2092 TLBGuid *guid;
2093 MSFT_GuidEntry entry;
2094 int offs = 0;
2096 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2097 while (1) {
2098 if (offs >= pcx->pTblDir->pGuidTab.length)
2099 return S_OK;
2101 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2103 guid = heap_alloc(sizeof(TLBGuid));
2105 guid->offset = offs;
2106 guid->guid = entry.guid;
2107 guid->hreftype = entry.hreftype;
2109 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2111 offs += sizeof(MSFT_GuidEntry);
2115 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2117 TLBGuid *ret;
2119 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2120 if(ret->offset == offset){
2121 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2122 return ret;
2126 return NULL;
2129 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2131 MSFT_NameIntro niName;
2133 if (offset < 0)
2135 ERR_(typelib)("bad offset %d\n", offset);
2136 return -1;
2139 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2140 pcx->pTblDir->pNametab.offset+offset);
2142 return niName.hreftype;
2145 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2147 char *string;
2148 MSFT_NameIntro intro;
2149 INT16 len_piece;
2150 int offs = 0, lengthInChars;
2152 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2153 while (1) {
2154 TLBString *tlbstr;
2156 if (offs >= pcx->pTblDir->pNametab.length)
2157 return S_OK;
2159 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2160 intro.namelen &= 0xFF;
2161 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2162 if(len_piece % 4)
2163 len_piece = (len_piece + 4) & ~0x3;
2164 if(len_piece < 8)
2165 len_piece = 8;
2167 string = heap_alloc(len_piece + 1);
2168 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2169 string[intro.namelen] = '\0';
2171 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2172 string, -1, NULL, 0);
2173 if (!lengthInChars) {
2174 heap_free(string);
2175 return E_UNEXPECTED;
2178 tlbstr = heap_alloc(sizeof(TLBString));
2180 tlbstr->offset = offs;
2181 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2182 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2184 heap_free(string);
2186 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2188 offs += len_piece;
2192 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2194 TLBString *tlbstr;
2196 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2197 if (tlbstr->offset == offset) {
2198 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2199 return tlbstr;
2203 return NULL;
2206 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2208 TLBString *tlbstr;
2210 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2211 if (tlbstr->offset == offset) {
2212 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2213 return tlbstr;
2217 return NULL;
2221 * read a value and fill a VARIANT structure
2223 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2225 int size;
2227 TRACE_(typelib)("\n");
2229 if(offset <0) { /* data are packed in here */
2230 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2231 V_I4(pVar) = offset & 0x3ffffff;
2232 return;
2234 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2235 pcx->pTblDir->pCustData.offset + offset );
2236 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2237 switch (V_VT(pVar)){
2238 case VT_EMPTY: /* FIXME: is this right? */
2239 case VT_NULL: /* FIXME: is this right? */
2240 case VT_I2 : /* this should not happen */
2241 case VT_I4 :
2242 case VT_R4 :
2243 case VT_ERROR :
2244 case VT_BOOL :
2245 case VT_I1 :
2246 case VT_UI1 :
2247 case VT_UI2 :
2248 case VT_UI4 :
2249 case VT_INT :
2250 case VT_UINT :
2251 case VT_VOID : /* FIXME: is this right? */
2252 case VT_HRESULT :
2253 size=4; break;
2254 case VT_R8 :
2255 case VT_CY :
2256 case VT_DATE :
2257 case VT_I8 :
2258 case VT_UI8 :
2259 case VT_DECIMAL : /* FIXME: is this right? */
2260 case VT_FILETIME :
2261 size=8;break;
2262 /* pointer types with known behaviour */
2263 case VT_BSTR :{
2264 char * ptr;
2265 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2266 if(size == -1){
2267 V_BSTR(pVar) = NULL;
2268 }else{
2269 ptr = heap_alloc_zero(size);
2270 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2271 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2272 /* FIXME: do we need a AtoW conversion here? */
2273 V_UNION(pVar, bstrVal[size])='\0';
2274 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2275 heap_free(ptr);
2278 size=-4; break;
2279 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2280 case VT_DISPATCH :
2281 case VT_VARIANT :
2282 case VT_UNKNOWN :
2283 case VT_PTR :
2284 case VT_SAFEARRAY :
2285 case VT_CARRAY :
2286 case VT_USERDEFINED :
2287 case VT_LPSTR :
2288 case VT_LPWSTR :
2289 case VT_BLOB :
2290 case VT_STREAM :
2291 case VT_STORAGE :
2292 case VT_STREAMED_OBJECT :
2293 case VT_STORED_OBJECT :
2294 case VT_BLOB_OBJECT :
2295 case VT_CF :
2296 case VT_CLSID :
2297 default:
2298 size=0;
2299 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2300 V_VT(pVar));
2303 if(size>0) /* (big|small) endian correct? */
2304 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2305 return;
2308 * create a linked list with custom data
2310 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2312 MSFT_CDGuid entry;
2313 TLBCustData* pNew;
2314 int count=0;
2316 TRACE_(typelib)("\n");
2318 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2320 while(offset >=0){
2321 count++;
2322 pNew=heap_alloc_zero(sizeof(TLBCustData));
2323 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2324 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2325 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2326 list_add_head(custdata_list, &pNew->entry);
2327 offset = entry.next;
2329 return count;
2332 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2334 if(type <0)
2335 pTd->vt=type & VT_TYPEMASK;
2336 else
2337 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2339 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2342 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2344 return (invkind == INVOKE_PROPERTYGET ||
2345 invkind == INVOKE_PROPERTYPUT ||
2346 invkind == INVOKE_PROPERTYPUTREF);
2349 static void
2350 MSFT_DoFuncs(TLBContext* pcx,
2351 ITypeInfoImpl* pTI,
2352 int cFuncs,
2353 int cVars,
2354 int offset,
2355 TLBFuncDesc** pptfd)
2358 * member information is stored in a data structure at offset
2359 * indicated by the memoffset field of the typeinfo structure
2360 * There are several distinctive parts.
2361 * The first part starts with a field that holds the total length
2362 * of this (first) part excluding this field. Then follow the records,
2363 * for each member there is one record.
2365 * The first entry is always the length of the record (including this
2366 * length word).
2367 * The rest of the record depends on the type of the member. If there is
2368 * a field indicating the member type (function, variable, interface, etc)
2369 * I have not found it yet. At this time we depend on the information
2370 * in the type info and the usual order how things are stored.
2372 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2373 * for each member;
2375 * Third is an equal sized array with file offsets to the name entry
2376 * of each member.
2378 * The fourth and last (?) part is an array with offsets to the records
2379 * in the first part of this file segment.
2382 int infolen, nameoffset, reclength, i;
2383 int recoffset = offset + sizeof(INT);
2385 char *recbuf = heap_alloc(0xffff);
2386 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2387 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2389 TRACE_(typelib)("\n");
2391 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2393 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2394 ptfd = *pptfd;
2395 for ( i = 0; i < cFuncs ; i++ )
2397 int optional;
2399 /* name, eventually add to a hash table */
2400 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2401 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2403 /* read the function information record */
2404 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2406 reclength &= 0xffff;
2408 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2410 /* size without argument data */
2411 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2412 if (pFuncRec->FKCCIC & 0x1000)
2413 optional -= pFuncRec->nrargs * sizeof(INT);
2415 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2416 ptfd->helpcontext = pFuncRec->HelpContext;
2418 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2419 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2421 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2423 if (pFuncRec->FKCCIC & 0x2000 )
2425 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2426 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2427 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2429 else
2430 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2432 else
2433 ptfd->Entry = (TLBString*)-1;
2435 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2436 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2438 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2439 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2441 /* fill the FuncDesc Structure */
2442 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2443 offset + infolen + ( i + 1) * sizeof(INT));
2445 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2446 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2447 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2448 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2449 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2450 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2451 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2453 /* nameoffset is sometimes -1 on the second half of a propget/propput
2454 * pair of functions */
2455 if ((nameoffset == -1) && (i > 0) &&
2456 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2457 TLB_is_propgetput(ptfd->funcdesc.invkind))
2458 ptfd->Name = ptfd_prev->Name;
2459 else
2460 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2462 MSFT_GetTdesc(pcx,
2463 pFuncRec->DataType,
2464 &ptfd->funcdesc.elemdescFunc.tdesc);
2466 /* do the parameters/arguments */
2467 if(pFuncRec->nrargs)
2469 int j = 0;
2470 MSFT_ParameterInfo paraminfo;
2472 ptfd->funcdesc.lprgelemdescParam =
2473 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2475 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2477 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2478 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2480 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2482 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2484 MSFT_GetTdesc(pcx,
2485 paraminfo.DataType,
2486 &elemdesc->tdesc);
2488 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2490 /* name */
2491 if (paraminfo.oName != -1)
2492 ptfd->pParamDesc[j].Name =
2493 MSFT_ReadName( pcx, paraminfo.oName );
2494 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2496 /* default value */
2497 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2498 (pFuncRec->FKCCIC & 0x1000) )
2500 INT* pInt = (INT *)((char *)pFuncRec +
2501 reclength -
2502 (pFuncRec->nrargs * 4) * sizeof(INT) );
2504 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2506 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2507 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2509 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2510 pInt[j], pcx);
2512 else
2513 elemdesc->u.paramdesc.pparamdescex = NULL;
2515 /* custom info */
2516 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2517 j*sizeof(pFuncRec->oArgCustData[0])) &&
2518 pFuncRec->FKCCIC & 0x80 )
2520 MSFT_CustData(pcx,
2521 pFuncRec->oArgCustData[j],
2522 &ptfd->pParamDesc[j].custdata_list);
2525 /* SEEK value = jump to offset,
2526 * from there jump to the end of record,
2527 * go back by (j-1) arguments
2529 MSFT_ReadLEDWords( &paraminfo ,
2530 sizeof(MSFT_ParameterInfo), pcx,
2531 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2532 * sizeof(MSFT_ParameterInfo)));
2536 /* scode is not used: archaic win16 stuff FIXME: right? */
2537 ptfd->funcdesc.cScodes = 0 ;
2538 ptfd->funcdesc.lprgscode = NULL ;
2540 ptfd_prev = ptfd;
2541 ++ptfd;
2542 recoffset += reclength;
2544 heap_free(recbuf);
2547 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2548 int cVars, int offset, TLBVarDesc ** pptvd)
2550 int infolen, nameoffset, reclength;
2551 char recbuf[256];
2552 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2553 TLBVarDesc *ptvd;
2554 int i;
2555 int recoffset;
2557 TRACE_(typelib)("\n");
2559 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2560 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2561 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2562 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2563 recoffset += offset+sizeof(INT);
2564 for(i=0;i<cVars;i++, ++ptvd){
2565 /* name, eventually add to a hash table */
2566 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2567 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2568 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2569 /* read the variable information record */
2570 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2571 reclength &= 0xff;
2572 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2574 /* optional data */
2575 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2576 ptvd->HelpContext = pVarRec->HelpContext;
2578 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2579 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2581 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2582 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2584 /* fill the VarDesc Structure */
2585 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2586 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2587 ptvd->vardesc.varkind = pVarRec->VarKind;
2588 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2589 MSFT_GetTdesc(pcx, pVarRec->DataType,
2590 &ptvd->vardesc.elemdescVar.tdesc);
2591 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2592 if(pVarRec->VarKind == VAR_CONST ){
2593 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2594 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2595 pVarRec->OffsValue, pcx);
2596 } else
2597 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2598 recoffset += reclength;
2602 /* process Implemented Interfaces of a com class */
2603 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2604 int offset)
2606 int i;
2607 MSFT_RefRecord refrec;
2608 TLBImplType *pImpl;
2610 TRACE_(typelib)("\n");
2612 pTI->impltypes = TLBImplType_Alloc(count);
2613 pImpl = pTI->impltypes;
2614 for(i=0;i<count;i++){
2615 if(offset<0) break; /* paranoia */
2616 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2617 pImpl->hRef = refrec.reftype;
2618 pImpl->implflags=refrec.flags;
2619 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2620 offset=refrec.onext;
2621 ++pImpl;
2625 #ifdef _WIN64
2626 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2627 * and some structures, and fix the alignment */
2628 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2630 if(info->typeattr.typekind == TKIND_ALIAS){
2631 switch(info->tdescAlias->vt){
2632 case VT_BSTR:
2633 case VT_DISPATCH:
2634 case VT_UNKNOWN:
2635 case VT_PTR:
2636 case VT_SAFEARRAY:
2637 case VT_LPSTR:
2638 case VT_LPWSTR:
2639 info->typeattr.cbSizeInstance = sizeof(void*);
2640 info->typeattr.cbAlignment = sizeof(void*);
2641 break;
2642 case VT_CARRAY:
2643 case VT_USERDEFINED:
2644 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2645 break;
2646 case VT_VARIANT:
2647 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2648 info->typeattr.cbAlignment = 8;
2649 default:
2650 if(info->typeattr.cbSizeInstance < sizeof(void*))
2651 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2652 else
2653 info->typeattr.cbAlignment = sizeof(void*);
2654 break;
2656 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2657 info->typeattr.typekind == TKIND_DISPATCH ||
2658 info->typeattr.typekind == TKIND_COCLASS){
2659 info->typeattr.cbSizeInstance = sizeof(void*);
2660 info->typeattr.cbAlignment = sizeof(void*);
2663 #endif
2666 * process a typeinfo record
2668 static ITypeInfoImpl * MSFT_DoTypeInfo(
2669 TLBContext *pcx,
2670 int count,
2671 ITypeLibImpl * pLibInfo)
2673 MSFT_TypeInfoBase tiBase;
2674 ITypeInfoImpl *ptiRet;
2676 TRACE_(typelib)("count=%u\n", count);
2678 ptiRet = ITypeInfoImpl_Constructor();
2679 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2680 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2682 /* this is where we are coming from */
2683 ptiRet->pTypeLib = pLibInfo;
2684 ptiRet->index=count;
2686 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2687 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2688 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2689 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2690 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2691 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2692 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2693 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2694 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2695 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2696 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2697 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2698 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2699 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2700 TYPEDESC tmp;
2701 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2702 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2703 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2706 /* FIXME: */
2707 /* IDLDESC idldescType; *//* never saw this one != zero */
2709 /* name, eventually add to a hash table */
2710 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2711 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2712 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2713 /* help info */
2714 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2715 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2716 ptiRet->dwHelpContext=tiBase.helpcontext;
2718 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2719 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2721 /* note: InfoType's Help file and HelpStringDll come from the containing
2722 * library. Further HelpString and Docstring appear to be the same thing :(
2724 /* functions */
2725 if(ptiRet->typeattr.cFuncs >0 )
2726 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2727 ptiRet->typeattr.cVars,
2728 tiBase.memoffset, &ptiRet->funcdescs);
2729 /* variables */
2730 if(ptiRet->typeattr.cVars >0 )
2731 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2732 ptiRet->typeattr.cVars,
2733 tiBase.memoffset, &ptiRet->vardescs);
2734 if(ptiRet->typeattr.cImplTypes >0 ) {
2735 switch(ptiRet->typeattr.typekind)
2737 case TKIND_COCLASS:
2738 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2739 tiBase.datatype1);
2740 break;
2741 case TKIND_DISPATCH:
2742 /* This is not -1 when the interface is a non-base dual interface or
2743 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2744 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2745 not this interface.
2748 if (tiBase.datatype1 != -1)
2750 ptiRet->impltypes = TLBImplType_Alloc(1);
2751 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2753 break;
2754 default:
2755 ptiRet->impltypes = TLBImplType_Alloc(1);
2756 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2757 break;
2760 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2762 TRACE_(typelib)("%s guid: %s kind:%s\n",
2763 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2764 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2765 typekind_desc[ptiRet->typeattr.typekind]);
2766 if (TRACE_ON(typelib))
2767 dump_TypeInfo(ptiRet);
2769 return ptiRet;
2772 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2774 char *string;
2775 INT16 len_str, len_piece;
2776 int offs = 0, lengthInChars;
2778 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2779 while (1) {
2780 TLBString *tlbstr;
2782 if (offs >= pcx->pTblDir->pStringtab.length)
2783 return S_OK;
2785 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2786 len_piece = len_str + sizeof(INT16);
2787 if(len_piece % 4)
2788 len_piece = (len_piece + 4) & ~0x3;
2789 if(len_piece < 8)
2790 len_piece = 8;
2792 string = heap_alloc(len_piece + 1);
2793 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2794 string[len_str] = '\0';
2796 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2797 string, -1, NULL, 0);
2798 if (!lengthInChars) {
2799 heap_free(string);
2800 return E_UNEXPECTED;
2803 tlbstr = heap_alloc(sizeof(TLBString));
2805 tlbstr->offset = offs;
2806 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2807 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2809 heap_free(string);
2811 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2813 offs += len_piece;
2817 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2819 TLBRefType *ref;
2820 int offs = 0;
2822 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2823 while (offs < pcx->pTblDir->pImpInfo.length) {
2824 MSFT_ImpInfo impinfo;
2825 TLBImpLib *pImpLib;
2827 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2829 ref = heap_alloc_zero(sizeof(TLBRefType));
2830 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2832 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2833 if(pImpLib->offset==impinfo.oImpFile)
2834 break;
2836 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2837 ref->reference = offs;
2838 ref->pImpTLInfo = pImpLib;
2839 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2840 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2841 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2842 ref->index = TLB_REF_USE_GUID;
2843 } else
2844 ref->index = impinfo.oGuid;
2845 }else{
2846 ERR("Cannot find a reference\n");
2847 ref->reference = -1;
2848 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2851 offs += sizeof(impinfo);
2854 return S_OK;
2857 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2858 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2859 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2860 * tradeoff here.
2862 static struct list tlb_cache = LIST_INIT(tlb_cache);
2863 static CRITICAL_SECTION cache_section;
2864 static CRITICAL_SECTION_DEBUG cache_section_debug =
2866 0, 0, &cache_section,
2867 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2868 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2870 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2873 typedef struct TLB_PEFile
2875 IUnknown IUnknown_iface;
2876 LONG refs;
2877 HMODULE dll;
2878 HRSRC typelib_resource;
2879 HGLOBAL typelib_global;
2880 LPVOID typelib_base;
2881 } TLB_PEFile;
2883 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2885 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2888 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2890 if (IsEqualIID(riid, &IID_IUnknown))
2892 *ppv = iface;
2893 IUnknown_AddRef(iface);
2894 return S_OK;
2896 *ppv = NULL;
2897 return E_NOINTERFACE;
2900 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2902 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2903 return InterlockedIncrement(&This->refs);
2906 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2908 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2909 ULONG refs = InterlockedDecrement(&This->refs);
2910 if (!refs)
2912 if (This->typelib_global)
2913 FreeResource(This->typelib_global);
2914 if (This->dll)
2915 FreeLibrary(This->dll);
2916 heap_free(This);
2918 return refs;
2921 static const IUnknownVtbl TLB_PEFile_Vtable =
2923 TLB_PEFile_QueryInterface,
2924 TLB_PEFile_AddRef,
2925 TLB_PEFile_Release
2928 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2930 TLB_PEFile *This;
2931 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2933 This = heap_alloc(sizeof(TLB_PEFile));
2934 if (!This)
2935 return E_OUTOFMEMORY;
2937 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2938 This->refs = 1;
2939 This->dll = NULL;
2940 This->typelib_resource = NULL;
2941 This->typelib_global = NULL;
2942 This->typelib_base = NULL;
2944 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2945 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2947 if (This->dll)
2949 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2950 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2951 if (This->typelib_resource)
2953 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2954 if (This->typelib_global)
2956 This->typelib_base = LockResource(This->typelib_global);
2958 if (This->typelib_base)
2960 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2961 *ppBase = This->typelib_base;
2962 *ppFile = &This->IUnknown_iface;
2963 return S_OK;
2968 TRACE("No TYPELIB resource found\n");
2969 hr = E_FAIL;
2972 TLB_PEFile_Release(&This->IUnknown_iface);
2973 return hr;
2976 typedef struct TLB_NEFile
2978 IUnknown IUnknown_iface;
2979 LONG refs;
2980 LPVOID typelib_base;
2981 } TLB_NEFile;
2983 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2985 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2988 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2990 if (IsEqualIID(riid, &IID_IUnknown))
2992 *ppv = iface;
2993 IUnknown_AddRef(iface);
2994 return S_OK;
2996 *ppv = NULL;
2997 return E_NOINTERFACE;
3000 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3002 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3003 return InterlockedIncrement(&This->refs);
3006 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3008 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3009 ULONG refs = InterlockedDecrement(&This->refs);
3010 if (!refs)
3012 heap_free(This->typelib_base);
3013 heap_free(This);
3015 return refs;
3018 static const IUnknownVtbl TLB_NEFile_Vtable =
3020 TLB_NEFile_QueryInterface,
3021 TLB_NEFile_AddRef,
3022 TLB_NEFile_Release
3025 /***********************************************************************
3026 * read_xx_header [internal]
3028 static int read_xx_header( HFILE lzfd )
3030 IMAGE_DOS_HEADER mzh;
3031 char magic[3];
3033 LZSeek( lzfd, 0, SEEK_SET );
3034 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3035 return 0;
3036 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3037 return 0;
3039 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3040 if ( 2 != LZRead( lzfd, magic, 2 ) )
3041 return 0;
3043 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3045 if ( magic[0] == 'N' && magic[1] == 'E' )
3046 return IMAGE_OS2_SIGNATURE;
3047 if ( magic[0] == 'P' && magic[1] == 'E' )
3048 return IMAGE_NT_SIGNATURE;
3050 magic[2] = '\0';
3051 WARN("Can't handle %s files.\n", magic );
3052 return 0;
3056 /***********************************************************************
3057 * find_ne_resource [internal]
3059 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3060 DWORD *resLen, DWORD *resOff )
3062 IMAGE_OS2_HEADER nehd;
3063 NE_TYPEINFO *typeInfo;
3064 NE_NAMEINFO *nameInfo;
3065 DWORD nehdoffset;
3066 LPBYTE resTab;
3067 DWORD resTabSize;
3068 int count;
3070 /* Read in NE header */
3071 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3072 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3074 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3075 if ( !resTabSize )
3077 TRACE("No resources in NE dll\n" );
3078 return FALSE;
3081 /* Read in resource table */
3082 resTab = heap_alloc( resTabSize );
3083 if ( !resTab ) return FALSE;
3085 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3086 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3088 heap_free( resTab );
3089 return FALSE;
3092 /* Find resource */
3093 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3095 if (!IS_INTRESOURCE(typeid)) /* named type */
3097 BYTE len = strlen( typeid );
3098 while (typeInfo->type_id)
3100 if (!(typeInfo->type_id & 0x8000))
3102 BYTE *p = resTab + typeInfo->type_id;
3103 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3105 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3106 typeInfo->count * sizeof(NE_NAMEINFO));
3109 else /* numeric type id */
3111 WORD id = LOWORD(typeid) | 0x8000;
3112 while (typeInfo->type_id)
3114 if (typeInfo->type_id == id) goto found_type;
3115 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3116 typeInfo->count * sizeof(NE_NAMEINFO));
3119 TRACE("No typeid entry found for %p\n", typeid );
3120 heap_free( resTab );
3121 return FALSE;
3123 found_type:
3124 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3126 if (!IS_INTRESOURCE(resid)) /* named resource */
3128 BYTE len = strlen( resid );
3129 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3131 BYTE *p = resTab + nameInfo->id;
3132 if (nameInfo->id & 0x8000) continue;
3133 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3136 else /* numeric resource id */
3138 WORD id = LOWORD(resid) | 0x8000;
3139 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3140 if (nameInfo->id == id) goto found_name;
3142 TRACE("No resid entry found for %p\n", typeid );
3143 heap_free( resTab );
3144 return FALSE;
3146 found_name:
3147 /* Return resource data */
3148 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3149 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3151 heap_free( resTab );
3152 return TRUE;
3155 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3157 HFILE lzfd = -1;
3158 OFSTRUCT ofs;
3159 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3160 TLB_NEFile *This;
3162 This = heap_alloc(sizeof(TLB_NEFile));
3163 if (!This) return E_OUTOFMEMORY;
3165 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3166 This->refs = 1;
3167 This->typelib_base = NULL;
3169 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3170 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3172 DWORD reslen, offset;
3173 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3175 This->typelib_base = heap_alloc(reslen);
3176 if( !This->typelib_base )
3177 hr = E_OUTOFMEMORY;
3178 else
3180 LZSeek( lzfd, offset, SEEK_SET );
3181 reslen = LZRead( lzfd, This->typelib_base, reslen );
3182 LZClose( lzfd );
3183 *ppBase = This->typelib_base;
3184 *pdwTLBLength = reslen;
3185 *ppFile = &This->IUnknown_iface;
3186 return S_OK;
3191 if( lzfd >= 0) LZClose( lzfd );
3192 TLB_NEFile_Release(&This->IUnknown_iface);
3193 return hr;
3196 typedef struct TLB_Mapping
3198 IUnknown IUnknown_iface;
3199 LONG refs;
3200 HANDLE file;
3201 HANDLE mapping;
3202 LPVOID typelib_base;
3203 } TLB_Mapping;
3205 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3207 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3210 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3212 if (IsEqualIID(riid, &IID_IUnknown))
3214 *ppv = iface;
3215 IUnknown_AddRef(iface);
3216 return S_OK;
3218 *ppv = NULL;
3219 return E_NOINTERFACE;
3222 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3224 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3225 return InterlockedIncrement(&This->refs);
3228 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3230 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3231 ULONG refs = InterlockedDecrement(&This->refs);
3232 if (!refs)
3234 if (This->typelib_base)
3235 UnmapViewOfFile(This->typelib_base);
3236 if (This->mapping)
3237 CloseHandle(This->mapping);
3238 if (This->file != INVALID_HANDLE_VALUE)
3239 CloseHandle(This->file);
3240 heap_free(This);
3242 return refs;
3245 static const IUnknownVtbl TLB_Mapping_Vtable =
3247 TLB_Mapping_QueryInterface,
3248 TLB_Mapping_AddRef,
3249 TLB_Mapping_Release
3252 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3254 TLB_Mapping *This;
3256 This = heap_alloc(sizeof(TLB_Mapping));
3257 if (!This)
3258 return E_OUTOFMEMORY;
3260 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3261 This->refs = 1;
3262 This->file = INVALID_HANDLE_VALUE;
3263 This->mapping = NULL;
3264 This->typelib_base = NULL;
3266 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3267 if (INVALID_HANDLE_VALUE != This->file)
3269 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3270 if (This->mapping)
3272 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3273 if(This->typelib_base)
3275 /* retrieve file size */
3276 *pdwTLBLength = GetFileSize(This->file, NULL);
3277 *ppBase = This->typelib_base;
3278 *ppFile = &This->IUnknown_iface;
3279 return S_OK;
3284 IUnknown_Release(&This->IUnknown_iface);
3285 return TYPE_E_CANTLOADLIBRARY;
3288 /****************************************************************************
3289 * TLB_ReadTypeLib
3291 * find the type of the typelib file and map the typelib resource into
3292 * the memory
3295 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3296 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3298 ITypeLibImpl *entry;
3299 HRESULT ret;
3300 INT index = 1;
3301 LPWSTR index_str, file = (LPWSTR)pszFileName;
3302 LPVOID pBase = NULL;
3303 DWORD dwTLBLength = 0;
3304 IUnknown *pFile = NULL;
3305 HANDLE h;
3307 *ppTypeLib = NULL;
3309 index_str = strrchrW(pszFileName, '\\');
3310 if(index_str && *++index_str != '\0')
3312 LPWSTR end_ptr;
3313 LONG idx = strtolW(index_str, &end_ptr, 10);
3314 if(*end_ptr == '\0')
3316 int str_len = index_str - pszFileName - 1;
3317 index = idx;
3318 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3319 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3320 file[str_len] = 0;
3324 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3326 if(strchrW(file, '\\'))
3328 lstrcpyW(pszPath, file);
3330 else
3332 int len = GetSystemDirectoryW(pszPath, cchPath);
3333 pszPath[len] = '\\';
3334 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3338 if(file != pszFileName) heap_free(file);
3340 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3341 if(h != INVALID_HANDLE_VALUE){
3342 FILE_NAME_INFORMATION size_info;
3343 BOOL br;
3345 /* GetFileInformationByHandleEx returns the path of the file without
3346 * WOW64 redirection */
3347 br = GetFileInformationByHandleEx(h, FileNameInfo, &size_info, sizeof(size_info));
3348 if(br || GetLastError() == ERROR_MORE_DATA){
3349 FILE_NAME_INFORMATION *info;
3350 DWORD size = sizeof(*info) + size_info.FileNameLength + sizeof(WCHAR);
3352 info = HeapAlloc(GetProcessHeap(), 0, size);
3354 br = GetFileInformationByHandleEx(h, FileNameInfo, info, size);
3355 if(br){
3356 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3357 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3360 HeapFree(GetProcessHeap(), 0, info);
3363 CloseHandle(h);
3366 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3368 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3369 EnterCriticalSection(&cache_section);
3370 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3372 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3374 TRACE("cache hit\n");
3375 *ppTypeLib = &entry->ITypeLib2_iface;
3376 ITypeLib2_AddRef(*ppTypeLib);
3377 LeaveCriticalSection(&cache_section);
3378 return S_OK;
3381 LeaveCriticalSection(&cache_section);
3383 /* now actually load and parse the typelib */
3385 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3386 if (ret == TYPE_E_CANTLOADLIBRARY)
3387 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3388 if (ret == TYPE_E_CANTLOADLIBRARY)
3389 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3390 if (SUCCEEDED(ret))
3392 if (dwTLBLength >= 4)
3394 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3395 if (dwSignature == MSFT_SIGNATURE)
3396 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3397 else if (dwSignature == SLTG_SIGNATURE)
3398 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3399 else
3401 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3402 ret = TYPE_E_CANTLOADLIBRARY;
3405 else
3406 ret = TYPE_E_CANTLOADLIBRARY;
3407 IUnknown_Release(pFile);
3410 if(*ppTypeLib) {
3411 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3413 TRACE("adding to cache\n");
3414 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3415 lstrcpyW(impl->path, pszPath);
3416 /* We should really canonicalise the path here. */
3417 impl->index = index;
3419 /* FIXME: check if it has added already in the meantime */
3420 EnterCriticalSection(&cache_section);
3421 list_add_head(&tlb_cache, &impl->entry);
3422 LeaveCriticalSection(&cache_section);
3423 ret = S_OK;
3425 else
3427 if(ret != E_FAIL)
3428 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3430 ret = TYPE_E_CANTLOADLIBRARY;
3434 return ret;
3437 /*================== ITypeLib(2) Methods ===================================*/
3439 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3441 ITypeLibImpl* pTypeLibImpl;
3443 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3444 if (!pTypeLibImpl) return NULL;
3446 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3447 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3448 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3449 pTypeLibImpl->ref = 1;
3451 list_init(&pTypeLibImpl->implib_list);
3452 list_init(&pTypeLibImpl->custdata_list);
3453 list_init(&pTypeLibImpl->name_list);
3454 list_init(&pTypeLibImpl->string_list);
3455 list_init(&pTypeLibImpl->guid_list);
3456 list_init(&pTypeLibImpl->ref_list);
3457 pTypeLibImpl->dispatch_href = -1;
3459 return pTypeLibImpl;
3462 /****************************************************************************
3463 * ITypeLib2_Constructor_MSFT
3465 * loading an MSFT typelib from an in-memory image
3467 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3469 TLBContext cx;
3470 LONG lPSegDir;
3471 MSFT_Header tlbHeader;
3472 MSFT_SegDir tlbSegDir;
3473 ITypeLibImpl * pTypeLibImpl;
3474 int i;
3476 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3478 pTypeLibImpl = TypeLibImpl_Constructor();
3479 if (!pTypeLibImpl) return NULL;
3481 /* get pointer to beginning of typelib data */
3482 cx.pos = 0;
3483 cx.oStart=0;
3484 cx.mapping = pLib;
3485 cx.pLibInfo = pTypeLibImpl;
3486 cx.length = dwTLBLength;
3488 /* read header */
3489 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3490 TRACE_(typelib)("header:\n");
3491 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3492 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3493 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3494 return NULL;
3496 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3498 /* there is a small amount of information here until the next important
3499 * part:
3500 * the segment directory . Try to calculate the amount of data */
3501 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3503 /* now read the segment directory */
3504 TRACE("read segment directory (at %d)\n",lPSegDir);
3505 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3506 cx.pTblDir = &tlbSegDir;
3508 /* just check two entries */
3509 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3511 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3512 heap_free(pTypeLibImpl);
3513 return NULL;
3516 MSFT_ReadAllNames(&cx);
3517 MSFT_ReadAllStrings(&cx);
3518 MSFT_ReadAllGuids(&cx);
3520 /* now fill our internal data */
3521 /* TLIBATTR fields */
3522 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3524 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3525 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3526 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3527 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3528 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3530 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3531 pTypeLibImpl->lcid = tlbHeader.lcid;
3533 /* name, eventually add to a hash table */
3534 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3536 /* help info */
3537 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3538 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3540 if( tlbHeader.varflags & HELPDLLFLAG)
3542 int offset;
3543 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3544 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3547 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3549 /* custom data */
3550 if(tlbHeader.CustomDataOffset >= 0)
3552 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3555 /* fill in type descriptions */
3556 if(tlbSegDir.pTypdescTab.length > 0)
3558 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3559 INT16 td[4];
3560 pTypeLibImpl->ctTypeDesc = cTD;
3561 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3562 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3563 for(i=0; i<cTD; )
3565 /* FIXME: add several sanity checks here */
3566 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3567 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3569 /* FIXME: check safearray */
3570 if(td[3] < 0)
3571 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3572 else
3573 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3575 else if(td[0] == VT_CARRAY)
3577 /* array descr table here */
3578 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3580 else if(td[0] == VT_USERDEFINED)
3582 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3584 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3587 /* second time around to fill the array subscript info */
3588 for(i=0;i<cTD;i++)
3590 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3591 if(tlbSegDir.pArrayDescriptions.offset>0)
3593 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3594 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3596 if(td[1]<0)
3597 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3598 else
3599 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3601 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3603 for(j = 0; j<td[2]; j++)
3605 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3606 sizeof(INT), &cx, DO_NOT_SEEK);
3607 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3608 sizeof(INT), &cx, DO_NOT_SEEK);
3611 else
3613 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3614 ERR("didn't find array description data\n");
3619 /* imported type libs */
3620 if(tlbSegDir.pImpFiles.offset>0)
3622 TLBImpLib *pImpLib;
3623 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3624 UINT16 size;
3626 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3628 char *name;
3630 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3631 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3632 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3634 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3635 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3636 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3637 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3639 size >>= 2;
3640 name = heap_alloc_zero(size+1);
3641 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3642 pImpLib->name = TLB_MultiByteToBSTR(name);
3643 heap_free(name);
3645 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3646 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3648 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3652 MSFT_ReadAllRefs(&cx);
3654 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3656 /* type infos */
3657 if(tlbHeader.nrtypeinfos >= 0 )
3659 ITypeInfoImpl **ppTI;
3661 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3663 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3665 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3667 ++ppTI;
3668 (pTypeLibImpl->TypeInfoCount)++;
3672 #ifdef _WIN64
3673 if(pTypeLibImpl->syskind == SYS_WIN32){
3674 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3675 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3677 #endif
3679 TRACE("(%p)\n", pTypeLibImpl);
3680 return &pTypeLibImpl->ITypeLib2_iface;
3684 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3686 char b[3];
3687 int i;
3688 short s;
3690 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3691 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3692 return FALSE;
3695 guid->Data4[0] = s >> 8;
3696 guid->Data4[1] = s & 0xff;
3698 b[2] = '\0';
3699 for(i = 0; i < 6; i++) {
3700 memcpy(b, str + 24 + 2 * i, 2);
3701 guid->Data4[i + 2] = strtol(b, NULL, 16);
3703 return TRUE;
3706 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3708 WORD bytelen;
3709 DWORD len;
3710 BSTR tmp_str;
3712 *pStr = NULL;
3713 bytelen = *(const WORD*)ptr;
3714 if(bytelen == 0xffff) return 2;
3716 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3717 tmp_str = SysAllocStringLen(NULL, len);
3718 if (tmp_str) {
3719 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3720 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3721 SysFreeString(tmp_str);
3723 return bytelen + 2;
3726 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3728 WORD bytelen;
3730 *str = NULL;
3731 bytelen = *(const WORD*)ptr;
3732 if(bytelen == 0xffff) return 2;
3733 *str = heap_alloc(bytelen + 1);
3734 memcpy(*str, ptr + 2, bytelen);
3735 (*str)[bytelen] = '\0';
3736 return bytelen + 2;
3739 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3741 BSTR tmp_str;
3742 TLBString *tlbstr;
3744 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3745 if (tlbstr->offset == offset)
3746 return tlbstr;
3749 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3750 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3751 SysFreeString(tmp_str);
3753 return tlbstr;
3756 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3758 char *ptr = pLibBlk;
3759 WORD w;
3761 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3762 FIXME("libblk magic = %04x\n", w);
3763 return 0;
3766 ptr += 6;
3767 if((w = *(WORD*)ptr) != 0xffff) {
3768 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3769 ptr += w;
3771 ptr += 2;
3773 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3775 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3777 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3778 ptr += 4;
3780 pTypeLibImpl->syskind = *(WORD*)ptr;
3781 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3782 ptr += 2;
3784 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3785 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3786 else
3787 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3788 ptr += 2;
3790 ptr += 4; /* skip res12 */
3792 pTypeLibImpl->libflags = *(WORD*)ptr;
3793 ptr += 2;
3795 pTypeLibImpl->ver_major = *(WORD*)ptr;
3796 ptr += 2;
3798 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3799 ptr += 2;
3801 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3802 ptr += sizeof(GUID);
3804 return ptr - (char*)pLibBlk;
3807 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3808 typedef struct
3810 unsigned int num;
3811 HREFTYPE refs[1];
3812 } sltg_ref_lookup_t;
3814 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3815 HREFTYPE *typelib_ref)
3817 if(table && typeinfo_ref < table->num)
3819 *typelib_ref = table->refs[typeinfo_ref];
3820 return S_OK;
3823 ERR_(typelib)("Unable to find reference\n");
3824 *typelib_ref = -1;
3825 return E_FAIL;
3828 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3830 BOOL done = FALSE;
3832 while(!done) {
3833 if((*pType & 0xe00) == 0xe00) {
3834 pTD->vt = VT_PTR;
3835 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3836 pTD = pTD->u.lptdesc;
3838 switch(*pType & 0x3f) {
3839 case VT_PTR:
3840 pTD->vt = VT_PTR;
3841 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3842 pTD = pTD->u.lptdesc;
3843 break;
3845 case VT_USERDEFINED:
3846 pTD->vt = VT_USERDEFINED;
3847 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3848 done = TRUE;
3849 break;
3851 case VT_CARRAY:
3853 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3854 array */
3856 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3858 pTD->vt = VT_CARRAY;
3859 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3860 pTD->u.lpadesc->cDims = pSA->cDims;
3861 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3862 pSA->cDims * sizeof(SAFEARRAYBOUND));
3864 pTD = &pTD->u.lpadesc->tdescElem;
3865 break;
3868 case VT_SAFEARRAY:
3870 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3871 useful? */
3873 pType++;
3874 pTD->vt = VT_SAFEARRAY;
3875 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3876 pTD = pTD->u.lptdesc;
3877 break;
3879 default:
3880 pTD->vt = *pType & 0x3f;
3881 done = TRUE;
3882 break;
3884 pType++;
3886 return pType;
3889 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3890 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3892 /* Handle [in/out] first */
3893 if((*pType & 0xc000) == 0xc000)
3894 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3895 else if(*pType & 0x8000)
3896 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3897 else if(*pType & 0x4000)
3898 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3899 else
3900 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3902 if(*pType & 0x2000)
3903 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3905 if(*pType & 0x80)
3906 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3908 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3912 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3913 char *pNameTable)
3915 unsigned int ref;
3916 char *name;
3917 TLBRefType *ref_type;
3918 sltg_ref_lookup_t *table;
3919 HREFTYPE typelib_ref;
3921 if(pRef->magic != SLTG_REF_MAGIC) {
3922 FIXME("Ref magic = %x\n", pRef->magic);
3923 return NULL;
3925 name = ( (char*)pRef->names + pRef->number);
3927 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3928 table->num = pRef->number >> 3;
3930 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3932 /* We don't want the first href to be 0 */
3933 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3935 for(ref = 0; ref < pRef->number >> 3; ref++) {
3936 char *refname;
3937 unsigned int lib_offs, type_num;
3939 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3941 name += SLTG_ReadStringA(name, &refname);
3942 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3943 FIXME_(typelib)("Can't sscanf ref\n");
3944 if(lib_offs != 0xffff) {
3945 TLBImpLib *import;
3947 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3948 if(import->offset == lib_offs)
3949 break;
3951 if(&import->entry == &pTL->implib_list) {
3952 char fname[MAX_PATH+1];
3953 int len;
3954 GUID tmpguid;
3956 import = heap_alloc_zero(sizeof(*import));
3957 import->offset = lib_offs;
3958 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3959 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3960 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3961 &import->wVersionMajor,
3962 &import->wVersionMinor,
3963 &import->lcid, fname) != 4) {
3964 FIXME_(typelib)("can't sscanf ref %s\n",
3965 pNameTable + lib_offs + 40);
3967 len = strlen(fname);
3968 if(fname[len-1] != '#')
3969 FIXME("fname = %s\n", fname);
3970 fname[len-1] = '\0';
3971 import->name = TLB_MultiByteToBSTR(fname);
3972 list_add_tail(&pTL->implib_list, &import->entry);
3974 ref_type->pImpTLInfo = import;
3976 /* Store a reference to IDispatch */
3977 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3978 pTL->dispatch_href = typelib_ref;
3980 } else { /* internal ref */
3981 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3983 ref_type->reference = typelib_ref;
3984 ref_type->index = type_num;
3986 heap_free(refname);
3987 list_add_tail(&pTL->ref_list, &ref_type->entry);
3989 table->refs[ref] = typelib_ref;
3990 typelib_ref += 4;
3992 if((BYTE)*name != SLTG_REF_MAGIC)
3993 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3994 dump_TLBRefType(pTL);
3995 return table;
3998 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3999 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
4001 SLTG_ImplInfo *info;
4002 TLBImplType *pImplType;
4003 /* I don't really get this structure, usually it's 0x16 bytes
4004 long, but iuser.tlb contains some that are 0x18 bytes long.
4005 That's ok because we can use the next ptr to jump to the next
4006 one. But how do we know the length of the last one? The WORD
4007 at offs 0x8 might be the clue. For now I'm just assuming that
4008 the last one is the regular 0x16 bytes. */
4010 info = (SLTG_ImplInfo*)pBlk;
4011 while(1){
4012 pTI->typeattr.cImplTypes++;
4013 if(info->next == 0xffff)
4014 break;
4015 info = (SLTG_ImplInfo*)(pBlk + info->next);
4018 info = (SLTG_ImplInfo*)pBlk;
4019 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
4020 pImplType = pTI->impltypes;
4021 while(1) {
4022 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4023 pImplType->implflags = info->impltypeflags;
4024 ++pImplType;
4026 if(info->next == 0xffff)
4027 break;
4028 if(OneOnly)
4029 FIXME_(typelib)("Interface inheriting more than one interface\n");
4030 info = (SLTG_ImplInfo*)(pBlk + info->next);
4032 info++; /* see comment at top of function */
4033 return (char*)info;
4036 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4037 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4039 TLBVarDesc *pVarDesc;
4040 const TLBString *prevName = NULL;
4041 SLTG_Variable *pItem;
4042 unsigned short i;
4043 WORD *pType;
4045 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4047 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4048 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4050 pVarDesc->vardesc.memid = pItem->memid;
4052 if (pItem->magic != SLTG_VAR_MAGIC &&
4053 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4054 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4055 return;
4058 if (pItem->name == 0xfffe)
4059 pVarDesc->Name = prevName;
4060 else
4061 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4063 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4064 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4065 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4067 if(pItem->flags & 0x02)
4068 pType = &pItem->type;
4069 else
4070 pType = (WORD*)(pBlk + pItem->type);
4072 if (pItem->flags & ~0xda)
4073 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4075 SLTG_DoElem(pType, pBlk,
4076 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4078 if (TRACE_ON(typelib)) {
4079 char buf[300];
4080 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4081 TRACE_(typelib)("elemdescVar: %s\n", buf);
4084 if (pItem->flags & 0x40) {
4085 TRACE_(typelib)("VAR_DISPATCH\n");
4086 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4088 else if (pItem->flags & 0x10) {
4089 TRACE_(typelib)("VAR_CONST\n");
4090 pVarDesc->vardesc.varkind = VAR_CONST;
4091 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4092 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4093 if (pItem->flags & 0x08)
4094 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4095 else {
4096 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4098 case VT_LPSTR:
4099 case VT_LPWSTR:
4100 case VT_BSTR:
4102 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4103 BSTR str;
4104 TRACE_(typelib)("len = %u\n", len);
4105 if (len == 0xffff) {
4106 str = NULL;
4107 } else {
4108 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4109 str = SysAllocStringLen(NULL, alloc_len);
4110 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4112 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4113 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4114 break;
4116 case VT_I2:
4117 case VT_UI2:
4118 case VT_I4:
4119 case VT_UI4:
4120 case VT_INT:
4121 case VT_UINT:
4122 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4123 *(INT*)(pBlk + pItem->byte_offs);
4124 break;
4125 default:
4126 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4130 else {
4131 TRACE_(typelib)("VAR_PERINSTANCE\n");
4132 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4133 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4136 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4137 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4139 if (pItem->flags & 0x80)
4140 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4142 prevName = pVarDesc->Name;
4144 pTI->typeattr.cVars = cVars;
4147 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4148 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4150 SLTG_Function *pFunc;
4151 unsigned short i;
4152 TLBFuncDesc *pFuncDesc;
4154 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4156 pFuncDesc = pTI->funcdescs;
4157 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4158 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4160 int param;
4161 WORD *pType, *pArg;
4163 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4164 case SLTG_FUNCTION_MAGIC:
4165 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4166 break;
4167 case SLTG_DISPATCH_FUNCTION_MAGIC:
4168 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4169 break;
4170 case SLTG_STATIC_FUNCTION_MAGIC:
4171 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4172 break;
4173 default:
4174 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4175 continue;
4177 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4179 pFuncDesc->funcdesc.memid = pFunc->dispid;
4180 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4181 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4182 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4183 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4184 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4186 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4187 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4189 if(pFunc->retnextopt & 0x80)
4190 pType = &pFunc->rettype;
4191 else
4192 pType = (WORD*)(pBlk + pFunc->rettype);
4194 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4196 pFuncDesc->funcdesc.lprgelemdescParam =
4197 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4198 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4200 pArg = (WORD*)(pBlk + pFunc->arg_off);
4202 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4203 char *paramName = pNameTable + *pArg;
4204 BOOL HaveOffs;
4205 /* If arg type follows then paramName points to the 2nd
4206 letter of the name, else the next WORD is an offset to
4207 the arg type and paramName points to the first letter.
4208 So let's take one char off paramName and see if we're
4209 pointing at an alpha-numeric char. However if *pArg is
4210 0xffff or 0xfffe then the param has no name, the former
4211 meaning that the next WORD is the type, the latter
4212 meaning that the next WORD is an offset to the type. */
4214 HaveOffs = FALSE;
4215 if(*pArg == 0xffff)
4216 paramName = NULL;
4217 else if(*pArg == 0xfffe) {
4218 paramName = NULL;
4219 HaveOffs = TRUE;
4221 else if(paramName[-1] && !isalnum(paramName[-1]))
4222 HaveOffs = TRUE;
4224 pArg++;
4226 if(HaveOffs) { /* the next word is an offset to type */
4227 pType = (WORD*)(pBlk + *pArg);
4228 SLTG_DoElem(pType, pBlk,
4229 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4230 pArg++;
4231 } else {
4232 if(paramName)
4233 paramName--;
4234 pArg = SLTG_DoElem(pArg, pBlk,
4235 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4238 /* Are we an optional param ? */
4239 if(pFuncDesc->funcdesc.cParams - param <=
4240 pFuncDesc->funcdesc.cParamsOpt)
4241 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4243 if(paramName) {
4244 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4245 paramName - pNameTable, pTI->pTypeLib);
4246 } else {
4247 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4251 pTI->typeattr.cFuncs = cFuncs;
4254 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4255 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4256 SLTG_TypeInfoTail *pTITail)
4258 char *pFirstItem;
4259 sltg_ref_lookup_t *ref_lookup = NULL;
4261 if(pTIHeader->href_table != 0xffffffff) {
4262 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4263 pNameTable);
4266 pFirstItem = pBlk;
4268 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4269 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4271 heap_free(ref_lookup);
4275 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4276 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4277 const SLTG_TypeInfoTail *pTITail)
4279 char *pFirstItem;
4280 sltg_ref_lookup_t *ref_lookup = NULL;
4282 if(pTIHeader->href_table != 0xffffffff) {
4283 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4284 pNameTable);
4287 pFirstItem = pBlk;
4289 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4290 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4293 if (pTITail->funcs_off != 0xffff)
4294 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4296 heap_free(ref_lookup);
4298 if (TRACE_ON(typelib))
4299 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4302 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4303 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4304 const SLTG_TypeInfoTail *pTITail)
4306 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4309 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4310 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4311 const SLTG_TypeInfoTail *pTITail)
4313 WORD *pType;
4314 sltg_ref_lookup_t *ref_lookup = NULL;
4316 if (pTITail->simple_alias) {
4317 /* if simple alias, no more processing required */
4318 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4319 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4320 return;
4323 if(pTIHeader->href_table != 0xffffffff) {
4324 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4325 pNameTable);
4328 /* otherwise it is an offset to a type */
4329 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4331 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4332 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4334 heap_free(ref_lookup);
4337 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4338 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4339 const SLTG_TypeInfoTail *pTITail)
4341 sltg_ref_lookup_t *ref_lookup = NULL;
4342 if (pTIHeader->href_table != 0xffffffff)
4343 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4344 pNameTable);
4346 if (pTITail->vars_off != 0xffff)
4347 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4349 if (pTITail->funcs_off != 0xffff)
4350 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4352 if (pTITail->impls_off != 0xffff)
4353 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4355 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4356 * of dispinterface functions including the IDispatch ones, so
4357 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4358 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4360 heap_free(ref_lookup);
4361 if (TRACE_ON(typelib))
4362 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4365 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4366 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4367 const SLTG_TypeInfoTail *pTITail)
4369 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4372 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4373 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4374 const SLTG_TypeInfoTail *pTITail)
4376 sltg_ref_lookup_t *ref_lookup = NULL;
4377 if (pTIHeader->href_table != 0xffffffff)
4378 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4379 pNameTable);
4381 if (pTITail->vars_off != 0xffff)
4382 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4384 if (pTITail->funcs_off != 0xffff)
4385 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4386 heap_free(ref_lookup);
4387 if (TRACE_ON(typelib))
4388 dump_TypeInfo(pTI);
4391 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4392 manageable copy of it into this */
4393 typedef struct {
4394 WORD small_no;
4395 char *index_name;
4396 char *other_name;
4397 WORD res1a;
4398 WORD name_offs;
4399 WORD more_bytes;
4400 char *extra;
4401 WORD res20;
4402 DWORD helpcontext;
4403 WORD res26;
4404 GUID uuid;
4405 } SLTG_InternalOtherTypeInfo;
4407 /****************************************************************************
4408 * ITypeLib2_Constructor_SLTG
4410 * loading a SLTG typelib from an in-memory image
4412 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4414 ITypeLibImpl *pTypeLibImpl;
4415 SLTG_Header *pHeader;
4416 SLTG_BlkEntry *pBlkEntry;
4417 SLTG_Magic *pMagic;
4418 SLTG_Index *pIndex;
4419 SLTG_Pad9 *pPad9;
4420 LPVOID pBlk, pFirstBlk;
4421 SLTG_LibBlk *pLibBlk;
4422 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4423 char *pAfterOTIBlks = NULL;
4424 char *pNameTable, *ptr;
4425 int i;
4426 DWORD len, order;
4427 ITypeInfoImpl **ppTypeInfoImpl;
4429 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4432 pTypeLibImpl = TypeLibImpl_Constructor();
4433 if (!pTypeLibImpl) return NULL;
4435 pHeader = pLib;
4437 TRACE_(typelib)("header:\n");
4438 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4439 pHeader->nrOfFileBlks );
4440 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4441 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4442 pHeader->SLTG_magic);
4443 return NULL;
4446 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4447 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4449 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4450 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4452 /* Next we have a magic block */
4453 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4455 /* Let's see if we're still in sync */
4456 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4457 sizeof(SLTG_COMPOBJ_MAGIC))) {
4458 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4459 return NULL;
4461 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4462 sizeof(SLTG_DIR_MAGIC))) {
4463 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4464 return NULL;
4467 pIndex = (SLTG_Index*)(pMagic+1);
4469 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4471 pFirstBlk = pPad9 + 1;
4473 /* We'll set up a ptr to the main library block, which is the last one. */
4475 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4476 pBlkEntry[order].next != 0;
4477 order = pBlkEntry[order].next - 1) {
4478 pBlk = (char*)pBlk + pBlkEntry[order].len;
4480 pLibBlk = pBlk;
4482 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4484 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4485 interspersed */
4487 len += 0x40;
4489 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4491 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4494 ptr = (char*)pLibBlk + len;
4496 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4497 WORD w, extra;
4498 len = 0;
4500 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4502 w = *(WORD*)(ptr + 2);
4503 if(w != 0xffff) {
4504 len += w;
4505 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4506 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4507 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4509 w = *(WORD*)(ptr + 4 + len);
4510 if(w != 0xffff) {
4511 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4512 len += w;
4513 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4514 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4515 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4517 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4518 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4519 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4520 if(extra) {
4521 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4522 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4523 len += extra;
4525 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4526 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4527 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4528 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4529 len += sizeof(SLTG_OtherTypeInfo);
4530 ptr += len;
4533 pAfterOTIBlks = ptr;
4535 /* Skip this WORD and get the next DWORD */
4536 len = *(DWORD*)(pAfterOTIBlks + 2);
4538 /* Now add this to pLibBLk look at what we're pointing at and
4539 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4540 dust and we should be pointing at the beginning of the name
4541 table */
4543 pNameTable = (char*)pLibBlk + len;
4545 switch(*(WORD*)pNameTable) {
4546 case 0xffff:
4547 break;
4548 case 0x0200:
4549 pNameTable += 0x20;
4550 break;
4551 default:
4552 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4553 break;
4556 pNameTable += 0x216;
4558 pNameTable += 2;
4560 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4562 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4565 /* Hopefully we now have enough ptrs set up to actually read in
4566 some TypeInfos. It's not clear which order to do them in, so
4567 I'll just follow the links along the BlkEntry chain and read
4568 them in the order in which they are in the file */
4570 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4571 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4573 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4574 pBlkEntry[order].next != 0;
4575 order = pBlkEntry[order].next - 1, i++) {
4577 SLTG_TypeInfoHeader *pTIHeader;
4578 SLTG_TypeInfoTail *pTITail;
4579 SLTG_MemberHeader *pMemHeader;
4581 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4582 FIXME_(typelib)("Index strings don't match\n");
4583 heap_free(pOtherTypeInfoBlks);
4584 return NULL;
4587 pTIHeader = pBlk;
4588 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4589 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4590 heap_free(pOtherTypeInfoBlks);
4591 return NULL;
4593 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4594 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4595 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4597 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4598 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4599 (*ppTypeInfoImpl)->index = i;
4600 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4601 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4602 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4603 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4604 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4605 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4606 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4607 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4609 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4610 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4612 if((pTIHeader->typeflags1 & 7) != 2)
4613 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4614 if(pTIHeader->typeflags3 != 2)
4615 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4617 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4618 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4619 typekind_desc[pTIHeader->typekind],
4620 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4621 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4623 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4625 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4627 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4628 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4629 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4631 switch(pTIHeader->typekind) {
4632 case TKIND_ENUM:
4633 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4634 pTIHeader, pTITail);
4635 break;
4637 case TKIND_RECORD:
4638 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4639 pTIHeader, pTITail);
4640 break;
4642 case TKIND_INTERFACE:
4643 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4644 pTIHeader, pTITail);
4645 break;
4647 case TKIND_COCLASS:
4648 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4649 pTIHeader, pTITail);
4650 break;
4652 case TKIND_ALIAS:
4653 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4654 pTIHeader, pTITail);
4655 break;
4657 case TKIND_DISPATCH:
4658 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4659 pTIHeader, pTITail);
4660 break;
4662 case TKIND_MODULE:
4663 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4664 pTIHeader, pTITail);
4665 break;
4667 default:
4668 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4669 break;
4673 /* could get cFuncs, cVars and cImplTypes from here
4674 but we've already set those */
4675 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4676 X(06);
4677 X(16);
4678 X(18);
4679 X(1a);
4680 X(1e);
4681 X(24);
4682 X(26);
4683 X(2a);
4684 X(2c);
4685 X(2e);
4686 X(30);
4687 X(32);
4688 X(34);
4689 #undef X
4690 ++ppTypeInfoImpl;
4691 pBlk = (char*)pBlk + pBlkEntry[order].len;
4694 if(i != pTypeLibImpl->TypeInfoCount) {
4695 FIXME("Somehow processed %d TypeInfos\n", i);
4696 heap_free(pOtherTypeInfoBlks);
4697 return NULL;
4700 heap_free(pOtherTypeInfoBlks);
4701 return &pTypeLibImpl->ITypeLib2_iface;
4704 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4706 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4708 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4710 if(IsEqualIID(riid, &IID_IUnknown) ||
4711 IsEqualIID(riid,&IID_ITypeLib)||
4712 IsEqualIID(riid,&IID_ITypeLib2))
4714 *ppv = &This->ITypeLib2_iface;
4716 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4717 IsEqualIID(riid, &IID_ICreateTypeLib2))
4719 *ppv = &This->ICreateTypeLib2_iface;
4721 else
4723 *ppv = NULL;
4724 TRACE("-- Interface: E_NOINTERFACE\n");
4725 return E_NOINTERFACE;
4728 IUnknown_AddRef((IUnknown*)*ppv);
4729 return S_OK;
4732 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4734 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4735 ULONG ref = InterlockedIncrement(&This->ref);
4737 TRACE("(%p) ref=%u\n", This, ref);
4739 return ref;
4742 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4744 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4745 ULONG ref = InterlockedDecrement(&This->ref);
4747 TRACE("(%p) ref=%u\n",This, ref);
4749 if (!ref)
4751 TLBImpLib *pImpLib, *pImpLibNext;
4752 TLBRefType *ref_type;
4753 TLBString *tlbstr, *tlbstr_next;
4754 TLBGuid *tlbguid, *tlbguid_next;
4755 void *cursor2;
4756 int i;
4758 /* remove cache entry */
4759 if(This->path)
4761 TRACE("removing from cache list\n");
4762 EnterCriticalSection(&cache_section);
4763 if(This->entry.next)
4764 list_remove(&This->entry);
4765 LeaveCriticalSection(&cache_section);
4766 heap_free(This->path);
4768 TRACE(" destroying ITypeLib(%p)\n",This);
4770 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4771 list_remove(&tlbstr->entry);
4772 SysFreeString(tlbstr->str);
4773 heap_free(tlbstr);
4776 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4777 list_remove(&tlbstr->entry);
4778 SysFreeString(tlbstr->str);
4779 heap_free(tlbstr);
4782 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4783 list_remove(&tlbguid->entry);
4784 heap_free(tlbguid);
4787 TLB_FreeCustData(&This->custdata_list);
4789 for (i = 0; i < This->ctTypeDesc; i++)
4790 if (This->pTypeDesc[i].vt == VT_CARRAY)
4791 heap_free(This->pTypeDesc[i].u.lpadesc);
4793 heap_free(This->pTypeDesc);
4795 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4797 if (pImpLib->pImpTypeLib)
4798 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4799 SysFreeString(pImpLib->name);
4801 list_remove(&pImpLib->entry);
4802 heap_free(pImpLib);
4805 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4807 list_remove(&ref_type->entry);
4808 heap_free(ref_type);
4811 for (i = 0; i < This->TypeInfoCount; ++i){
4812 heap_free(This->typeinfos[i]->tdescAlias);
4813 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4815 heap_free(This->typeinfos);
4816 heap_free(This);
4817 return 0;
4820 return ref;
4823 /* ITypeLib::GetTypeInfoCount
4825 * Returns the number of type descriptions in the type library
4827 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4829 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4830 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4831 return This->TypeInfoCount;
4834 /* ITypeLib::GetTypeInfo
4836 * retrieves the specified type description in the library.
4838 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4839 ITypeLib2 *iface,
4840 UINT index,
4841 ITypeInfo **ppTInfo)
4843 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4845 TRACE("%p %u %p\n", This, index, ppTInfo);
4847 if(!ppTInfo)
4848 return E_INVALIDARG;
4850 if(index >= This->TypeInfoCount)
4851 return TYPE_E_ELEMENTNOTFOUND;
4853 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4854 ITypeInfo_AddRef(*ppTInfo);
4856 return S_OK;
4860 /* ITypeLibs::GetTypeInfoType
4862 * Retrieves the type of a type description.
4864 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4865 ITypeLib2 *iface,
4866 UINT index,
4867 TYPEKIND *pTKind)
4869 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4871 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4873 if(!pTKind)
4874 return E_INVALIDARG;
4876 if(index >= This->TypeInfoCount)
4877 return TYPE_E_ELEMENTNOTFOUND;
4879 *pTKind = This->typeinfos[index]->typeattr.typekind;
4881 return S_OK;
4884 /* ITypeLib::GetTypeInfoOfGuid
4886 * Retrieves the type description that corresponds to the specified GUID.
4889 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4890 ITypeLib2 *iface,
4891 REFGUID guid,
4892 ITypeInfo **ppTInfo)
4894 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4895 int i;
4897 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4899 for(i = 0; i < This->TypeInfoCount; ++i){
4900 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4901 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4902 ITypeInfo_AddRef(*ppTInfo);
4903 return S_OK;
4907 return TYPE_E_ELEMENTNOTFOUND;
4910 /* ITypeLib::GetLibAttr
4912 * Retrieves the structure that contains the library's attributes.
4915 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4916 ITypeLib2 *iface,
4917 LPTLIBATTR *attr)
4919 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4921 TRACE("(%p, %p)\n", This, attr);
4923 if (!attr) return E_INVALIDARG;
4925 *attr = heap_alloc(sizeof(**attr));
4926 if (!*attr) return E_OUTOFMEMORY;
4928 (*attr)->guid = *TLB_get_guid_null(This->guid);
4929 (*attr)->lcid = This->set_lcid;
4930 (*attr)->syskind = This->syskind;
4931 (*attr)->wMajorVerNum = This->ver_major;
4932 (*attr)->wMinorVerNum = This->ver_minor;
4933 (*attr)->wLibFlags = This->libflags;
4935 return S_OK;
4938 /* ITypeLib::GetTypeComp
4940 * Enables a client compiler to bind to a library's types, variables,
4941 * constants, and global functions.
4944 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4945 ITypeLib2 *iface,
4946 ITypeComp **ppTComp)
4948 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4950 TRACE("(%p)->(%p)\n",This,ppTComp);
4951 *ppTComp = &This->ITypeComp_iface;
4952 ITypeComp_AddRef(*ppTComp);
4954 return S_OK;
4957 /* ITypeLib::GetDocumentation
4959 * Retrieves the library's documentation string, the complete Help file name
4960 * and path, and the context identifier for the library Help topic in the Help
4961 * file.
4963 * On a successful return all non-null BSTR pointers will have been set,
4964 * possibly to NULL.
4966 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4967 ITypeLib2 *iface,
4968 INT index,
4969 BSTR *pBstrName,
4970 BSTR *pBstrDocString,
4971 DWORD *pdwHelpContext,
4972 BSTR *pBstrHelpFile)
4974 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4975 HRESULT result = E_INVALIDARG;
4976 ITypeInfo *pTInfo;
4978 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4979 This, index,
4980 pBstrName, pBstrDocString,
4981 pdwHelpContext, pBstrHelpFile);
4983 if(index<0)
4985 /* documentation for the typelib */
4986 if(pBstrName)
4988 if (This->Name)
4990 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4991 goto memerr1;
4993 else
4994 *pBstrName = NULL;
4996 if(pBstrDocString)
4998 if (This->DocString)
5000 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
5001 goto memerr2;
5003 else
5004 *pBstrDocString = NULL;
5006 if(pdwHelpContext)
5008 *pdwHelpContext = This->dwHelpContext;
5010 if(pBstrHelpFile)
5012 if (This->HelpFile)
5014 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5015 goto memerr3;
5017 else
5018 *pBstrHelpFile = NULL;
5021 result = S_OK;
5023 else
5025 /* for a typeinfo */
5026 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5028 if(SUCCEEDED(result))
5030 result = ITypeInfo_GetDocumentation(pTInfo,
5031 MEMBERID_NIL,
5032 pBstrName,
5033 pBstrDocString,
5034 pdwHelpContext, pBstrHelpFile);
5036 ITypeInfo_Release(pTInfo);
5039 return result;
5040 memerr3:
5041 if (pBstrDocString) SysFreeString (*pBstrDocString);
5042 memerr2:
5043 if (pBstrName) SysFreeString (*pBstrName);
5044 memerr1:
5045 return STG_E_INSUFFICIENTMEMORY;
5048 /* ITypeLib::IsName
5050 * Indicates whether a passed-in string contains the name of a type or member
5051 * described in the library.
5054 static HRESULT WINAPI ITypeLib2_fnIsName(
5055 ITypeLib2 *iface,
5056 LPOLESTR szNameBuf,
5057 ULONG lHashVal,
5058 BOOL *pfName)
5060 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5061 int tic;
5062 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5064 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5065 pfName);
5067 *pfName=TRUE;
5068 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5069 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5070 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5071 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5072 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5073 int pc;
5074 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5075 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5076 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5077 goto ITypeLib2_fnIsName_exit;
5080 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5081 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5082 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5086 *pfName=FALSE;
5088 ITypeLib2_fnIsName_exit:
5089 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5090 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5092 return S_OK;
5095 /* ITypeLib::FindName
5097 * Finds occurrences of a type description in a type library. This may be used
5098 * to quickly verify that a name exists in a type library.
5101 static HRESULT WINAPI ITypeLib2_fnFindName(
5102 ITypeLib2 *iface,
5103 LPOLESTR name,
5104 ULONG hash,
5105 ITypeInfo **ppTInfo,
5106 MEMBERID *memid,
5107 UINT16 *found)
5109 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5110 int tic;
5111 UINT count = 0;
5112 UINT len;
5114 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5116 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5117 return E_INVALIDARG;
5119 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5120 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5121 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5122 TLBVarDesc *var;
5123 UINT fdc;
5125 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5126 memid[count] = MEMBERID_NIL;
5127 goto ITypeLib2_fnFindName_exit;
5130 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5131 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5133 if(!TLB_str_memcmp(name, func->Name, len)) {
5134 memid[count] = func->funcdesc.memid;
5135 goto ITypeLib2_fnFindName_exit;
5139 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->typeattr.cVars, name);
5140 if (var) {
5141 memid[count] = var->vardesc.memid;
5142 goto ITypeLib2_fnFindName_exit;
5145 continue;
5146 ITypeLib2_fnFindName_exit:
5147 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5148 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5149 count++;
5151 TRACE("found %d typeinfos\n", count);
5153 *found = count;
5155 return S_OK;
5158 /* ITypeLib::ReleaseTLibAttr
5160 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5163 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5164 ITypeLib2 *iface,
5165 TLIBATTR *pTLibAttr)
5167 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5168 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5169 heap_free(pTLibAttr);
5172 /* ITypeLib2::GetCustData
5174 * gets the custom data
5176 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5177 ITypeLib2 * iface,
5178 REFGUID guid,
5179 VARIANT *pVarVal)
5181 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5182 TLBCustData *pCData;
5184 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5186 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5187 if(!pCData)
5188 return TYPE_E_ELEMENTNOTFOUND;
5190 VariantInit(pVarVal);
5191 VariantCopy(pVarVal, &pCData->data);
5193 return S_OK;
5196 /* ITypeLib2::GetLibStatistics
5198 * Returns statistics about a type library that are required for efficient
5199 * sizing of hash tables.
5202 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5203 ITypeLib2 * iface,
5204 ULONG *pcUniqueNames,
5205 ULONG *pcchUniqueNames)
5207 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5209 FIXME("(%p): stub!\n", This);
5211 if(pcUniqueNames) *pcUniqueNames=1;
5212 if(pcchUniqueNames) *pcchUniqueNames=1;
5213 return S_OK;
5216 /* ITypeLib2::GetDocumentation2
5218 * Retrieves the library's documentation string, the complete Help file name
5219 * and path, the localization context to use, and the context ID for the
5220 * library Help topic in the Help file.
5223 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5224 ITypeLib2 * iface,
5225 INT index,
5226 LCID lcid,
5227 BSTR *pbstrHelpString,
5228 DWORD *pdwHelpStringContext,
5229 BSTR *pbstrHelpStringDll)
5231 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5232 HRESULT result;
5233 ITypeInfo *pTInfo;
5235 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5237 /* the help string should be obtained from the helpstringdll,
5238 * using the _DLLGetDocumentation function, based on the supplied
5239 * lcid. Nice to do sometime...
5241 if(index<0)
5243 /* documentation for the typelib */
5244 if(pbstrHelpString)
5245 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5246 if(pdwHelpStringContext)
5247 *pdwHelpStringContext=This->dwHelpContext;
5248 if(pbstrHelpStringDll)
5249 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5251 result = S_OK;
5253 else
5255 /* for a typeinfo */
5256 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5258 if(SUCCEEDED(result))
5260 ITypeInfo2 * pTInfo2;
5261 result = ITypeInfo_QueryInterface(pTInfo,
5262 &IID_ITypeInfo2,
5263 (LPVOID*) &pTInfo2);
5265 if(SUCCEEDED(result))
5267 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5268 MEMBERID_NIL,
5269 lcid,
5270 pbstrHelpString,
5271 pdwHelpStringContext,
5272 pbstrHelpStringDll);
5274 ITypeInfo2_Release(pTInfo2);
5277 ITypeInfo_Release(pTInfo);
5280 return result;
5283 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5285 TLBCustData *pCData;
5286 unsigned int ct;
5287 CUSTDATAITEM *cdi;
5289 ct = list_count(custdata_list);
5291 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5292 if(!pCustData->prgCustData)
5293 return E_OUTOFMEMORY;
5295 pCustData->cCustData = ct;
5297 cdi = pCustData->prgCustData;
5298 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5299 cdi->guid = *TLB_get_guid_null(pCData->guid);
5300 VariantCopy(&cdi->varValue, &pCData->data);
5301 ++cdi;
5304 return S_OK;
5308 /* ITypeLib2::GetAllCustData
5310 * Gets all custom data items for the library.
5313 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5314 ITypeLib2 * iface,
5315 CUSTDATA *pCustData)
5317 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5318 TRACE("(%p)->(%p)\n", This, pCustData);
5319 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5322 static const ITypeLib2Vtbl tlbvt = {
5323 ITypeLib2_fnQueryInterface,
5324 ITypeLib2_fnAddRef,
5325 ITypeLib2_fnRelease,
5326 ITypeLib2_fnGetTypeInfoCount,
5327 ITypeLib2_fnGetTypeInfo,
5328 ITypeLib2_fnGetTypeInfoType,
5329 ITypeLib2_fnGetTypeInfoOfGuid,
5330 ITypeLib2_fnGetLibAttr,
5331 ITypeLib2_fnGetTypeComp,
5332 ITypeLib2_fnGetDocumentation,
5333 ITypeLib2_fnIsName,
5334 ITypeLib2_fnFindName,
5335 ITypeLib2_fnReleaseTLibAttr,
5337 ITypeLib2_fnGetCustData,
5338 ITypeLib2_fnGetLibStatistics,
5339 ITypeLib2_fnGetDocumentation2,
5340 ITypeLib2_fnGetAllCustData
5344 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5346 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5348 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5351 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5353 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5355 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5358 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5360 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5362 return ITypeLib2_Release(&This->ITypeLib2_iface);
5365 static HRESULT WINAPI ITypeLibComp_fnBind(
5366 ITypeComp * iface,
5367 OLECHAR * szName,
5368 ULONG lHash,
5369 WORD wFlags,
5370 ITypeInfo ** ppTInfo,
5371 DESCKIND * pDescKind,
5372 BINDPTR * pBindPtr)
5374 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5375 BOOL typemismatch = FALSE;
5376 int i;
5378 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5380 *pDescKind = DESCKIND_NONE;
5381 pBindPtr->lptcomp = NULL;
5382 *ppTInfo = NULL;
5384 for(i = 0; i < This->TypeInfoCount; ++i){
5385 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5386 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5388 /* FIXME: check wFlags here? */
5389 /* FIXME: we should use a hash table to look this info up using lHash
5390 * instead of an O(n) search */
5391 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5392 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5394 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5396 *pDescKind = DESCKIND_TYPECOMP;
5397 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5398 ITypeComp_AddRef(pBindPtr->lptcomp);
5399 TRACE("module or enum: %s\n", debugstr_w(szName));
5400 return S_OK;
5404 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5405 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5407 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5408 HRESULT hr;
5410 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5411 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5413 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5414 return S_OK;
5416 else if (hr == TYPE_E_TYPEMISMATCH)
5417 typemismatch = TRUE;
5420 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5421 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5423 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5424 HRESULT hr;
5425 ITypeInfo *subtypeinfo;
5426 BINDPTR subbindptr;
5427 DESCKIND subdesckind;
5429 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5430 &subtypeinfo, &subdesckind, &subbindptr);
5431 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5433 TYPEDESC tdesc_appobject;
5434 const VARDESC vardesc_appobject =
5436 -2, /* memid */
5437 NULL, /* lpstrSchema */
5439 0 /* oInst */
5442 /* ELEMDESC */
5444 /* TYPEDESC */
5446 &tdesc_appobject
5448 VT_PTR
5451 0, /* wVarFlags */
5452 VAR_STATIC /* varkind */
5455 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5456 tdesc_appobject.vt = VT_USERDEFINED;
5458 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5460 /* cleanup things filled in by Bind call so we can put our
5461 * application object data in there instead */
5462 switch (subdesckind)
5464 case DESCKIND_FUNCDESC:
5465 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5466 break;
5467 case DESCKIND_VARDESC:
5468 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5469 break;
5470 default:
5471 break;
5473 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5475 if (pTypeInfo->hreftype == -1)
5476 FIXME("no hreftype for interface %p\n", pTypeInfo);
5478 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5479 if (FAILED(hr))
5480 return hr;
5482 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5483 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5484 ITypeInfo_AddRef(*ppTInfo);
5485 return S_OK;
5487 else if (hr == TYPE_E_TYPEMISMATCH)
5488 typemismatch = TRUE;
5492 if (typemismatch)
5494 TRACE("type mismatch %s\n", debugstr_w(szName));
5495 return TYPE_E_TYPEMISMATCH;
5497 else
5499 TRACE("name not found %s\n", debugstr_w(szName));
5500 return S_OK;
5504 static HRESULT WINAPI ITypeLibComp_fnBindType(
5505 ITypeComp * iface,
5506 OLECHAR * szName,
5507 ULONG lHash,
5508 ITypeInfo ** ppTInfo,
5509 ITypeComp ** ppTComp)
5511 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5512 ITypeInfoImpl *info;
5514 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5516 if(!szName || !ppTInfo || !ppTComp)
5517 return E_INVALIDARG;
5519 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5520 if(!info){
5521 *ppTInfo = NULL;
5522 *ppTComp = NULL;
5523 return S_OK;
5526 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5527 ITypeInfo_AddRef(*ppTInfo);
5528 *ppTComp = &info->ITypeComp_iface;
5529 ITypeComp_AddRef(*ppTComp);
5531 return S_OK;
5534 static const ITypeCompVtbl tlbtcvt =
5537 ITypeLibComp_fnQueryInterface,
5538 ITypeLibComp_fnAddRef,
5539 ITypeLibComp_fnRelease,
5541 ITypeLibComp_fnBind,
5542 ITypeLibComp_fnBindType
5545 /*================== ITypeInfo(2) Methods ===================================*/
5546 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5548 ITypeInfoImpl *pTypeInfoImpl;
5550 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5551 if (pTypeInfoImpl)
5553 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5554 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5555 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5556 pTypeInfoImpl->ref = 0;
5557 pTypeInfoImpl->hreftype = -1;
5558 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5559 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5560 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5561 list_init(pTypeInfoImpl->pcustdata_list);
5563 TRACE("(%p)\n", pTypeInfoImpl);
5564 return pTypeInfoImpl;
5567 /* ITypeInfo::QueryInterface
5569 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5570 ITypeInfo2 *iface,
5571 REFIID riid,
5572 VOID **ppvObject)
5574 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5576 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5578 *ppvObject=NULL;
5579 if(IsEqualIID(riid, &IID_IUnknown) ||
5580 IsEqualIID(riid,&IID_ITypeInfo)||
5581 IsEqualIID(riid,&IID_ITypeInfo2))
5582 *ppvObject = This;
5583 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5584 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5585 *ppvObject = &This->ICreateTypeInfo2_iface;
5586 else if(IsEqualIID(riid, &IID_ITypeComp))
5587 *ppvObject = &This->ITypeComp_iface;
5589 if(*ppvObject){
5590 IUnknown_AddRef((IUnknown*)*ppvObject);
5591 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5592 return S_OK;
5594 TRACE("-- Interface: E_NOINTERFACE\n");
5595 return E_NOINTERFACE;
5598 /* ITypeInfo::AddRef
5600 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5602 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5603 ULONG ref = InterlockedIncrement(&This->ref);
5605 TRACE("(%p)->ref is %u\n",This, ref);
5607 if (ref == 1 /* incremented from 0 */)
5608 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5610 return ref;
5613 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5615 UINT i;
5617 TRACE("destroying ITypeInfo(%p)\n",This);
5619 for (i = 0; i < This->typeattr.cFuncs; ++i)
5621 int j;
5622 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5623 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5625 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5626 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5627 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5628 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5630 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5631 heap_free(pFInfo->pParamDesc);
5632 TLB_FreeCustData(&pFInfo->custdata_list);
5634 heap_free(This->funcdescs);
5636 for(i = 0; i < This->typeattr.cVars; ++i)
5638 TLBVarDesc *pVInfo = &This->vardescs[i];
5639 if (pVInfo->vardesc_create) {
5640 TLB_FreeVarDesc(pVInfo->vardesc_create);
5641 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5642 VariantClear(pVInfo->vardesc.u.lpvarValue);
5643 heap_free(pVInfo->vardesc.u.lpvarValue);
5645 TLB_FreeCustData(&pVInfo->custdata_list);
5647 heap_free(This->vardescs);
5649 if(This->impltypes){
5650 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5651 TLBImplType *pImpl = &This->impltypes[i];
5652 TLB_FreeCustData(&pImpl->custdata_list);
5654 heap_free(This->impltypes);
5657 TLB_FreeCustData(&This->custdata_list);
5659 heap_free(This);
5662 /* ITypeInfo::Release
5664 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5666 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5667 ULONG ref = InterlockedDecrement(&This->ref);
5669 TRACE("(%p)->(%u)\n",This, ref);
5671 if (!ref)
5673 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5674 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5675 if (not_attached_to_typelib)
5676 heap_free(This);
5677 /* otherwise This will be freed when typelib is freed */
5680 return ref;
5683 /* ITypeInfo::GetTypeAttr
5685 * Retrieves a TYPEATTR structure that contains the attributes of the type
5686 * description.
5689 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5690 LPTYPEATTR *ppTypeAttr)
5692 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5693 SIZE_T size;
5695 TRACE("(%p)\n",This);
5697 size = sizeof(**ppTypeAttr);
5698 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5699 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5701 *ppTypeAttr = heap_alloc(size);
5702 if (!*ppTypeAttr)
5703 return E_OUTOFMEMORY;
5705 **ppTypeAttr = This->typeattr;
5706 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5708 if (This->tdescAlias)
5709 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5711 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5712 /* This should include all the inherited funcs */
5713 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5714 /* This is always the size of IDispatch's vtbl */
5715 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5716 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5718 return S_OK;
5721 /* ITypeInfo::GetTypeComp
5723 * Retrieves the ITypeComp interface for the type description, which enables a
5724 * client compiler to bind to the type description's members.
5727 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5728 ITypeComp * *ppTComp)
5730 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5732 TRACE("(%p)->(%p)\n", This, ppTComp);
5734 *ppTComp = &This->ITypeComp_iface;
5735 ITypeComp_AddRef(*ppTComp);
5736 return S_OK;
5739 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5741 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5742 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5743 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5744 return size;
5747 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5749 *dest = *src;
5750 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5751 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5753 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5754 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5755 *buffer += sizeof(PARAMDESCEX);
5756 *pparamdescex_dest = *pparamdescex_src;
5757 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5758 VariantInit(&pparamdescex_dest->varDefaultValue);
5759 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5760 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5762 else
5763 dest->u.paramdesc.pparamdescex = NULL;
5764 return S_OK;
5767 static HRESULT TLB_SanitizeBSTR(BSTR str)
5769 UINT len = SysStringLen(str), i;
5770 for (i = 0; i < len; ++i)
5771 if (str[i] > 0x7f)
5772 str[i] = '?';
5773 return S_OK;
5776 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5778 if (V_VT(var) == VT_INT)
5779 return VariantChangeType(var, var, 0, VT_I4);
5780 else if (V_VT(var) == VT_UINT)
5781 return VariantChangeType(var, var, 0, VT_UI4);
5782 else if (V_VT(var) == VT_BSTR)
5783 return TLB_SanitizeBSTR(V_BSTR(var));
5785 return S_OK;
5788 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5790 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5791 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5794 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5796 FUNCDESC *dest;
5797 char *buffer;
5798 SIZE_T size = sizeof(*src);
5799 SHORT i;
5800 HRESULT hr;
5802 size += sizeof(*src->lprgscode) * src->cScodes;
5803 size += TLB_SizeElemDesc(&src->elemdescFunc);
5804 for (i = 0; i < src->cParams; i++)
5806 size += sizeof(ELEMDESC);
5807 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5810 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5811 if (!dest) return E_OUTOFMEMORY;
5813 *dest = *src;
5814 if (dispinterface) /* overwrite funckind */
5815 dest->funckind = FUNC_DISPATCH;
5816 buffer = (char *)(dest + 1);
5818 dest->oVft = dest->oVft & 0xFFFC;
5820 if (dest->cScodes) {
5821 dest->lprgscode = (SCODE *)buffer;
5822 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5823 buffer += sizeof(*src->lprgscode) * src->cScodes;
5824 } else
5825 dest->lprgscode = NULL;
5827 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5828 if (FAILED(hr))
5830 SysFreeString((BSTR)dest);
5831 return hr;
5834 if (dest->cParams) {
5835 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5836 buffer += sizeof(ELEMDESC) * src->cParams;
5837 for (i = 0; i < src->cParams; i++)
5839 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5840 if (FAILED(hr))
5841 break;
5843 if (FAILED(hr))
5845 /* undo the above actions */
5846 for (i = i - 1; i >= 0; i--)
5847 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5848 TLB_FreeElemDesc(&dest->elemdescFunc);
5849 SysFreeString((BSTR)dest);
5850 return hr;
5852 } else
5853 dest->lprgelemdescParam = NULL;
5855 /* special treatment for dispinterfaces: this makes functions appear
5856 * to return their [retval] value when it is really returning an
5857 * HRESULT */
5858 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5860 if (dest->cParams &&
5861 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5863 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5864 if (elemdesc->tdesc.vt != VT_PTR)
5866 ERR("elemdesc should have started with VT_PTR instead of:\n");
5867 if (ERR_ON(ole))
5868 dump_ELEMDESC(elemdesc);
5869 return E_UNEXPECTED;
5872 /* copy last parameter to the return value. we are using a flat
5873 * buffer so there is no danger of leaking memory in
5874 * elemdescFunc */
5875 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5877 /* remove the last parameter */
5878 dest->cParams--;
5880 else
5881 /* otherwise this function is made to appear to have no return
5882 * value */
5883 dest->elemdescFunc.tdesc.vt = VT_VOID;
5887 *dest_ptr = dest;
5888 return S_OK;
5891 static void TLB_FreeVarDesc(VARDESC *var_desc)
5893 TLB_FreeElemDesc(&var_desc->elemdescVar);
5894 if (var_desc->varkind == VAR_CONST)
5895 VariantClear(var_desc->u.lpvarValue);
5896 SysFreeString((BSTR)var_desc);
5899 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5901 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5903 if (index >= This->typeattr.cFuncs)
5904 return TYPE_E_ELEMENTNOTFOUND;
5906 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5907 return S_OK;
5910 /* internal function to make the inherited interfaces' methods appear
5911 * part of the interface */
5912 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5913 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5915 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5916 HRESULT hr;
5917 UINT implemented_funcs = 0;
5919 if (funcs)
5920 *funcs = 0;
5921 else
5922 *hrefoffset = DISPATCH_HREF_OFFSET;
5924 if(This->impltypes)
5926 ITypeInfo *pSubTypeInfo;
5927 UINT sub_funcs;
5929 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5930 if (FAILED(hr))
5931 return hr;
5933 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5934 index,
5935 ppFuncDesc,
5936 &sub_funcs, hrefoffset);
5937 implemented_funcs += sub_funcs;
5938 ITypeInfo_Release(pSubTypeInfo);
5939 if (SUCCEEDED(hr))
5940 return hr;
5941 *hrefoffset += DISPATCH_HREF_OFFSET;
5944 if (funcs)
5945 *funcs = implemented_funcs + This->typeattr.cFuncs;
5946 else
5947 *hrefoffset = 0;
5949 if (index < implemented_funcs)
5950 return E_INVALIDARG;
5951 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5952 ppFuncDesc);
5955 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5957 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5958 while (TRUE)
5960 switch (pTypeDesc->vt)
5962 case VT_USERDEFINED:
5963 pTypeDesc->u.hreftype += hrefoffset;
5964 return;
5965 case VT_PTR:
5966 case VT_SAFEARRAY:
5967 pTypeDesc = pTypeDesc->u.lptdesc;
5968 break;
5969 case VT_CARRAY:
5970 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5971 break;
5972 default:
5973 return;
5978 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5980 SHORT i;
5981 for (i = 0; i < pFuncDesc->cParams; i++)
5982 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5983 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5986 /* ITypeInfo::GetFuncDesc
5988 * Retrieves the FUNCDESC structure that contains information about a
5989 * specified function.
5992 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5993 LPFUNCDESC *ppFuncDesc)
5995 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5996 const FUNCDESC *internal_funcdesc;
5997 HRESULT hr;
5998 UINT hrefoffset = 0;
6000 TRACE("(%p) index %d\n", This, index);
6002 if (!ppFuncDesc)
6003 return E_INVALIDARG;
6005 if (This->needs_layout)
6006 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6008 if (This->typeattr.typekind == TKIND_DISPATCH)
6009 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6010 &internal_funcdesc, NULL,
6011 &hrefoffset);
6012 else
6013 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6014 &internal_funcdesc);
6015 if (FAILED(hr))
6017 WARN("description for function %d not found\n", index);
6018 return hr;
6021 hr = TLB_AllocAndInitFuncDesc(
6022 internal_funcdesc,
6023 ppFuncDesc,
6024 This->typeattr.typekind == TKIND_DISPATCH);
6026 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6027 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6029 TRACE("-- 0x%08x\n", hr);
6030 return hr;
6033 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6035 VARDESC *dest;
6036 char *buffer;
6037 SIZE_T size = sizeof(*src);
6038 HRESULT hr;
6040 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6041 if (src->varkind == VAR_CONST)
6042 size += sizeof(VARIANT);
6043 size += TLB_SizeElemDesc(&src->elemdescVar);
6045 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6046 if (!dest) return E_OUTOFMEMORY;
6048 *dest = *src;
6049 buffer = (char *)(dest + 1);
6050 if (src->lpstrSchema)
6052 int len;
6053 dest->lpstrSchema = (LPOLESTR)buffer;
6054 len = strlenW(src->lpstrSchema);
6055 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6056 buffer += (len + 1) * sizeof(WCHAR);
6059 if (src->varkind == VAR_CONST)
6061 HRESULT hr;
6063 dest->u.lpvarValue = (VARIANT *)buffer;
6064 *dest->u.lpvarValue = *src->u.lpvarValue;
6065 buffer += sizeof(VARIANT);
6066 VariantInit(dest->u.lpvarValue);
6067 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6068 if (FAILED(hr))
6070 SysFreeString((BSTR)dest);
6071 return hr;
6074 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6075 if (FAILED(hr))
6077 if (src->varkind == VAR_CONST)
6078 VariantClear(dest->u.lpvarValue);
6079 SysFreeString((BSTR)dest);
6080 return hr;
6082 *dest_ptr = dest;
6083 return S_OK;
6086 /* ITypeInfo::GetVarDesc
6088 * Retrieves a VARDESC structure that describes the specified variable.
6091 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6092 LPVARDESC *ppVarDesc)
6094 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6095 const TLBVarDesc *pVDesc = &This->vardescs[index];
6097 TRACE("(%p) index %d\n", This, index);
6099 if(index >= This->typeattr.cVars)
6100 return TYPE_E_ELEMENTNOTFOUND;
6102 if (This->needs_layout)
6103 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6105 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6108 /* ITypeInfo_GetNames
6110 * Retrieves the variable with the specified member ID (or the name of the
6111 * property or method and its parameters) that correspond to the specified
6112 * function ID.
6114 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6115 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6117 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6118 const TLBFuncDesc *pFDesc;
6119 const TLBVarDesc *pVDesc;
6120 int i;
6121 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6123 if(!rgBstrNames)
6124 return E_INVALIDARG;
6126 *pcNames = 0;
6128 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
6129 if(pFDesc)
6131 if(!cMaxNames || !pFDesc->Name)
6132 return S_OK;
6134 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6135 ++(*pcNames);
6137 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6138 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6139 return S_OK;
6140 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6141 ++(*pcNames);
6143 return S_OK;
6146 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
6147 if(pVDesc)
6149 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6150 *pcNames=1;
6152 else
6154 if(This->impltypes &&
6155 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
6156 /* recursive search */
6157 ITypeInfo *pTInfo;
6158 HRESULT result;
6159 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6160 if(SUCCEEDED(result))
6162 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6163 ITypeInfo_Release(pTInfo);
6164 return result;
6166 WARN("Could not search inherited interface!\n");
6168 else
6170 WARN("no names found\n");
6172 *pcNames=0;
6173 return TYPE_E_ELEMENTNOTFOUND;
6175 return S_OK;
6179 /* ITypeInfo::GetRefTypeOfImplType
6181 * If a type description describes a COM class, it retrieves the type
6182 * description of the implemented interface types. For an interface,
6183 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6184 * if any exist.
6187 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6188 ITypeInfo2 *iface,
6189 UINT index,
6190 HREFTYPE *pRefType)
6192 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6193 HRESULT hr = S_OK;
6195 TRACE("(%p) index %d\n", This, index);
6196 if (TRACE_ON(ole)) dump_TypeInfo(This);
6198 if(index==(UINT)-1)
6200 /* only valid on dual interfaces;
6201 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6204 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6206 *pRefType = -2;
6208 else
6210 hr = TYPE_E_ELEMENTNOTFOUND;
6213 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6215 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6216 *pRefType = This->pTypeLib->dispatch_href;
6218 else
6220 if(index >= This->typeattr.cImplTypes)
6221 hr = TYPE_E_ELEMENTNOTFOUND;
6222 else{
6223 *pRefType = This->impltypes[index].hRef;
6224 if (This->typeattr.typekind == TKIND_INTERFACE)
6225 *pRefType |= 0x2;
6229 if(TRACE_ON(ole))
6231 if(SUCCEEDED(hr))
6232 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6233 else
6234 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6237 return hr;
6240 /* ITypeInfo::GetImplTypeFlags
6242 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6243 * or base interface in a type description.
6245 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6246 UINT index, INT *pImplTypeFlags)
6248 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6250 TRACE("(%p) index %d\n", This, index);
6252 if(!pImplTypeFlags)
6253 return E_INVALIDARG;
6255 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6256 *pImplTypeFlags = 0;
6257 return S_OK;
6260 if(index >= This->typeattr.cImplTypes)
6261 return TYPE_E_ELEMENTNOTFOUND;
6263 *pImplTypeFlags = This->impltypes[index].implflags;
6265 return S_OK;
6268 /* GetIDsOfNames
6269 * Maps between member names and member IDs, and parameter names and
6270 * parameter IDs.
6272 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6273 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6275 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6276 const TLBVarDesc *pVDesc;
6277 HRESULT ret=S_OK;
6278 UINT i, fdc;
6280 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6281 cNames);
6283 /* init out parameters in case of failure */
6284 for (i = 0; i < cNames; i++)
6285 pMemId[i] = MEMBERID_NIL;
6287 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6288 int j;
6289 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6290 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6291 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6292 for(i=1; i < cNames; i++){
6293 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6294 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6295 break;
6296 if( j<pFDesc->funcdesc.cParams)
6297 pMemId[i]=j;
6298 else
6299 ret=DISP_E_UNKNOWNNAME;
6301 TRACE("-- 0x%08x\n", ret);
6302 return ret;
6305 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, *rgszNames);
6306 if(pVDesc){
6307 if(cNames)
6308 *pMemId = pVDesc->vardesc.memid;
6309 return ret;
6311 /* not found, see if it can be found in an inherited interface */
6312 if(This->impltypes) {
6313 /* recursive search */
6314 ITypeInfo *pTInfo;
6315 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6316 if(SUCCEEDED(ret)){
6317 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6318 ITypeInfo_Release(pTInfo);
6319 return ret;
6321 WARN("Could not search inherited interface!\n");
6322 } else
6323 WARN("no names found\n");
6324 return DISP_E_UNKNOWNNAME;
6328 #ifdef __i386__
6330 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6331 __ASM_GLOBAL_FUNC( call_method,
6332 "pushl %ebp\n\t"
6333 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6334 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6335 "movl %esp,%ebp\n\t"
6336 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6337 "pushl %esi\n\t"
6338 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6339 "pushl %edi\n\t"
6340 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6341 "movl 12(%ebp),%edx\n\t"
6342 "movl %esp,%edi\n\t"
6343 "shll $2,%edx\n\t"
6344 "jz 1f\n\t"
6345 "subl %edx,%edi\n\t"
6346 "andl $~15,%edi\n\t"
6347 "movl %edi,%esp\n\t"
6348 "movl 12(%ebp),%ecx\n\t"
6349 "movl 16(%ebp),%esi\n\t"
6350 "cld\n\t"
6351 "rep; movsl\n"
6352 "1:\tcall *8(%ebp)\n\t"
6353 "subl %esp,%edi\n\t"
6354 "movl 20(%ebp),%ecx\n\t"
6355 "movl %edi,(%ecx)\n\t"
6356 "leal -8(%ebp),%esp\n\t"
6357 "popl %edi\n\t"
6358 __ASM_CFI(".cfi_same_value %edi\n\t")
6359 "popl %esi\n\t"
6360 __ASM_CFI(".cfi_same_value %esi\n\t")
6361 "popl %ebp\n\t"
6362 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6363 __ASM_CFI(".cfi_same_value %ebp\n\t")
6364 "ret" )
6366 /* same function but returning floating point */
6367 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6369 /* ITypeInfo::Invoke
6371 * Invokes a method, or accesses a property of an object, that implements the
6372 * interface described by the type description.
6374 DWORD
6375 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6376 DWORD res;
6377 int stack_offset;
6379 if (TRACE_ON(ole)) {
6380 int i;
6381 TRACE("Calling %p(",func);
6382 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6383 if (nrargs > 30) TRACE("...");
6384 TRACE(")\n");
6387 switch (callconv) {
6388 case CC_STDCALL:
6389 case CC_CDECL:
6390 res = call_method( func, nrargs, args, &stack_offset );
6391 break;
6392 default:
6393 FIXME("unsupported calling convention %d\n",callconv);
6394 res = -1;
6395 break;
6397 TRACE("returns %08x\n",res);
6398 return res;
6401 #elif defined(__x86_64__)
6403 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6404 __ASM_GLOBAL_FUNC( call_method,
6405 "pushq %rbp\n\t"
6406 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6407 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6408 "movq %rsp,%rbp\n\t"
6409 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6410 "pushq %rsi\n\t"
6411 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6412 "pushq %rdi\n\t"
6413 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6414 "movq %rcx,%rax\n\t"
6415 "movq $4,%rcx\n\t"
6416 "cmp %rcx,%rdx\n\t"
6417 "cmovgq %rdx,%rcx\n\t"
6418 "leaq 0(,%rcx,8),%rdx\n\t"
6419 "subq %rdx,%rsp\n\t"
6420 "andq $~15,%rsp\n\t"
6421 "movq %rsp,%rdi\n\t"
6422 "movq %r8,%rsi\n\t"
6423 "rep; movsq\n\t"
6424 "movq 0(%rsp),%rcx\n\t"
6425 "movq 8(%rsp),%rdx\n\t"
6426 "movq 16(%rsp),%r8\n\t"
6427 "movq 24(%rsp),%r9\n\t"
6428 "movq 0(%rsp),%xmm0\n\t"
6429 "movq 8(%rsp),%xmm1\n\t"
6430 "movq 16(%rsp),%xmm2\n\t"
6431 "movq 24(%rsp),%xmm3\n\t"
6432 "callq *%rax\n\t"
6433 "leaq -16(%rbp),%rsp\n\t"
6434 "popq %rdi\n\t"
6435 __ASM_CFI(".cfi_same_value %rdi\n\t")
6436 "popq %rsi\n\t"
6437 __ASM_CFI(".cfi_same_value %rsi\n\t")
6438 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6439 "popq %rbp\n\t"
6440 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6441 __ASM_CFI(".cfi_same_value %rbp\n\t")
6442 "ret")
6444 /* same function but returning floating point */
6445 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6447 #endif /* __x86_64__ */
6449 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6451 HRESULT hr = S_OK;
6452 ITypeInfo *tinfo2 = NULL;
6453 TYPEATTR *tattr = NULL;
6455 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6456 if (hr)
6458 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6459 "hr = 0x%08x\n",
6460 tdesc->u.hreftype, hr);
6461 return hr;
6463 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6464 if (hr)
6466 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6467 ITypeInfo_Release(tinfo2);
6468 return hr;
6471 switch (tattr->typekind)
6473 case TKIND_ENUM:
6474 *vt |= VT_I4;
6475 break;
6477 case TKIND_ALIAS:
6478 tdesc = &tattr->tdescAlias;
6479 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6480 break;
6482 case TKIND_INTERFACE:
6483 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6484 *vt |= VT_DISPATCH;
6485 else
6486 *vt |= VT_UNKNOWN;
6487 break;
6489 case TKIND_DISPATCH:
6490 *vt |= VT_DISPATCH;
6491 break;
6493 case TKIND_COCLASS:
6494 *vt |= VT_DISPATCH;
6495 break;
6497 case TKIND_RECORD:
6498 FIXME("TKIND_RECORD unhandled.\n");
6499 hr = E_NOTIMPL;
6500 break;
6502 case TKIND_UNION:
6503 FIXME("TKIND_UNION unhandled.\n");
6504 hr = E_NOTIMPL;
6505 break;
6507 default:
6508 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6509 hr = E_NOTIMPL;
6510 break;
6512 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6513 ITypeInfo_Release(tinfo2);
6514 return hr;
6517 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6519 HRESULT hr = S_OK;
6521 /* enforce only one level of pointer indirection */
6522 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6524 tdesc = tdesc->u.lptdesc;
6526 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6527 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6528 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6529 if ((tdesc->vt == VT_USERDEFINED) ||
6530 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6532 VARTYPE vt_userdefined = 0;
6533 const TYPEDESC *tdesc_userdefined = tdesc;
6534 if (tdesc->vt == VT_PTR)
6536 vt_userdefined = VT_BYREF;
6537 tdesc_userdefined = tdesc->u.lptdesc;
6539 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6540 if ((hr == S_OK) &&
6541 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6542 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6544 *vt |= vt_userdefined;
6545 return S_OK;
6548 *vt = VT_BYREF;
6551 switch (tdesc->vt)
6553 case VT_HRESULT:
6554 *vt |= VT_ERROR;
6555 break;
6556 case VT_USERDEFINED:
6557 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6558 break;
6559 case VT_VOID:
6560 case VT_CARRAY:
6561 case VT_PTR:
6562 case VT_LPSTR:
6563 case VT_LPWSTR:
6564 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6565 hr = DISP_E_BADVARTYPE;
6566 break;
6567 case VT_SAFEARRAY:
6568 *vt |= VT_ARRAY;
6569 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6570 break;
6571 case VT_INT:
6572 *vt |= VT_I4;
6573 break;
6574 case VT_UINT:
6575 *vt |= VT_UI4;
6576 break;
6577 default:
6578 *vt |= tdesc->vt;
6579 break;
6581 return hr;
6584 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6586 ITypeInfo *tinfo2;
6587 TYPEATTR *tattr;
6588 HRESULT hres;
6590 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6591 if(FAILED(hres))
6592 return hres;
6594 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6595 if(FAILED(hres)) {
6596 ITypeInfo_Release(tinfo2);
6597 return hres;
6600 switch(tattr->typekind) {
6601 case TKIND_ALIAS:
6602 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6603 break;
6605 case TKIND_INTERFACE:
6606 case TKIND_DISPATCH:
6607 *guid = tattr->guid;
6608 break;
6610 default:
6611 ERR("Unexpected typekind %d\n", tattr->typekind);
6612 hres = E_UNEXPECTED;
6615 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6616 ITypeInfo_Release(tinfo2);
6617 return hres;
6620 /***********************************************************************
6621 * DispCallFunc (OLEAUT32.@)
6623 * Invokes a function of the specified calling convention, passing the
6624 * specified arguments and returns the result.
6626 * PARAMS
6627 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6628 * oVft [I] The offset in the vtable. See notes.
6629 * cc [I] Calling convention of the function to call.
6630 * vtReturn [I] The return type of the function.
6631 * cActuals [I] Number of parameters.
6632 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6633 * prgpvarg [I] The arguments to pass.
6634 * pvargResult [O] The return value of the function. Can be NULL.
6636 * RETURNS
6637 * Success: S_OK.
6638 * Failure: HRESULT code.
6640 * NOTES
6641 * The HRESULT return value of this function is not affected by the return
6642 * value of the user supplied function, which is returned in pvargResult.
6644 * If pvInstance is NULL then a non-object function is to be called and oVft
6645 * is the address of the function to call.
6647 * The cc parameter can be one of the following values:
6648 *|CC_FASTCALL
6649 *|CC_CDECL
6650 *|CC_PASCAL
6651 *|CC_STDCALL
6652 *|CC_FPFASTCALL
6653 *|CC_SYSCALL
6654 *|CC_MPWCDECL
6655 *|CC_MPWPASCAL
6658 HRESULT WINAPI
6659 DispCallFunc(
6660 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6661 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6663 #ifdef __i386__
6664 int argspos, stack_offset;
6665 void *func;
6666 UINT i;
6667 DWORD *args;
6669 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6670 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6671 pvargResult, V_VT(pvargResult));
6673 if (cc != CC_STDCALL && cc != CC_CDECL)
6675 FIXME("unsupported calling convention %d\n",cc);
6676 return E_INVALIDARG;
6679 /* maximum size for an argument is sizeof(VARIANT) */
6680 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6682 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6683 argspos = 1;
6684 if (pvInstance)
6686 const FARPROC *vtable = *(FARPROC **)pvInstance;
6687 func = vtable[oVft/sizeof(void *)];
6688 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6690 else func = (void *)oVft;
6692 for (i = 0; i < cActuals; i++)
6694 VARIANT *arg = prgpvarg[i];
6696 switch (prgvt[i])
6698 case VT_EMPTY:
6699 break;
6700 case VT_I8:
6701 case VT_UI8:
6702 case VT_R8:
6703 case VT_DATE:
6704 case VT_CY:
6705 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6706 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6707 break;
6708 case VT_DECIMAL:
6709 case VT_VARIANT:
6710 memcpy( &args[argspos], arg, sizeof(*arg) );
6711 argspos += sizeof(*arg) / sizeof(DWORD);
6712 break;
6713 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6714 args[argspos++] = V_BOOL(arg);
6715 break;
6716 default:
6717 args[argspos++] = V_UI4(arg);
6718 break;
6720 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6723 switch (vtReturn)
6725 case VT_EMPTY:
6726 call_method( func, argspos - 1, args + 1, &stack_offset );
6727 break;
6728 case VT_R4:
6729 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6730 break;
6731 case VT_R8:
6732 case VT_DATE:
6733 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6734 break;
6735 case VT_DECIMAL:
6736 case VT_VARIANT:
6737 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6738 call_method( func, argspos, args, &stack_offset );
6739 break;
6740 case VT_I8:
6741 case VT_UI8:
6742 case VT_CY:
6743 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6744 break;
6745 case VT_HRESULT:
6746 WARN("invalid return type %u\n", vtReturn);
6747 heap_free( args );
6748 return E_INVALIDARG;
6749 default:
6750 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6751 break;
6753 heap_free( args );
6754 if (stack_offset && cc == CC_STDCALL)
6756 WARN( "stack pointer off by %d\n", stack_offset );
6757 return DISP_E_BADCALLEE;
6759 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6760 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6761 return S_OK;
6763 #elif defined(__x86_64__)
6764 int argspos;
6765 UINT i;
6766 DWORD_PTR *args;
6767 void *func;
6769 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6770 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6771 pvargResult, V_VT(pvargResult));
6773 if (cc != CC_STDCALL && cc != CC_CDECL)
6775 FIXME("unsupported calling convention %d\n",cc);
6776 return E_INVALIDARG;
6779 /* maximum size for an argument is sizeof(DWORD_PTR) */
6780 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6782 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6783 argspos = 1;
6784 if (pvInstance)
6786 const FARPROC *vtable = *(FARPROC **)pvInstance;
6787 func = vtable[oVft/sizeof(void *)];
6788 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6790 else func = (void *)oVft;
6792 for (i = 0; i < cActuals; i++)
6794 VARIANT *arg = prgpvarg[i];
6796 switch (prgvt[i])
6798 case VT_DECIMAL:
6799 case VT_VARIANT:
6800 args[argspos++] = (ULONG_PTR)arg;
6801 break;
6802 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6803 args[argspos++] = V_BOOL(arg);
6804 break;
6805 default:
6806 args[argspos++] = V_UI8(arg);
6807 break;
6809 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6812 switch (vtReturn)
6814 case VT_R4:
6815 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6816 break;
6817 case VT_R8:
6818 case VT_DATE:
6819 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6820 break;
6821 case VT_DECIMAL:
6822 case VT_VARIANT:
6823 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6824 call_method( func, argspos, args );
6825 break;
6826 case VT_HRESULT:
6827 WARN("invalid return type %u\n", vtReturn);
6828 heap_free( args );
6829 return E_INVALIDARG;
6830 default:
6831 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6832 break;
6834 heap_free( args );
6835 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6836 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6837 return S_OK;
6839 #else
6840 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6841 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6842 return E_NOTIMPL;
6843 #endif
6846 static inline BOOL func_restricted( const FUNCDESC *desc )
6848 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6851 #define INVBUF_ELEMENT_SIZE \
6852 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6853 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6854 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6855 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6856 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6857 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6858 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6859 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6861 static HRESULT WINAPI ITypeInfo_fnInvoke(
6862 ITypeInfo2 *iface,
6863 VOID *pIUnk,
6864 MEMBERID memid,
6865 UINT16 wFlags,
6866 DISPPARAMS *pDispParams,
6867 VARIANT *pVarResult,
6868 EXCEPINFO *pExcepInfo,
6869 UINT *pArgErr)
6871 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6872 int i;
6873 unsigned int var_index;
6874 TYPEKIND type_kind;
6875 HRESULT hres;
6876 const TLBFuncDesc *pFuncInfo;
6877 UINT fdc;
6879 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6880 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6883 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6884 return DISP_E_MEMBERNOTFOUND;
6886 if (!pDispParams)
6888 ERR("NULL pDispParams not allowed\n");
6889 return E_INVALIDARG;
6892 dump_DispParms(pDispParams);
6894 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6896 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6897 pDispParams->cNamedArgs, pDispParams->cArgs);
6898 return E_INVALIDARG;
6901 /* we do this instead of using GetFuncDesc since it will return a fake
6902 * FUNCDESC for dispinterfaces and we want the real function description */
6903 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
6904 pFuncInfo = &This->funcdescs[fdc];
6905 if ((memid == pFuncInfo->funcdesc.memid) &&
6906 (wFlags & pFuncInfo->funcdesc.invkind) &&
6907 !func_restricted( &pFuncInfo->funcdesc ))
6908 break;
6911 if (fdc < This->typeattr.cFuncs) {
6912 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6914 if (TRACE_ON(ole))
6916 TRACE("invoking:\n");
6917 dump_TLBFuncDescOne(pFuncInfo);
6920 switch (func_desc->funckind) {
6921 case FUNC_PUREVIRTUAL:
6922 case FUNC_VIRTUAL: {
6923 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6924 VARIANT varresult;
6925 VARIANT retval; /* pointer for storing byref retvals in */
6926 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6927 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6928 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6929 UINT cNamedArgs = pDispParams->cNamedArgs;
6930 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6931 UINT vargs_converted=0;
6933 hres = S_OK;
6935 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6937 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6939 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6940 hres = DISP_E_PARAMNOTFOUND;
6941 goto func_fail;
6945 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6947 ERR("functions with the vararg attribute do not support named arguments\n");
6948 hres = DISP_E_NONAMEDARGS;
6949 goto func_fail;
6952 for (i = 0; i < func_desc->cParams; i++)
6954 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6955 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6956 if (FAILED(hres))
6957 goto func_fail;
6960 TRACE("changing args\n");
6961 for (i = 0; i < func_desc->cParams; i++)
6963 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6964 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6965 VARIANTARG *src_arg;
6967 if (wParamFlags & PARAMFLAG_FLCID)
6969 VARIANTARG *arg;
6970 arg = prgpvarg[i] = &rgvarg[i];
6971 V_VT(arg) = VT_I4;
6972 V_I4(arg) = This->pTypeLib->lcid;
6973 continue;
6976 src_arg = NULL;
6978 if (cNamedArgs)
6980 USHORT j;
6981 for (j = 0; j < cNamedArgs; j++)
6982 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6984 src_arg = &pDispParams->rgvarg[j];
6985 break;
6989 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6991 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6992 vargs_converted++;
6995 if (wParamFlags & PARAMFLAG_FRETVAL)
6997 /* under most conditions the caller is not allowed to
6998 * pass in a dispparam arg in the index of what would be
6999 * the retval parameter. however, there is an exception
7000 * where the extra parameter is used in an extra
7001 * IDispatch::Invoke below */
7002 if ((i < pDispParams->cArgs) &&
7003 ((func_desc->cParams != 1) || !pVarResult ||
7004 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7006 hres = DISP_E_BADPARAMCOUNT;
7007 break;
7010 /* note: this check is placed so that if the caller passes
7011 * in a VARIANTARG for the retval we just ignore it, like
7012 * native does */
7013 if (i == func_desc->cParams - 1)
7015 VARIANTARG *arg;
7016 arg = prgpvarg[i] = &rgvarg[i];
7017 memset(arg, 0, sizeof(*arg));
7018 V_VT(arg) = rgvt[i];
7019 memset(&retval, 0, sizeof(retval));
7020 V_BYREF(arg) = &retval;
7022 else
7024 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7025 hres = E_UNEXPECTED;
7026 break;
7029 else if (src_arg)
7031 TRACE("%s\n", debugstr_variant(src_arg));
7033 if(rgvt[i]!=V_VT(src_arg))
7035 if (rgvt[i] == VT_VARIANT)
7036 hres = VariantCopy(&rgvarg[i], src_arg);
7037 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7039 if (rgvt[i] == V_VT(src_arg))
7040 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7041 else
7043 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7044 if (wParamFlags & PARAMFLAG_FIN)
7045 hres = VariantCopy(&missing_arg[i], src_arg);
7046 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7048 V_VT(&rgvarg[i]) = rgvt[i];
7050 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7052 SAFEARRAY *a;
7053 SAFEARRAYBOUND bound;
7054 VARIANT *v;
7055 LONG j;
7056 bound.lLbound = 0;
7057 bound.cElements = pDispParams->cArgs-i;
7058 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7060 ERR("SafeArrayCreate failed\n");
7061 break;
7063 hres = SafeArrayAccessData(a, (LPVOID)&v);
7064 if (hres != S_OK)
7066 ERR("SafeArrayAccessData failed with %x\n", hres);
7067 SafeArrayDestroy(a);
7068 break;
7070 for (j = 0; j < bound.cElements; j++)
7071 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7072 hres = SafeArrayUnaccessData(a);
7073 if (hres != S_OK)
7075 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7076 SafeArrayDestroy(a);
7077 break;
7079 if (rgvt[i] & VT_BYREF)
7080 V_BYREF(&rgvarg[i]) = &a;
7081 else
7082 V_ARRAY(&rgvarg[i]) = a;
7083 V_VT(&rgvarg[i]) = rgvt[i];
7085 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7087 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7088 if (wParamFlags & PARAMFLAG_FIN)
7089 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7090 else
7091 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7092 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7093 V_VT(&rgvarg[i]) = rgvt[i];
7095 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7097 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7098 V_VT(&rgvarg[i]) = rgvt[i];
7100 else
7102 /* FIXME: this doesn't work for VT_BYREF arguments if
7103 * they are not the same type as in the paramdesc */
7104 V_VT(&rgvarg[i]) = V_VT(src_arg);
7105 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7106 V_VT(&rgvarg[i]) = rgvt[i];
7109 if (FAILED(hres))
7111 ERR("failed to convert param %d to %s from %s\n", i,
7112 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7113 break;
7115 prgpvarg[i] = &rgvarg[i];
7117 else
7119 prgpvarg[i] = src_arg;
7122 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7123 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7124 && V_UNKNOWN(prgpvarg[i])) {
7125 IUnknown *userdefined_iface;
7126 GUID guid;
7128 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7129 if(FAILED(hres))
7130 break;
7132 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7133 if(FAILED(hres)) {
7134 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7135 break;
7138 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7139 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7142 else if (wParamFlags & PARAMFLAG_FOPT)
7144 VARIANTARG *arg;
7145 arg = prgpvarg[i] = &rgvarg[i];
7146 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7148 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7149 if (FAILED(hres))
7150 break;
7152 else
7154 VARIANTARG *missing_arg;
7155 /* if the function wants a pointer to a variant then
7156 * set that up, otherwise just pass the VT_ERROR in
7157 * the argument by value */
7158 if (rgvt[i] & VT_BYREF)
7160 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7161 V_VT(arg) = VT_VARIANT | VT_BYREF;
7162 V_VARIANTREF(arg) = missing_arg;
7164 else
7165 missing_arg = arg;
7166 V_VT(missing_arg) = VT_ERROR;
7167 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7170 else
7172 hres = DISP_E_BADPARAMCOUNT;
7173 break;
7176 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7178 /* VT_VOID is a special case for return types, so it is not
7179 * handled in the general function */
7180 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7181 V_VT(&varresult) = VT_EMPTY;
7182 else
7184 V_VT(&varresult) = 0;
7185 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7186 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7189 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7190 V_VT(&varresult), func_desc->cParams, rgvt,
7191 prgpvarg, &varresult);
7193 vargs_converted = 0;
7195 for (i = 0; i < func_desc->cParams; i++)
7197 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7198 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7200 if (wParamFlags & PARAMFLAG_FLCID)
7201 continue;
7202 else if (wParamFlags & PARAMFLAG_FRETVAL)
7204 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7206 if (pVarResult)
7208 VariantInit(pVarResult);
7209 /* deref return value */
7210 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7213 VARIANT_ClearInd(prgpvarg[i]);
7215 else if (vargs_converted < pDispParams->cArgs)
7217 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7218 if (wParamFlags & PARAMFLAG_FOUT)
7220 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7222 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7224 if (FAILED(hres))
7226 ERR("failed to convert param %d to vt %d\n", i,
7227 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7228 break;
7232 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7233 func_desc->cParamsOpt < 0 &&
7234 i == func_desc->cParams-1)
7236 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7237 LONG j, ubound;
7238 VARIANT *v;
7239 hres = SafeArrayGetUBound(a, 1, &ubound);
7240 if (hres != S_OK)
7242 ERR("SafeArrayGetUBound failed with %x\n", hres);
7243 break;
7245 hres = SafeArrayAccessData(a, (LPVOID)&v);
7246 if (hres != S_OK)
7248 ERR("SafeArrayAccessData failed with %x\n", hres);
7249 break;
7251 for (j = 0; j <= ubound; j++)
7252 VariantClear(&v[j]);
7253 hres = SafeArrayUnaccessData(a);
7254 if (hres != S_OK)
7256 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7257 break;
7260 VariantClear(&rgvarg[i]);
7261 vargs_converted++;
7263 else if (wParamFlags & PARAMFLAG_FOPT)
7265 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7266 VariantClear(&rgvarg[i]);
7269 VariantClear(&missing_arg[i]);
7272 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7274 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7275 hres = DISP_E_EXCEPTION;
7276 if (pExcepInfo)
7278 IErrorInfo *pErrorInfo;
7279 pExcepInfo->scode = V_ERROR(&varresult);
7280 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7282 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7283 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7284 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7285 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7287 IErrorInfo_Release(pErrorInfo);
7291 if (V_VT(&varresult) != VT_ERROR)
7293 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7295 if (pVarResult)
7297 VariantClear(pVarResult);
7298 *pVarResult = varresult;
7300 else
7301 VariantClear(&varresult);
7304 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7305 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7306 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7307 (pDispParams->cArgs != 0))
7309 if (V_VT(pVarResult) == VT_DISPATCH)
7311 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7312 /* Note: not VariantClear; we still need the dispatch
7313 * pointer to be valid */
7314 VariantInit(pVarResult);
7315 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7316 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7317 pDispParams, pVarResult, pExcepInfo, pArgErr);
7318 IDispatch_Release(pDispatch);
7320 else
7322 VariantClear(pVarResult);
7323 hres = DISP_E_NOTACOLLECTION;
7327 func_fail:
7328 heap_free(buffer);
7329 break;
7331 case FUNC_DISPATCH: {
7332 IDispatch *disp;
7334 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7335 if (SUCCEEDED(hres)) {
7336 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7337 hres = IDispatch_Invoke(
7338 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7339 pVarResult,pExcepInfo,pArgErr
7341 if (FAILED(hres))
7342 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7343 IDispatch_Release(disp);
7344 } else
7345 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7346 break;
7348 default:
7349 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7350 hres = E_FAIL;
7351 break;
7354 TRACE("-- 0x%08x\n", hres);
7355 return hres;
7357 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7358 VARDESC *var_desc;
7360 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7361 if(FAILED(hres)) return hres;
7363 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7364 dump_VARDESC(var_desc);
7365 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7366 return E_NOTIMPL;
7369 /* not found, look for it in inherited interfaces */
7370 ITypeInfo2_GetTypeKind(iface, &type_kind);
7371 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7372 if(This->impltypes) {
7373 /* recursive search */
7374 ITypeInfo *pTInfo;
7375 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7376 if(SUCCEEDED(hres)){
7377 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7378 ITypeInfo_Release(pTInfo);
7379 return hres;
7381 WARN("Could not search inherited interface!\n");
7384 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7385 return DISP_E_MEMBERNOTFOUND;
7388 /* ITypeInfo::GetDocumentation
7390 * Retrieves the documentation string, the complete Help file name and path,
7391 * and the context ID for the Help topic for a specified type description.
7393 * (Can be tested by the Visual Basic Editor in Word for instance.)
7395 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7396 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7397 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7399 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7400 const TLBFuncDesc *pFDesc;
7401 const TLBVarDesc *pVDesc;
7402 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7403 " HelpContext(%p) HelpFile(%p)\n",
7404 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7405 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7406 if(pBstrName)
7407 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7408 if(pBstrDocString)
7409 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7410 if(pdwHelpContext)
7411 *pdwHelpContext=This->dwHelpContext;
7412 if(pBstrHelpFile)
7413 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7414 return S_OK;
7415 }else {/* for a member */
7416 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7417 if(pFDesc){
7418 if(pBstrName)
7419 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7420 if(pBstrDocString)
7421 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7422 if(pdwHelpContext)
7423 *pdwHelpContext=pFDesc->helpcontext;
7424 if(pBstrHelpFile)
7425 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7426 return S_OK;
7428 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
7429 if(pVDesc){
7430 if(pBstrName)
7431 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7432 if(pBstrDocString)
7433 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7434 if(pdwHelpContext)
7435 *pdwHelpContext=pVDesc->HelpContext;
7436 if(pBstrHelpFile)
7437 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7438 return S_OK;
7442 if(This->impltypes &&
7443 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7444 /* recursive search */
7445 ITypeInfo *pTInfo;
7446 HRESULT result;
7447 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7448 if(SUCCEEDED(result)) {
7449 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7450 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7451 ITypeInfo_Release(pTInfo);
7452 return result;
7454 WARN("Could not search inherited interface!\n");
7457 WARN("member %d not found\n", memid);
7458 return TYPE_E_ELEMENTNOTFOUND;
7461 /* ITypeInfo::GetDllEntry
7463 * Retrieves a description or specification of an entry point for a function
7464 * in a DLL.
7466 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7467 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7468 WORD *pwOrdinal)
7470 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7471 const TLBFuncDesc *pFDesc;
7473 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7475 if (pBstrDllName) *pBstrDllName = NULL;
7476 if (pBstrName) *pBstrName = NULL;
7477 if (pwOrdinal) *pwOrdinal = 0;
7479 if (This->typeattr.typekind != TKIND_MODULE)
7480 return TYPE_E_BADMODULEKIND;
7482 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7483 if(pFDesc){
7484 dump_TypeInfo(This);
7485 if (TRACE_ON(ole))
7486 dump_TLBFuncDescOne(pFDesc);
7488 if (pBstrDllName)
7489 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7491 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7492 if (pBstrName)
7493 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7494 if (pwOrdinal)
7495 *pwOrdinal = -1;
7496 return S_OK;
7498 if (pBstrName)
7499 *pBstrName = NULL;
7500 if (pwOrdinal)
7501 *pwOrdinal = LOWORD(pFDesc->Entry);
7502 return S_OK;
7504 return TYPE_E_ELEMENTNOTFOUND;
7507 /* internal function to make the inherited interfaces' methods appear
7508 * part of the interface */
7509 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7510 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7512 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7513 HRESULT hr;
7515 TRACE("%p, 0x%x\n", iface, *hRefType);
7517 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7519 ITypeInfo *pSubTypeInfo;
7521 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7522 if (FAILED(hr))
7523 return hr;
7525 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7526 hRefType, ppTInfo);
7527 ITypeInfo_Release(pSubTypeInfo);
7528 if (SUCCEEDED(hr))
7529 return hr;
7531 *hRefType -= DISPATCH_HREF_OFFSET;
7533 if (!(*hRefType & DISPATCH_HREF_MASK))
7534 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7535 else
7536 return E_FAIL;
7539 struct search_res_tlb_params
7541 const GUID *guid;
7542 ITypeLib *pTLib;
7545 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7547 struct search_res_tlb_params *params = (LPVOID)lParam;
7548 static const WCHAR formatW[] = {'\\','%','d',0};
7549 WCHAR szPath[MAX_PATH+1];
7550 ITypeLib *pTLib = NULL;
7551 HRESULT ret;
7552 DWORD len;
7554 if (IS_INTRESOURCE(lpszName) == FALSE)
7555 return TRUE;
7557 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7558 return TRUE;
7560 if (snprintfW(szPath + len, sizeof(szPath)/sizeof(WCHAR) - len, formatW, LOWORD(lpszName)) < 0)
7561 return TRUE;
7563 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7564 if (SUCCEEDED(ret))
7566 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7567 if (IsEqualGUID(params->guid, impl->guid))
7569 params->pTLib = pTLib;
7570 return FALSE; /* stop enumeration */
7572 ITypeLib_Release(pTLib);
7575 return TRUE;
7578 /* ITypeInfo::GetRefTypeInfo
7580 * If a type description references other type descriptions, it retrieves
7581 * the referenced type descriptions.
7583 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7584 ITypeInfo2 *iface,
7585 HREFTYPE hRefType,
7586 ITypeInfo **ppTInfo)
7588 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7589 HRESULT result = E_FAIL;
7591 if(!ppTInfo)
7592 return E_INVALIDARG;
7594 if ((INT)hRefType < 0) {
7595 ITypeInfoImpl *pTypeInfoImpl;
7597 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7598 !(This->typeattr.typekind == TKIND_INTERFACE ||
7599 This->typeattr.typekind == TKIND_DISPATCH))
7600 return TYPE_E_ELEMENTNOTFOUND;
7602 /* when we meet a DUAL typeinfo, we must create the alternate
7603 * version of it.
7605 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7607 *pTypeInfoImpl = *This;
7608 pTypeInfoImpl->ref = 0;
7609 list_init(&pTypeInfoImpl->custdata_list);
7611 if (This->typeattr.typekind == TKIND_INTERFACE)
7612 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7613 else
7614 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7616 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7617 /* the AddRef implicitly adds a reference to the parent typelib, which
7618 * stops the copied data from being destroyed until the new typeinfo's
7619 * refcount goes to zero, but we need to signal to the new instance to
7620 * not free its data structures when it is destroyed */
7621 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7623 ITypeInfo_AddRef(*ppTInfo);
7625 result = S_OK;
7626 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7627 (This->typeattr.typekind == TKIND_DISPATCH))
7629 HREFTYPE href_dispatch = hRefType;
7630 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7631 } else {
7632 TLBRefType *ref_type;
7633 ITypeLib *pTLib = NULL;
7634 UINT i;
7636 if(!(hRefType & 0x1)){
7637 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7639 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7641 result = S_OK;
7642 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7643 ITypeInfo_AddRef(*ppTInfo);
7644 goto end;
7649 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7651 if(ref_type->reference == (hRefType & (~0x3)))
7652 break;
7654 if(&ref_type->entry == &This->pTypeLib->ref_list)
7656 FIXME("Can't find pRefType for ref %x\n", hRefType);
7657 goto end;
7660 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7661 UINT Index;
7662 TRACE("internal reference\n");
7663 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7664 } else {
7665 if(ref_type->pImpTLInfo->pImpTypeLib) {
7666 TRACE("typeinfo in imported typelib that is already loaded\n");
7667 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7668 ITypeLib_AddRef(pTLib);
7669 result = S_OK;
7670 } else {
7671 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
7672 struct search_res_tlb_params params;
7673 BSTR libnam;
7675 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7677 /* Search in resource table */
7678 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
7679 params.pTLib = NULL;
7680 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
7681 pTLib = params.pTLib;
7682 result = S_OK;
7684 if (!pTLib)
7686 /* Search on disk */
7687 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7688 ref_type->pImpTLInfo->wVersionMajor,
7689 ref_type->pImpTLInfo->wVersionMinor,
7690 This->pTypeLib->syskind,
7691 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7692 if (FAILED(result))
7693 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7695 result = LoadTypeLib(libnam, &pTLib);
7696 SysFreeString(libnam);
7699 if(SUCCEEDED(result)) {
7700 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7701 ITypeLib_AddRef(pTLib);
7705 if(SUCCEEDED(result)) {
7706 if(ref_type->index == TLB_REF_USE_GUID)
7707 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7708 else
7709 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7711 if (pTLib != NULL)
7712 ITypeLib_Release(pTLib);
7715 end:
7716 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7717 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7718 return result;
7721 /* ITypeInfo::AddressOfMember
7723 * Retrieves the addresses of static functions or variables, such as those
7724 * defined in a DLL.
7726 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7727 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7729 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7730 HRESULT hr;
7731 BSTR dll, entry;
7732 WORD ordinal;
7733 HMODULE module;
7735 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7737 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7738 if (FAILED(hr))
7739 return hr;
7741 module = LoadLibraryW(dll);
7742 if (!module)
7744 ERR("couldn't load %s\n", debugstr_w(dll));
7745 SysFreeString(dll);
7746 SysFreeString(entry);
7747 return STG_E_FILENOTFOUND;
7749 /* FIXME: store library somewhere where we can free it */
7751 if (entry)
7753 LPSTR entryA;
7754 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7755 entryA = heap_alloc(len);
7756 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7758 *ppv = GetProcAddress(module, entryA);
7759 if (!*ppv)
7760 ERR("function not found %s\n", debugstr_a(entryA));
7762 heap_free(entryA);
7764 else
7766 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7767 if (!*ppv)
7768 ERR("function not found %d\n", ordinal);
7771 SysFreeString(dll);
7772 SysFreeString(entry);
7774 if (!*ppv)
7775 return TYPE_E_DLLFUNCTIONNOTFOUND;
7777 return S_OK;
7780 /* ITypeInfo::CreateInstance
7782 * Creates a new instance of a type that describes a component object class
7783 * (coclass).
7785 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7786 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7788 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7789 HRESULT hr;
7790 TYPEATTR *pTA;
7792 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7794 *ppvObj = NULL;
7796 if(pOuterUnk)
7798 WARN("Not able to aggregate\n");
7799 return CLASS_E_NOAGGREGATION;
7802 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7803 if(FAILED(hr)) return hr;
7805 if(pTA->typekind != TKIND_COCLASS)
7807 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7808 hr = E_INVALIDARG;
7809 goto end;
7812 hr = S_FALSE;
7813 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7815 IUnknown *pUnk;
7816 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7817 TRACE("GetActiveObject rets %08x\n", hr);
7818 if(hr == S_OK)
7820 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7821 IUnknown_Release(pUnk);
7825 if(hr != S_OK)
7826 hr = CoCreateInstance(&pTA->guid, NULL,
7827 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7828 riid, ppvObj);
7830 end:
7831 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7832 return hr;
7835 /* ITypeInfo::GetMops
7837 * Retrieves marshalling information.
7839 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7840 BSTR *pBstrMops)
7842 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7843 FIXME("(%p %d) stub!\n", This, memid);
7844 *pBstrMops = NULL;
7845 return S_OK;
7848 /* ITypeInfo::GetContainingTypeLib
7850 * Retrieves the containing type library and the index of the type description
7851 * within that type library.
7853 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7854 ITypeLib * *ppTLib, UINT *pIndex)
7856 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7858 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7859 if (pIndex) {
7860 *pIndex=This->index;
7861 TRACE("returning pIndex=%d\n", *pIndex);
7864 if (ppTLib) {
7865 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
7866 ITypeLib_AddRef(*ppTLib);
7867 TRACE("returning ppTLib=%p\n", *ppTLib);
7870 return S_OK;
7873 /* ITypeInfo::ReleaseTypeAttr
7875 * Releases a TYPEATTR previously returned by Get
7878 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7879 TYPEATTR* pTypeAttr)
7881 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7882 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7883 heap_free(pTypeAttr);
7886 /* ITypeInfo::ReleaseFuncDesc
7888 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7890 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7891 ITypeInfo2 *iface,
7892 FUNCDESC *pFuncDesc)
7894 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7895 SHORT i;
7897 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7899 for (i = 0; i < pFuncDesc->cParams; i++)
7900 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7901 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7903 SysFreeString((BSTR)pFuncDesc);
7906 /* ITypeInfo::ReleaseVarDesc
7908 * Releases a VARDESC previously returned by GetVarDesc.
7910 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7911 VARDESC *pVarDesc)
7913 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7914 TRACE("(%p)->(%p)\n", This, pVarDesc);
7916 TLB_FreeVarDesc(pVarDesc);
7919 /* ITypeInfo2::GetTypeKind
7921 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7924 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7925 TYPEKIND *pTypeKind)
7927 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7928 *pTypeKind = This->typeattr.typekind;
7929 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7930 return S_OK;
7933 /* ITypeInfo2::GetTypeFlags
7935 * Returns the type flags without any allocations. This returns a DWORD type
7936 * flag, which expands the type flags without growing the TYPEATTR (type
7937 * attribute).
7940 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7942 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7943 *pTypeFlags=This->typeattr.wTypeFlags;
7944 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7945 return S_OK;
7948 /* ITypeInfo2::GetFuncIndexOfMemId
7949 * Binds to a specific member based on a known DISPID, where the member name
7950 * is not known (for example, when binding to a default member).
7953 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7954 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7956 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7957 UINT fdc;
7958 HRESULT result;
7960 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7961 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7962 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7963 break;
7965 if(fdc < This->typeattr.cFuncs) {
7966 *pFuncIndex = fdc;
7967 result = S_OK;
7968 } else
7969 result = TYPE_E_ELEMENTNOTFOUND;
7971 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7972 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7973 return result;
7976 /* TypeInfo2::GetVarIndexOfMemId
7978 * Binds to a specific member based on a known DISPID, where the member name
7979 * is not known (for example, when binding to a default member).
7982 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7983 MEMBERID memid, UINT *pVarIndex)
7985 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7986 TLBVarDesc *pVarInfo;
7988 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7990 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
7991 if(!pVarInfo)
7992 return TYPE_E_ELEMENTNOTFOUND;
7994 *pVarIndex = (pVarInfo - This->vardescs);
7996 return S_OK;
7999 /* ITypeInfo2::GetCustData
8001 * Gets the custom data
8003 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8004 ITypeInfo2 * iface,
8005 REFGUID guid,
8006 VARIANT *pVarVal)
8008 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8009 TLBCustData *pCData;
8011 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8013 if(!guid || !pVarVal)
8014 return E_INVALIDARG;
8016 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8018 VariantInit( pVarVal);
8019 if (pCData)
8020 VariantCopy( pVarVal, &pCData->data);
8021 else
8022 VariantClear( pVarVal );
8023 return S_OK;
8026 /* ITypeInfo2::GetFuncCustData
8028 * Gets the custom data
8030 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8031 ITypeInfo2 * iface,
8032 UINT index,
8033 REFGUID guid,
8034 VARIANT *pVarVal)
8036 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8037 TLBCustData *pCData;
8038 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8040 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8042 if(index >= This->typeattr.cFuncs)
8043 return TYPE_E_ELEMENTNOTFOUND;
8045 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8046 if(!pCData)
8047 return TYPE_E_ELEMENTNOTFOUND;
8049 VariantInit(pVarVal);
8050 VariantCopy(pVarVal, &pCData->data);
8052 return S_OK;
8055 /* ITypeInfo2::GetParamCustData
8057 * Gets the custom data
8059 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8060 ITypeInfo2 * iface,
8061 UINT indexFunc,
8062 UINT indexParam,
8063 REFGUID guid,
8064 VARIANT *pVarVal)
8066 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8067 TLBCustData *pCData;
8068 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8070 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8071 debugstr_guid(guid), pVarVal);
8073 if(indexFunc >= This->typeattr.cFuncs)
8074 return TYPE_E_ELEMENTNOTFOUND;
8076 if(indexParam >= pFDesc->funcdesc.cParams)
8077 return TYPE_E_ELEMENTNOTFOUND;
8079 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8080 if(!pCData)
8081 return TYPE_E_ELEMENTNOTFOUND;
8083 VariantInit(pVarVal);
8084 VariantCopy(pVarVal, &pCData->data);
8086 return S_OK;
8089 /* ITypeInfo2::GetVarCustData
8091 * Gets the custom data
8093 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8094 ITypeInfo2 * iface,
8095 UINT index,
8096 REFGUID guid,
8097 VARIANT *pVarVal)
8099 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8100 TLBCustData *pCData;
8101 TLBVarDesc *pVDesc = &This->vardescs[index];
8103 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8105 if(index >= This->typeattr.cVars)
8106 return TYPE_E_ELEMENTNOTFOUND;
8108 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8109 if(!pCData)
8110 return TYPE_E_ELEMENTNOTFOUND;
8112 VariantInit(pVarVal);
8113 VariantCopy(pVarVal, &pCData->data);
8115 return S_OK;
8118 /* ITypeInfo2::GetImplCustData
8120 * Gets the custom data
8122 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8123 ITypeInfo2 * iface,
8124 UINT index,
8125 REFGUID guid,
8126 VARIANT *pVarVal)
8128 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8129 TLBCustData *pCData;
8130 TLBImplType *pRDesc = &This->impltypes[index];
8132 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8134 if(index >= This->typeattr.cImplTypes)
8135 return TYPE_E_ELEMENTNOTFOUND;
8137 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8138 if(!pCData)
8139 return TYPE_E_ELEMENTNOTFOUND;
8141 VariantInit(pVarVal);
8142 VariantCopy(pVarVal, &pCData->data);
8144 return S_OK;
8147 /* ITypeInfo2::GetDocumentation2
8149 * Retrieves the documentation string, the complete Help file name and path,
8150 * the localization context to use, and the context ID for the library Help
8151 * topic in the Help file.
8154 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8155 ITypeInfo2 * iface,
8156 MEMBERID memid,
8157 LCID lcid,
8158 BSTR *pbstrHelpString,
8159 DWORD *pdwHelpStringContext,
8160 BSTR *pbstrHelpStringDll)
8162 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8163 const TLBFuncDesc *pFDesc;
8164 const TLBVarDesc *pVDesc;
8165 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8166 "HelpStringContext(%p) HelpStringDll(%p)\n",
8167 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8168 pbstrHelpStringDll );
8169 /* the help string should be obtained from the helpstringdll,
8170 * using the _DLLGetDocumentation function, based on the supplied
8171 * lcid. Nice to do sometime...
8173 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8174 if(pbstrHelpString)
8175 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8176 if(pdwHelpStringContext)
8177 *pdwHelpStringContext=This->dwHelpStringContext;
8178 if(pbstrHelpStringDll)
8179 *pbstrHelpStringDll=
8180 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8181 return S_OK;
8182 }else {/* for a member */
8183 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
8184 if(pFDesc){
8185 if(pbstrHelpString)
8186 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8187 if(pdwHelpStringContext)
8188 *pdwHelpStringContext=pFDesc->HelpStringContext;
8189 if(pbstrHelpStringDll)
8190 *pbstrHelpStringDll=
8191 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8192 return S_OK;
8194 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8195 if(pVDesc){
8196 if(pbstrHelpString)
8197 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8198 if(pdwHelpStringContext)
8199 *pdwHelpStringContext=pVDesc->HelpStringContext;
8200 if(pbstrHelpStringDll)
8201 *pbstrHelpStringDll=
8202 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8203 return S_OK;
8206 return TYPE_E_ELEMENTNOTFOUND;
8209 /* ITypeInfo2::GetAllCustData
8211 * Gets all custom data items for the Type info.
8214 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8215 ITypeInfo2 * iface,
8216 CUSTDATA *pCustData)
8218 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8220 TRACE("%p %p\n", This, pCustData);
8222 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8225 /* ITypeInfo2::GetAllFuncCustData
8227 * Gets all custom data items for the specified Function
8230 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8231 ITypeInfo2 * iface,
8232 UINT index,
8233 CUSTDATA *pCustData)
8235 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8236 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8238 TRACE("%p %u %p\n", This, index, pCustData);
8240 if(index >= This->typeattr.cFuncs)
8241 return TYPE_E_ELEMENTNOTFOUND;
8243 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8246 /* ITypeInfo2::GetAllParamCustData
8248 * Gets all custom data items for the Functions
8251 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8252 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8254 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8255 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8257 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8259 if(indexFunc >= This->typeattr.cFuncs)
8260 return TYPE_E_ELEMENTNOTFOUND;
8262 if(indexParam >= pFDesc->funcdesc.cParams)
8263 return TYPE_E_ELEMENTNOTFOUND;
8265 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8268 /* ITypeInfo2::GetAllVarCustData
8270 * Gets all custom data items for the specified Variable
8273 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8274 UINT index, CUSTDATA *pCustData)
8276 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8277 TLBVarDesc * pVDesc = &This->vardescs[index];
8279 TRACE("%p %u %p\n", This, index, pCustData);
8281 if(index >= This->typeattr.cVars)
8282 return TYPE_E_ELEMENTNOTFOUND;
8284 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8287 /* ITypeInfo2::GetAllImplCustData
8289 * Gets all custom data items for the specified implementation type
8292 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8293 ITypeInfo2 * iface,
8294 UINT index,
8295 CUSTDATA *pCustData)
8297 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8298 TLBImplType *pRDesc = &This->impltypes[index];
8300 TRACE("%p %u %p\n", This, index, pCustData);
8302 if(index >= This->typeattr.cImplTypes)
8303 return TYPE_E_ELEMENTNOTFOUND;
8305 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8308 static const ITypeInfo2Vtbl tinfvt =
8311 ITypeInfo_fnQueryInterface,
8312 ITypeInfo_fnAddRef,
8313 ITypeInfo_fnRelease,
8315 ITypeInfo_fnGetTypeAttr,
8316 ITypeInfo_fnGetTypeComp,
8317 ITypeInfo_fnGetFuncDesc,
8318 ITypeInfo_fnGetVarDesc,
8319 ITypeInfo_fnGetNames,
8320 ITypeInfo_fnGetRefTypeOfImplType,
8321 ITypeInfo_fnGetImplTypeFlags,
8322 ITypeInfo_fnGetIDsOfNames,
8323 ITypeInfo_fnInvoke,
8324 ITypeInfo_fnGetDocumentation,
8325 ITypeInfo_fnGetDllEntry,
8326 ITypeInfo_fnGetRefTypeInfo,
8327 ITypeInfo_fnAddressOfMember,
8328 ITypeInfo_fnCreateInstance,
8329 ITypeInfo_fnGetMops,
8330 ITypeInfo_fnGetContainingTypeLib,
8331 ITypeInfo_fnReleaseTypeAttr,
8332 ITypeInfo_fnReleaseFuncDesc,
8333 ITypeInfo_fnReleaseVarDesc,
8335 ITypeInfo2_fnGetTypeKind,
8336 ITypeInfo2_fnGetTypeFlags,
8337 ITypeInfo2_fnGetFuncIndexOfMemId,
8338 ITypeInfo2_fnGetVarIndexOfMemId,
8339 ITypeInfo2_fnGetCustData,
8340 ITypeInfo2_fnGetFuncCustData,
8341 ITypeInfo2_fnGetParamCustData,
8342 ITypeInfo2_fnGetVarCustData,
8343 ITypeInfo2_fnGetImplTypeCustData,
8344 ITypeInfo2_fnGetDocumentation2,
8345 ITypeInfo2_fnGetAllCustData,
8346 ITypeInfo2_fnGetAllFuncCustData,
8347 ITypeInfo2_fnGetAllParamCustData,
8348 ITypeInfo2_fnGetAllVarCustData,
8349 ITypeInfo2_fnGetAllImplTypeCustData,
8352 /******************************************************************************
8353 * CreateDispTypeInfo [OLEAUT32.31]
8355 * Build type information for an object so it can be called through an
8356 * IDispatch interface.
8358 * RETURNS
8359 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8360 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8362 * NOTES
8363 * This call allows an objects methods to be accessed through IDispatch, by
8364 * building an ITypeInfo object that IDispatch can use to call through.
8366 HRESULT WINAPI CreateDispTypeInfo(
8367 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8368 LCID lcid, /* [I] Locale Id */
8369 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8371 ITypeInfoImpl *pTIClass, *pTIIface;
8372 ITypeLibImpl *pTypeLibImpl;
8373 unsigned int param, func;
8374 TLBFuncDesc *pFuncDesc;
8375 TLBRefType *ref;
8377 TRACE("\n");
8378 pTypeLibImpl = TypeLibImpl_Constructor();
8379 if (!pTypeLibImpl) return E_FAIL;
8381 pTypeLibImpl->TypeInfoCount = 2;
8382 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8384 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8385 pTIIface->pTypeLib = pTypeLibImpl;
8386 pTIIface->index = 0;
8387 pTIIface->Name = NULL;
8388 pTIIface->dwHelpContext = -1;
8389 pTIIface->guid = NULL;
8390 pTIIface->typeattr.lcid = lcid;
8391 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8392 pTIIface->typeattr.wMajorVerNum = 0;
8393 pTIIface->typeattr.wMinorVerNum = 0;
8394 pTIIface->typeattr.cbAlignment = 2;
8395 pTIIface->typeattr.cbSizeInstance = -1;
8396 pTIIface->typeattr.cbSizeVft = -1;
8397 pTIIface->typeattr.cFuncs = 0;
8398 pTIIface->typeattr.cImplTypes = 0;
8399 pTIIface->typeattr.cVars = 0;
8400 pTIIface->typeattr.wTypeFlags = 0;
8401 pTIIface->hreftype = 0;
8403 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8404 pFuncDesc = pTIIface->funcdescs;
8405 for(func = 0; func < pidata->cMembers; func++) {
8406 METHODDATA *md = pidata->pmethdata + func;
8407 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8408 pFuncDesc->funcdesc.memid = md->dispid;
8409 pFuncDesc->funcdesc.lprgscode = NULL;
8410 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8411 pFuncDesc->funcdesc.invkind = md->wFlags;
8412 pFuncDesc->funcdesc.callconv = md->cc;
8413 pFuncDesc->funcdesc.cParams = md->cArgs;
8414 pFuncDesc->funcdesc.cParamsOpt = 0;
8415 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8416 pFuncDesc->funcdesc.cScodes = 0;
8417 pFuncDesc->funcdesc.wFuncFlags = 0;
8418 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8419 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8420 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8421 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8422 md->cArgs * sizeof(ELEMDESC));
8423 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8424 for(param = 0; param < md->cArgs; param++) {
8425 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8426 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8428 pFuncDesc->helpcontext = 0;
8429 pFuncDesc->HelpStringContext = 0;
8430 pFuncDesc->HelpString = NULL;
8431 pFuncDesc->Entry = NULL;
8432 list_init(&pFuncDesc->custdata_list);
8433 pTIIface->typeattr.cFuncs++;
8434 ++pFuncDesc;
8437 dump_TypeInfo(pTIIface);
8439 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8440 pTIClass->pTypeLib = pTypeLibImpl;
8441 pTIClass->index = 1;
8442 pTIClass->Name = NULL;
8443 pTIClass->dwHelpContext = -1;
8444 pTIClass->guid = NULL;
8445 pTIClass->typeattr.lcid = lcid;
8446 pTIClass->typeattr.typekind = TKIND_COCLASS;
8447 pTIClass->typeattr.wMajorVerNum = 0;
8448 pTIClass->typeattr.wMinorVerNum = 0;
8449 pTIClass->typeattr.cbAlignment = 2;
8450 pTIClass->typeattr.cbSizeInstance = -1;
8451 pTIClass->typeattr.cbSizeVft = -1;
8452 pTIClass->typeattr.cFuncs = 0;
8453 pTIClass->typeattr.cImplTypes = 1;
8454 pTIClass->typeattr.cVars = 0;
8455 pTIClass->typeattr.wTypeFlags = 0;
8456 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8458 pTIClass->impltypes = TLBImplType_Alloc(1);
8460 ref = heap_alloc_zero(sizeof(*ref));
8461 ref->pImpTLInfo = TLB_REF_INTERNAL;
8462 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8464 dump_TypeInfo(pTIClass);
8466 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8468 ITypeInfo_AddRef(*pptinfo);
8469 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8471 return S_OK;
8475 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8477 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8479 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8482 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8484 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8486 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8489 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8491 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8493 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8496 static HRESULT WINAPI ITypeComp_fnBind(
8497 ITypeComp * iface,
8498 OLECHAR * szName,
8499 ULONG lHash,
8500 WORD wFlags,
8501 ITypeInfo ** ppTInfo,
8502 DESCKIND * pDescKind,
8503 BINDPTR * pBindPtr)
8505 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8506 const TLBFuncDesc *pFDesc;
8507 const TLBVarDesc *pVDesc;
8508 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8509 UINT fdc;
8511 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8513 *pDescKind = DESCKIND_NONE;
8514 pBindPtr->lpfuncdesc = NULL;
8515 *ppTInfo = NULL;
8517 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8518 pFDesc = &This->funcdescs[fdc];
8519 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8520 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8521 break;
8522 else
8523 /* name found, but wrong flags */
8524 hr = TYPE_E_TYPEMISMATCH;
8528 if (fdc < This->typeattr.cFuncs)
8530 HRESULT hr = TLB_AllocAndInitFuncDesc(
8531 &pFDesc->funcdesc,
8532 &pBindPtr->lpfuncdesc,
8533 This->typeattr.typekind == TKIND_DISPATCH);
8534 if (FAILED(hr))
8535 return hr;
8536 *pDescKind = DESCKIND_FUNCDESC;
8537 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8538 ITypeInfo_AddRef(*ppTInfo);
8539 return S_OK;
8540 } else {
8541 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, szName);
8542 if(pVDesc){
8543 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8544 if (FAILED(hr))
8545 return hr;
8546 *pDescKind = DESCKIND_VARDESC;
8547 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8548 ITypeInfo_AddRef(*ppTInfo);
8549 return S_OK;
8553 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8554 /* recursive search */
8555 ITypeInfo *pTInfo;
8556 ITypeComp *pTComp;
8557 HRESULT hr;
8558 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8559 if (SUCCEEDED(hr))
8561 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8562 ITypeInfo_Release(pTInfo);
8564 if (SUCCEEDED(hr))
8566 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8567 ITypeComp_Release(pTComp);
8568 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8569 This->typeattr.typekind == TKIND_DISPATCH)
8571 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8572 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8573 SysFreeString((BSTR)tmp);
8575 return hr;
8577 WARN("Could not search inherited interface!\n");
8579 if (hr == DISP_E_MEMBERNOTFOUND)
8580 hr = S_OK;
8581 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8582 return hr;
8585 static HRESULT WINAPI ITypeComp_fnBindType(
8586 ITypeComp * iface,
8587 OLECHAR * szName,
8588 ULONG lHash,
8589 ITypeInfo ** ppTInfo,
8590 ITypeComp ** ppTComp)
8592 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8594 /* strange behaviour (does nothing) but like the
8595 * original */
8597 if (!ppTInfo || !ppTComp)
8598 return E_POINTER;
8600 *ppTInfo = NULL;
8601 *ppTComp = NULL;
8603 return S_OK;
8606 static const ITypeCompVtbl tcompvt =
8609 ITypeComp_fnQueryInterface,
8610 ITypeComp_fnAddRef,
8611 ITypeComp_fnRelease,
8613 ITypeComp_fnBind,
8614 ITypeComp_fnBindType
8617 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8618 ICreateTypeLib2** ppctlib)
8620 ITypeLibImpl *This;
8621 HRESULT hres;
8623 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8625 if (!szFile) return E_INVALIDARG;
8627 This = TypeLibImpl_Constructor();
8628 if (!This)
8629 return E_OUTOFMEMORY;
8631 This->lcid = GetSystemDefaultLCID();
8632 This->syskind = syskind;
8633 This->ptr_size = get_ptr_size(syskind);
8635 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8636 if (!This->path) {
8637 ITypeLib2_Release(&This->ITypeLib2_iface);
8638 return E_OUTOFMEMORY;
8640 lstrcpyW(This->path, szFile);
8642 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8643 ITypeLib2_Release(&This->ITypeLib2_iface);
8644 return hres;
8647 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8648 REFIID riid, void **object)
8650 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8652 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8655 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8657 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8659 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8662 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8664 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8666 return ITypeLib2_Release(&This->ITypeLib2_iface);
8669 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8670 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8672 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8673 ITypeInfoImpl *info;
8674 HRESULT hres;
8676 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8678 if (!ctinfo || !name)
8679 return E_INVALIDARG;
8681 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8682 if (info)
8683 return TYPE_E_NAMECONFLICT;
8685 if (This->typeinfos)
8686 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8687 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8688 else
8689 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8691 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8693 info->pTypeLib = This;
8694 info->Name = TLB_append_str(&This->name_list, name);
8695 info->index = This->TypeInfoCount;
8696 info->typeattr.typekind = kind;
8697 info->typeattr.cbAlignment = 4;
8699 switch (info->typeattr.typekind) {
8700 case TKIND_ENUM:
8701 case TKIND_INTERFACE:
8702 case TKIND_DISPATCH:
8703 case TKIND_COCLASS:
8704 info->typeattr.cbSizeInstance = This->ptr_size;
8705 break;
8706 case TKIND_RECORD:
8707 case TKIND_UNION:
8708 info->typeattr.cbSizeInstance = 0;
8709 break;
8710 case TKIND_MODULE:
8711 info->typeattr.cbSizeInstance = 2;
8712 break;
8713 case TKIND_ALIAS:
8714 info->typeattr.cbSizeInstance = -0x75;
8715 break;
8716 default:
8717 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
8718 info->typeattr.cbSizeInstance = 0xdeadbeef;
8719 break;
8722 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8723 &IID_ICreateTypeInfo, (void **)ctinfo);
8724 if (FAILED(hres)) {
8725 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8726 return hres;
8729 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8731 ++This->TypeInfoCount;
8733 return S_OK;
8736 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8737 LPOLESTR name)
8739 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8741 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8743 if (!name)
8744 return E_INVALIDARG;
8746 This->Name = TLB_append_str(&This->name_list, name);
8748 return S_OK;
8751 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8752 WORD majorVerNum, WORD minorVerNum)
8754 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8756 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8758 This->ver_major = majorVerNum;
8759 This->ver_minor = minorVerNum;
8761 return S_OK;
8764 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8765 REFGUID guid)
8767 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8769 TRACE("%p %s\n", This, debugstr_guid(guid));
8771 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8773 return S_OK;
8776 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8777 LPOLESTR doc)
8779 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8781 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8783 if (!doc)
8784 return E_INVALIDARG;
8786 This->DocString = TLB_append_str(&This->string_list, doc);
8788 return S_OK;
8791 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8792 LPOLESTR helpFileName)
8794 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8796 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8798 if (!helpFileName)
8799 return E_INVALIDARG;
8801 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8803 return S_OK;
8806 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8807 DWORD helpContext)
8809 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8811 TRACE("%p %d\n", This, helpContext);
8813 This->dwHelpContext = helpContext;
8815 return S_OK;
8818 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8819 LCID lcid)
8821 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8823 TRACE("%p %x\n", This, lcid);
8825 This->set_lcid = lcid;
8827 return S_OK;
8830 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8831 UINT libFlags)
8833 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8835 TRACE("%p %x\n", This, libFlags);
8837 This->libflags = libFlags;
8839 return S_OK;
8842 typedef struct tagWMSFT_SegContents {
8843 DWORD len;
8844 void *data;
8845 } WMSFT_SegContents;
8847 typedef struct tagWMSFT_TLBFile {
8848 MSFT_Header header;
8849 WMSFT_SegContents typeinfo_seg;
8850 WMSFT_SegContents impfile_seg;
8851 WMSFT_SegContents impinfo_seg;
8852 WMSFT_SegContents ref_seg;
8853 WMSFT_SegContents guidhash_seg;
8854 WMSFT_SegContents guid_seg;
8855 WMSFT_SegContents namehash_seg;
8856 WMSFT_SegContents name_seg;
8857 WMSFT_SegContents string_seg;
8858 WMSFT_SegContents typdesc_seg;
8859 WMSFT_SegContents arraydesc_seg;
8860 WMSFT_SegContents custdata_seg;
8861 WMSFT_SegContents cdguids_seg;
8862 MSFT_SegDir segdir;
8863 WMSFT_SegContents aux_seg;
8864 } WMSFT_TLBFile;
8866 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8867 WMSFT_TLBFile *file)
8869 TLBString *str;
8870 UINT last_offs;
8871 char *data;
8873 file->string_seg.len = 0;
8874 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8875 int size;
8877 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8878 if (size == 0)
8879 return E_UNEXPECTED;
8881 size += sizeof(INT16);
8882 if (size % 4)
8883 size = (size + 4) & ~0x3;
8884 if (size < 8)
8885 size = 8;
8887 file->string_seg.len += size;
8889 /* temporarily use str->offset to store the length of the aligned,
8890 * converted string */
8891 str->offset = size;
8894 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8896 last_offs = 0;
8897 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8898 int size;
8900 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8901 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8902 if (size == 0) {
8903 heap_free(file->string_seg.data);
8904 return E_UNEXPECTED;
8907 *((INT16*)data) = size;
8909 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8911 size = str->offset;
8912 data += size;
8913 str->offset = last_offs;
8914 last_offs += size;
8917 return S_OK;
8920 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8921 WMSFT_TLBFile *file)
8923 TLBString *str;
8924 UINT last_offs;
8925 char *data;
8926 MSFT_NameIntro *last_intro = NULL;
8928 file->header.nametablecount = 0;
8929 file->header.nametablechars = 0;
8931 file->name_seg.len = 0;
8932 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8933 int size;
8935 size = strlenW(str->str);
8936 file->header.nametablechars += size;
8937 file->header.nametablecount++;
8939 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8940 if (size == 0)
8941 return E_UNEXPECTED;
8943 size += sizeof(MSFT_NameIntro);
8944 if (size % 4)
8945 size = (size + 4) & ~0x3;
8946 if (size < 8)
8947 size = 8;
8949 file->name_seg.len += size;
8951 /* temporarily use str->offset to store the length of the aligned,
8952 * converted string */
8953 str->offset = size;
8956 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8957 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8959 last_offs = 0;
8960 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8961 int size, hash;
8962 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8964 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8965 data + sizeof(MSFT_NameIntro),
8966 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8967 if (size == 0) {
8968 heap_free(file->name_seg.data);
8969 return E_UNEXPECTED;
8971 data[sizeof(MSFT_NameIntro) + size] = '\0';
8973 intro->hreftype = -1; /* TODO? */
8974 intro->namelen = size & 0xFF;
8975 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8976 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
8977 intro->namelen |= hash << 16;
8978 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
8979 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
8981 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8982 str->offset - size - sizeof(MSFT_NameIntro));
8984 /* update str->offset to actual value to use in other
8985 * compilation functions that require positions within
8986 * the string table */
8987 last_intro = intro;
8988 size = str->offset;
8989 data += size;
8990 str->offset = last_offs;
8991 last_offs += size;
8994 if(last_intro)
8995 last_intro->hreftype = 0; /* last one is 0? */
8997 return S_OK;
9000 static inline int hash_guid(GUID *guid)
9002 int i, hash = 0;
9004 for (i = 0; i < 8; i ++)
9005 hash ^= ((const short *)guid)[i];
9007 return hash & 0x1f;
9010 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9012 TLBGuid *guid;
9013 MSFT_GuidEntry *entry;
9014 DWORD offs;
9015 int hash_key, *guidhashtab;
9017 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9018 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9020 entry = file->guid_seg.data;
9021 offs = 0;
9022 guidhashtab = file->guidhash_seg.data;
9023 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9024 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9025 entry->hreftype = guid->hreftype;
9027 hash_key = hash_guid(&guid->guid);
9028 entry->next_hash = guidhashtab[hash_key];
9029 guidhashtab[hash_key] = offs;
9031 guid->offset = offs;
9032 offs += sizeof(MSFT_GuidEntry);
9033 ++entry;
9036 return S_OK;
9039 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9041 VARIANT v = *value;
9042 VARTYPE arg_type = V_VT(value);
9043 int mask = 0;
9044 HRESULT hres;
9045 DWORD ret = file->custdata_seg.len;
9047 if(arg_type == VT_INT)
9048 arg_type = VT_I4;
9049 if(arg_type == VT_UINT)
9050 arg_type = VT_UI4;
9052 v = *value;
9053 if(V_VT(value) != arg_type) {
9054 hres = VariantChangeType(&v, value, 0, arg_type);
9055 if(FAILED(hres)){
9056 ERR("VariantChangeType failed: %08x\n", hres);
9057 return -1;
9061 /* Check if default value can be stored in-place */
9062 switch(arg_type){
9063 case VT_I4:
9064 case VT_UI4:
9065 mask = 0x3ffffff;
9066 if(V_UI4(&v) > 0x3ffffff)
9067 break;
9068 /* fall through */
9069 case VT_I1:
9070 case VT_UI1:
9071 case VT_BOOL:
9072 if(!mask)
9073 mask = 0xff;
9074 /* fall through */
9075 case VT_I2:
9076 case VT_UI2:
9077 if(!mask)
9078 mask = 0xffff;
9079 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9082 /* have to allocate space in custdata_seg */
9083 switch(arg_type) {
9084 case VT_I4:
9085 case VT_R4:
9086 case VT_UI4:
9087 case VT_INT:
9088 case VT_UINT:
9089 case VT_HRESULT:
9090 case VT_PTR: {
9091 /* Construct the data to be allocated */
9092 int *data;
9094 if(file->custdata_seg.data){
9095 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9096 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9097 file->custdata_seg.len += sizeof(int) * 2;
9098 }else{
9099 file->custdata_seg.len = sizeof(int) * 2;
9100 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9103 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9104 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9106 /* TODO: Check if the encoded data is already present in custdata_seg */
9108 return ret;
9111 case VT_BSTR: {
9112 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9113 char *data;
9115 if(file->custdata_seg.data){
9116 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9117 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9118 file->custdata_seg.len += len;
9119 }else{
9120 file->custdata_seg.len = len;
9121 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9124 *((unsigned short *)data) = V_VT(value);
9125 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9126 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9127 if(V_BSTR(&v)[i] <= 0x7f)
9128 data[i+6] = V_BSTR(&v)[i];
9129 else
9130 data[i+6] = '?';
9132 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9133 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9134 data[i] = 0x57;
9136 /* TODO: Check if the encoded data is already present in custdata_seg */
9138 return ret;
9140 default:
9141 FIXME("Argument type not yet handled\n");
9142 return -1;
9146 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9148 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9150 DWORD offs = file->arraydesc_seg.len;
9151 DWORD *encoded;
9152 USHORT i;
9154 /* TODO: we should check for duplicates, but that's harder because each
9155 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9156 * at the library-level) */
9158 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9159 if(!file->arraydesc_seg.data)
9160 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9161 else
9162 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9163 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9165 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9166 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9167 for(i = 0; i < desc->cDims; ++i){
9168 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9169 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9172 return offs;
9175 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9177 DWORD junk;
9178 INT16 junk2;
9179 DWORD offs = 0;
9180 DWORD encoded[2];
9181 VARTYPE vt, subtype;
9182 char *data;
9184 if(!desc)
9185 return -1;
9187 if(!out_mix)
9188 out_mix = &junk;
9189 if(!out_size)
9190 out_size = &junk2;
9192 vt = desc->vt & VT_TYPEMASK;
9194 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9195 DWORD mix;
9196 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9197 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9198 *out_mix = 0x7FFF;
9199 *out_size += 2 * sizeof(DWORD);
9200 }else if(vt == VT_CARRAY){
9201 encoded[0] = desc->vt | (0x7FFE << 16);
9202 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9203 *out_mix = 0x7FFE;
9204 }else if(vt == VT_USERDEFINED){
9205 encoded[0] = desc->vt | (0x7FFF << 16);
9206 encoded[1] = desc->u.hreftype;
9207 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9208 }else{
9209 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9211 switch(vt){
9212 case VT_INT:
9213 subtype = VT_I4;
9214 break;
9215 case VT_UINT:
9216 subtype = VT_UI4;
9217 break;
9218 case VT_VOID:
9219 subtype = VT_EMPTY;
9220 break;
9221 default:
9222 subtype = vt;
9223 break;
9226 *out_mix = subtype;
9227 return 0x80000000 | (subtype << 16) | desc->vt;
9230 data = file->typdesc_seg.data;
9231 while(offs < file->typdesc_seg.len){
9232 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9233 return offs;
9234 offs += sizeof(encoded);
9237 file->typdesc_seg.len += sizeof(encoded);
9238 if(!file->typdesc_seg.data)
9239 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9240 else
9241 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9243 memcpy(&data[offs], encoded, sizeof(encoded));
9245 return offs;
9248 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9250 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9251 DWORD ret = cdguids_seg->len, offs;
9252 MSFT_CDGuid *cdguid;
9253 TLBCustData *cd;
9255 if(list_empty(custdata_list))
9256 return -1;
9258 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9259 if(!cdguids_seg->data){
9260 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9261 }else {
9262 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9263 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9266 offs = ret + sizeof(MSFT_CDGuid);
9267 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9268 cdguid->GuidOffset = cd->guid->offset;
9269 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9270 cdguid->next = offs;
9271 offs += sizeof(MSFT_CDGuid);
9272 ++cdguid;
9275 --cdguid;
9276 cdguid->next = -1;
9278 return ret;
9281 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9282 WMSFT_TLBFile *file)
9284 WMSFT_SegContents *aux_seg = &file->aux_seg;
9285 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9286 MSFT_VarRecord *varrecord;
9287 MSFT_FuncRecord *funcrecord;
9288 MEMBERID *memid;
9289 DWORD *name, *offsets, offs;
9291 for(i = 0; i < info->typeattr.cFuncs; ++i){
9292 TLBFuncDesc *desc = &info->funcdescs[i];
9294 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9296 /* optional fields */
9297 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9298 if(!list_empty(&desc->custdata_list))
9299 recorded_size += 7 * sizeof(INT);
9300 else if(desc->HelpStringContext != 0)
9301 recorded_size += 6 * sizeof(INT);
9302 /* res9? resA? */
9303 else if(desc->Entry)
9304 recorded_size += 3 * sizeof(INT);
9305 else if(desc->HelpString)
9306 recorded_size += 2 * sizeof(INT);
9307 else if(desc->helpcontext)
9308 recorded_size += sizeof(INT);
9310 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9312 for(j = 0; j < desc->funcdesc.cParams; ++j){
9313 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9314 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9315 break;
9319 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9322 for(i = 0; i < info->typeattr.cVars; ++i){
9323 TLBVarDesc *desc = &info->vardescs[i];
9325 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9327 /* optional fields */
9328 if(desc->HelpStringContext != 0)
9329 recorded_size += 5 * sizeof(INT);
9330 else if(!list_empty(&desc->custdata_list))
9331 recorded_size += 4 * sizeof(INT);
9332 /* res9? */
9333 else if(desc->HelpString)
9334 recorded_size += 2 * sizeof(INT);
9335 else if(desc->HelpContext != 0)
9336 recorded_size += sizeof(INT);
9338 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9341 if(!recorded_size && !extra_size)
9342 return ret;
9344 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9346 aux_seg->len += recorded_size + extra_size;
9348 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9350 if(aux_seg->data)
9351 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9352 else
9353 aux_seg->data = heap_alloc(aux_seg->len);
9355 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9357 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9358 offs = 0;
9360 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9361 for(i = 0; i < info->typeattr.cFuncs; ++i){
9362 TLBFuncDesc *desc = &info->funcdescs[i];
9363 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9365 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9366 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9367 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9368 funcrecord->VtableOffset = desc->funcdesc.oVft;
9370 /* FKCCIC:
9371 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9372 * ^^^funckind
9373 * ^^^ ^invkind
9374 * ^has_cust_data
9375 * ^^^^callconv
9376 * ^has_param_defaults
9377 * ^oEntry_is_intresource
9379 funcrecord->FKCCIC =
9380 desc->funcdesc.funckind |
9381 (desc->funcdesc.invkind << 3) |
9382 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9383 (desc->funcdesc.callconv << 8);
9385 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9386 funcrecord->FKCCIC |= 0x2000;
9388 for(j = 0; j < desc->funcdesc.cParams; ++j){
9389 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9390 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9391 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9394 if(paramdefault_size > 0)
9395 funcrecord->FKCCIC |= 0x1000;
9397 funcrecord->nrargs = desc->funcdesc.cParams;
9398 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9400 /* optional fields */
9401 /* res9? resA? */
9402 if(!list_empty(&desc->custdata_list)){
9403 size += 7 * sizeof(INT);
9404 funcrecord->HelpContext = desc->helpcontext;
9405 if(desc->HelpString)
9406 funcrecord->oHelpString = desc->HelpString->offset;
9407 else
9408 funcrecord->oHelpString = -1;
9409 if(!desc->Entry)
9410 funcrecord->oEntry = -1;
9411 else if(IS_INTRESOURCE(desc->Entry))
9412 funcrecord->oEntry = LOWORD(desc->Entry);
9413 else
9414 funcrecord->oEntry = desc->Entry->offset;
9415 funcrecord->res9 = -1;
9416 funcrecord->resA = -1;
9417 funcrecord->HelpStringContext = desc->HelpStringContext;
9418 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9419 }else if(desc->HelpStringContext != 0){
9420 size += 6 * sizeof(INT);
9421 funcrecord->HelpContext = desc->helpcontext;
9422 if(desc->HelpString)
9423 funcrecord->oHelpString = desc->HelpString->offset;
9424 else
9425 funcrecord->oHelpString = -1;
9426 if(!desc->Entry)
9427 funcrecord->oEntry = -1;
9428 else if(IS_INTRESOURCE(desc->Entry))
9429 funcrecord->oEntry = LOWORD(desc->Entry);
9430 else
9431 funcrecord->oEntry = desc->Entry->offset;
9432 funcrecord->res9 = -1;
9433 funcrecord->resA = -1;
9434 funcrecord->HelpStringContext = desc->HelpStringContext;
9435 }else if(desc->Entry){
9436 size += 3 * sizeof(INT);
9437 funcrecord->HelpContext = desc->helpcontext;
9438 if(desc->HelpString)
9439 funcrecord->oHelpString = desc->HelpString->offset;
9440 else
9441 funcrecord->oHelpString = -1;
9442 if(!desc->Entry)
9443 funcrecord->oEntry = -1;
9444 else if(IS_INTRESOURCE(desc->Entry))
9445 funcrecord->oEntry = LOWORD(desc->Entry);
9446 else
9447 funcrecord->oEntry = desc->Entry->offset;
9448 }else if(desc->HelpString){
9449 size += 2 * sizeof(INT);
9450 funcrecord->HelpContext = desc->helpcontext;
9451 funcrecord->oHelpString = desc->HelpString->offset;
9452 }else if(desc->helpcontext){
9453 size += sizeof(INT);
9454 funcrecord->HelpContext = desc->helpcontext;
9457 paramdefault = (DWORD*)((char *)funcrecord + size);
9458 size += paramdefault_size;
9460 for(j = 0; j < desc->funcdesc.cParams; ++j){
9461 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9463 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9464 if(desc->pParamDesc[j].Name)
9465 info->oName = desc->pParamDesc[j].Name->offset;
9466 else
9467 info->oName = -1;
9468 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9470 if(paramdefault_size){
9471 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9472 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9473 else if(paramdefault_size)
9474 *paramdefault = -1;
9475 ++paramdefault;
9478 size += sizeof(MSFT_ParameterInfo);
9481 funcrecord->Info = size | (i << 16); /* is it just the index? */
9483 *offsets = offs;
9484 offs += size;
9485 ++offsets;
9487 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9490 varrecord = (MSFT_VarRecord*)funcrecord;
9491 for(i = 0; i < info->typeattr.cVars; ++i){
9492 TLBVarDesc *desc = &info->vardescs[i];
9493 DWORD size = 5 * sizeof(INT);
9495 varrecord->vardescsize = sizeof(desc->vardesc);
9496 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9497 varrecord->Flags = desc->vardesc.wVarFlags;
9498 varrecord->VarKind = desc->vardesc.varkind;
9500 if(desc->vardesc.varkind == VAR_CONST){
9501 varrecord->vardescsize += sizeof(VARIANT);
9502 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9503 }else
9504 varrecord->OffsValue = desc->vardesc.u.oInst;
9506 /* res9? */
9507 if(desc->HelpStringContext != 0){
9508 size += 5 * sizeof(INT);
9509 varrecord->HelpContext = desc->HelpContext;
9510 if(desc->HelpString)
9511 varrecord->HelpString = desc->HelpString->offset;
9512 else
9513 varrecord->HelpString = -1;
9514 varrecord->res9 = -1;
9515 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9516 varrecord->HelpStringContext = desc->HelpStringContext;
9517 }else if(!list_empty(&desc->custdata_list)){
9518 size += 4 * sizeof(INT);
9519 varrecord->HelpContext = desc->HelpContext;
9520 if(desc->HelpString)
9521 varrecord->HelpString = desc->HelpString->offset;
9522 else
9523 varrecord->HelpString = -1;
9524 varrecord->res9 = -1;
9525 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9526 }else if(desc->HelpString){
9527 size += 2 * sizeof(INT);
9528 varrecord->HelpContext = desc->HelpContext;
9529 if(desc->HelpString)
9530 varrecord->HelpString = desc->HelpString->offset;
9531 else
9532 varrecord->HelpString = -1;
9533 }else if(desc->HelpContext != 0){
9534 size += sizeof(INT);
9535 varrecord->HelpContext = desc->HelpContext;
9538 varrecord->Info = size | (i << 16);
9540 *offsets = offs;
9541 offs += size;
9542 ++offsets;
9544 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9547 memid = (MEMBERID*)varrecord;
9548 for(i = 0; i < info->typeattr.cFuncs; ++i){
9549 TLBFuncDesc *desc = &info->funcdescs[i];
9550 *memid = desc->funcdesc.memid;
9551 ++memid;
9553 for(i = 0; i < info->typeattr.cVars; ++i){
9554 TLBVarDesc *desc = &info->vardescs[i];
9555 *memid = desc->vardesc.memid;
9556 ++memid;
9559 name = (UINT*)memid;
9560 for(i = 0; i < info->typeattr.cFuncs; ++i){
9561 TLBFuncDesc *desc = &info->funcdescs[i];
9562 if(desc->Name)
9563 *name = desc->Name->offset;
9564 else
9565 *name = -1;
9566 ++name;
9568 for(i = 0; i < info->typeattr.cVars; ++i){
9569 TLBVarDesc *desc = &info->vardescs[i];
9570 if(desc->Name)
9571 *name = desc->Name->offset;
9572 else
9573 *name = -1;
9574 ++name;
9577 return ret;
9580 typedef struct tagWMSFT_RefChunk {
9581 DWORD href;
9582 DWORD res04;
9583 DWORD res08;
9584 DWORD next;
9585 } WMSFT_RefChunk;
9587 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9589 DWORD offs = file->ref_seg.len, i;
9590 WMSFT_RefChunk *chunk;
9592 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9593 if(!file->ref_seg.data)
9594 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9595 else
9596 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9598 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9600 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9601 chunk->href = info->impltypes[i].hRef;
9602 chunk->res04 = info->impltypes[i].implflags;
9603 chunk->res08 = -1;
9604 if(i < info->typeattr.cImplTypes - 1)
9605 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9606 else
9607 chunk->next = -1;
9608 ++chunk;
9611 return offs;
9614 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9616 DWORD size;
9618 size = sizeof(MSFT_TypeInfoBase);
9620 if(data){
9621 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9622 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9623 base->typekind = TKIND_DISPATCH;
9624 else
9625 base->typekind = info->typeattr.typekind;
9626 base->typekind |= index << 16; /* TODO: There are some other flags here */
9627 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9628 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9629 base->res2 = 0;
9630 base->res3 = 0;
9631 base->res4 = 3;
9632 base->res5 = 0;
9633 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9634 base->res7 = 0;
9635 base->res8 = 0;
9636 base->res9 = 0;
9637 base->resA = 0;
9638 if(info->guid)
9639 base->posguid = info->guid->offset;
9640 else
9641 base->posguid = -1;
9642 base->flags = info->typeattr.wTypeFlags;
9643 if(info->Name) {
9644 base->NameOffset = info->Name->offset;
9646 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9647 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9648 }else {
9649 base->NameOffset = -1;
9651 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9652 if(info->DocString)
9653 base->docstringoffs = info->DocString->offset;
9654 else
9655 base->docstringoffs = -1;
9656 base->helpstringcontext = info->dwHelpStringContext;
9657 base->helpcontext = info->dwHelpContext;
9658 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9659 base->cImplTypes = info->typeattr.cImplTypes;
9660 base->cbSizeVft = info->typeattr.cbSizeVft;
9661 base->size = info->typeattr.cbSizeInstance;
9662 if(info->typeattr.typekind == TKIND_COCLASS){
9663 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9664 }else if(info->typeattr.typekind == TKIND_ALIAS){
9665 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9666 }else if(info->typeattr.typekind == TKIND_MODULE){
9667 if(info->DllName)
9668 base->datatype1 = info->DllName->offset;
9669 else
9670 base->datatype1 = -1;
9671 }else{
9672 if(info->typeattr.cImplTypes > 0)
9673 base->datatype1 = info->impltypes[0].hRef;
9674 else
9675 base->datatype1 = -1;
9677 base->datatype2 = index; /* FIXME: i think there's more here */
9678 base->res18 = 0;
9679 base->res19 = -1;
9682 return size;
9685 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9687 UINT i;
9689 file->typeinfo_seg.len = 0;
9690 for(i = 0; i < This->TypeInfoCount; ++i){
9691 ITypeInfoImpl *info = This->typeinfos[i];
9692 *junk = file->typeinfo_seg.len;
9693 ++junk;
9694 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9697 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9698 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9700 file->aux_seg.len = 0;
9701 file->aux_seg.data = NULL;
9703 file->typeinfo_seg.len = 0;
9704 for(i = 0; i < This->TypeInfoCount; ++i){
9705 ITypeInfoImpl *info = This->typeinfos[i];
9706 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9707 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9711 typedef struct tagWMSFT_ImpFile {
9712 INT guid_offs;
9713 LCID lcid;
9714 DWORD version;
9715 } WMSFT_ImpFile;
9717 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9719 TLBImpLib *implib;
9720 WMSFT_ImpFile *impfile;
9721 char *data;
9722 DWORD last_offs = 0;
9724 file->impfile_seg.len = 0;
9725 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9726 int size = 0;
9728 if(implib->name){
9729 WCHAR *path = strrchrW(implib->name, '\\');
9730 if(path)
9731 ++path;
9732 else
9733 path = implib->name;
9734 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9735 if (size == 0)
9736 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9739 size += sizeof(INT16);
9740 if (size % 4)
9741 size = (size + 4) & ~0x3;
9742 if (size < 8)
9743 size = 8;
9745 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9748 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9750 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9751 int strlen = 0, size;
9753 impfile = (WMSFT_ImpFile*)data;
9754 impfile->guid_offs = implib->guid->offset;
9755 impfile->lcid = implib->lcid;
9756 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9758 data += sizeof(WMSFT_ImpFile);
9760 if(implib->name){
9761 WCHAR *path= strrchrW(implib->name, '\\');
9762 if(path)
9763 ++path;
9764 else
9765 path = implib->name;
9766 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9767 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9768 if (strlen == 0)
9769 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9772 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9774 size = strlen + sizeof(INT16);
9775 if (size % 4)
9776 size = (size + 4) & ~0x3;
9777 if (size < 8)
9778 size = 8;
9779 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9781 data += size;
9782 implib->offset = last_offs;
9783 last_offs += size + sizeof(WMSFT_ImpFile);
9787 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9789 MSFT_ImpInfo *info;
9790 TLBRefType *ref_type;
9791 UINT i = 0;
9793 WMSFT_compile_impfile(This, file);
9795 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9796 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9798 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9799 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9800 if(ref_type->index == TLB_REF_USE_GUID){
9801 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9802 info->oGuid = ref_type->guid->offset;
9803 }else
9804 info->oGuid = ref_type->index;
9805 info->oImpFile = ref_type->pImpTLInfo->offset;
9806 ++i;
9807 ++info;
9811 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9813 file->guidhash_seg.len = 0x80;
9814 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9815 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9818 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9820 file->namehash_seg.len = 0x200;
9821 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9822 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9825 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9827 if(contents && contents->len){
9828 segdir->offset = *running_offset;
9829 segdir->length = contents->len;
9830 *running_offset += segdir->length;
9831 }else{
9832 segdir->offset = -1;
9833 segdir->length = 0;
9836 /* TODO: do these ever change? */
9837 segdir->res08 = -1;
9838 segdir->res0c = 0xf;
9841 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9843 DWORD written;
9844 if(segment)
9845 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9848 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9849 DWORD file_len)
9851 DWORD i;
9852 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9854 for(i = 0; i < This->TypeInfoCount; ++i){
9855 base->memoffset += file_len;
9856 ++base;
9859 return S_OK;
9862 static void WMSFT_free_file(WMSFT_TLBFile *file)
9864 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9865 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9866 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9867 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9868 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9869 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9870 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9871 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9872 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9873 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9874 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9875 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9876 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9877 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9880 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9882 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9883 WMSFT_TLBFile file;
9884 DWORD written, junk_size, junk_offs, running_offset;
9885 BOOL br;
9886 HANDLE outfile;
9887 HRESULT hres;
9888 DWORD *junk;
9889 UINT i;
9891 TRACE("%p\n", This);
9893 for(i = 0; i < This->TypeInfoCount; ++i)
9894 if(This->typeinfos[i]->needs_layout)
9895 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9897 memset(&file, 0, sizeof(file));
9899 file.header.magic1 = 0x5446534D;
9900 file.header.magic2 = 0x00010002;
9901 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9902 file.header.lcid2 = This->set_lcid;
9903 file.header.varflags = 0x40 | This->syskind;
9904 if (This->HelpFile)
9905 file.header.varflags |= 0x10;
9906 if (This->HelpStringDll)
9907 file.header.varflags |= HELPDLLFLAG;
9908 file.header.version = (This->ver_minor << 16) | This->ver_major;
9909 file.header.flags = This->libflags;
9910 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9911 file.header.helpcontext = This->dwHelpContext;
9912 file.header.res44 = 0x20;
9913 file.header.res48 = 0x80;
9914 file.header.dispatchpos = This->dispatch_href;
9916 WMSFT_compile_namehash(This, &file);
9917 /* do name and string compilation to get offsets for other compilations */
9918 hres = WMSFT_compile_names(This, &file);
9919 if (FAILED(hres)){
9920 WMSFT_free_file(&file);
9921 return hres;
9924 hres = WMSFT_compile_strings(This, &file);
9925 if (FAILED(hres)){
9926 WMSFT_free_file(&file);
9927 return hres;
9930 WMSFT_compile_guidhash(This, &file);
9931 hres = WMSFT_compile_guids(This, &file);
9932 if (FAILED(hres)){
9933 WMSFT_free_file(&file);
9934 return hres;
9937 if(This->HelpFile)
9938 file.header.helpfile = This->HelpFile->offset;
9939 else
9940 file.header.helpfile = -1;
9942 if(This->DocString)
9943 file.header.helpstring = This->DocString->offset;
9944 else
9945 file.header.helpstring = -1;
9947 /* do some more segment compilation */
9948 file.header.nimpinfos = list_count(&This->ref_list);
9949 file.header.nrtypeinfos = This->TypeInfoCount;
9951 if(This->Name)
9952 file.header.NameOffset = This->Name->offset;
9953 else
9954 file.header.NameOffset = -1;
9956 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
9958 if(This->guid)
9959 file.header.posguid = This->guid->offset;
9960 else
9961 file.header.posguid = -1;
9963 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9964 if(file.header.varflags & HELPDLLFLAG)
9965 junk_size += sizeof(DWORD);
9966 if(junk_size){
9967 junk = heap_alloc_zero(junk_size);
9968 if(file.header.varflags & HELPDLLFLAG){
9969 *junk = This->HelpStringDll->offset;
9970 junk_offs = 1;
9971 }else
9972 junk_offs = 0;
9973 }else{
9974 junk = NULL;
9975 junk_offs = 0;
9978 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9979 WMSFT_compile_impinfo(This, &file);
9981 running_offset = 0;
9983 TRACE("header at: 0x%x\n", running_offset);
9984 running_offset += sizeof(file.header);
9986 TRACE("junk at: 0x%x\n", running_offset);
9987 running_offset += junk_size;
9989 TRACE("segdir at: 0x%x\n", running_offset);
9990 running_offset += sizeof(file.segdir);
9992 TRACE("typeinfo at: 0x%x\n", running_offset);
9993 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
9995 TRACE("guidhashtab at: 0x%x\n", running_offset);
9996 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
9998 TRACE("guidtab at: 0x%x\n", running_offset);
9999 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10001 TRACE("reftab at: 0x%x\n", running_offset);
10002 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10004 TRACE("impinfo at: 0x%x\n", running_offset);
10005 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10007 TRACE("impfiles at: 0x%x\n", running_offset);
10008 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10010 TRACE("namehashtab at: 0x%x\n", running_offset);
10011 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10013 TRACE("nametab at: 0x%x\n", running_offset);
10014 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10016 TRACE("stringtab at: 0x%x\n", running_offset);
10017 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10019 TRACE("typdesc at: 0x%x\n", running_offset);
10020 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10022 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10023 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10025 TRACE("custdata at: 0x%x\n", running_offset);
10026 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10028 TRACE("cdguids at: 0x%x\n", running_offset);
10029 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10031 TRACE("res0e at: 0x%x\n", running_offset);
10032 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10034 TRACE("res0f at: 0x%x\n", running_offset);
10035 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10037 TRACE("aux_seg at: 0x%x\n", running_offset);
10039 WMSFT_fixup_typeinfos(This, &file, running_offset);
10041 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10042 FILE_ATTRIBUTE_NORMAL, 0);
10043 if (outfile == INVALID_HANDLE_VALUE){
10044 WMSFT_free_file(&file);
10045 heap_free(junk);
10046 return TYPE_E_IOERROR;
10049 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10050 if (!br) {
10051 WMSFT_free_file(&file);
10052 CloseHandle(outfile);
10053 heap_free(junk);
10054 return TYPE_E_IOERROR;
10057 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10058 heap_free(junk);
10059 if (!br) {
10060 WMSFT_free_file(&file);
10061 CloseHandle(outfile);
10062 return TYPE_E_IOERROR;
10065 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10066 if (!br) {
10067 WMSFT_free_file(&file);
10068 CloseHandle(outfile);
10069 return TYPE_E_IOERROR;
10072 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10073 WMSFT_write_segment(outfile, &file.guidhash_seg);
10074 WMSFT_write_segment(outfile, &file.guid_seg);
10075 WMSFT_write_segment(outfile, &file.ref_seg);
10076 WMSFT_write_segment(outfile, &file.impinfo_seg);
10077 WMSFT_write_segment(outfile, &file.impfile_seg);
10078 WMSFT_write_segment(outfile, &file.namehash_seg);
10079 WMSFT_write_segment(outfile, &file.name_seg);
10080 WMSFT_write_segment(outfile, &file.string_seg);
10081 WMSFT_write_segment(outfile, &file.typdesc_seg);
10082 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10083 WMSFT_write_segment(outfile, &file.custdata_seg);
10084 WMSFT_write_segment(outfile, &file.cdguids_seg);
10085 WMSFT_write_segment(outfile, &file.aux_seg);
10087 WMSFT_free_file(&file);
10089 CloseHandle(outfile);
10091 return S_OK;
10094 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10095 LPOLESTR name)
10097 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10098 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10099 return E_NOTIMPL;
10102 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10103 REFGUID guid, VARIANT *varVal)
10105 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10106 TLBGuid *tlbguid;
10108 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10110 if (!guid || !varVal)
10111 return E_INVALIDARG;
10113 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10115 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10118 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10119 ULONG helpStringContext)
10121 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10122 FIXME("%p %u - stub\n", This, helpStringContext);
10123 return E_NOTIMPL;
10126 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10127 LPOLESTR filename)
10129 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10130 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10132 if (!filename)
10133 return E_INVALIDARG;
10135 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10137 return S_OK;
10140 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10141 ICreateTypeLib2_fnQueryInterface,
10142 ICreateTypeLib2_fnAddRef,
10143 ICreateTypeLib2_fnRelease,
10144 ICreateTypeLib2_fnCreateTypeInfo,
10145 ICreateTypeLib2_fnSetName,
10146 ICreateTypeLib2_fnSetVersion,
10147 ICreateTypeLib2_fnSetGuid,
10148 ICreateTypeLib2_fnSetDocString,
10149 ICreateTypeLib2_fnSetHelpFileName,
10150 ICreateTypeLib2_fnSetHelpContext,
10151 ICreateTypeLib2_fnSetLcid,
10152 ICreateTypeLib2_fnSetLibFlags,
10153 ICreateTypeLib2_fnSaveAllChanges,
10154 ICreateTypeLib2_fnDeleteTypeInfo,
10155 ICreateTypeLib2_fnSetCustData,
10156 ICreateTypeLib2_fnSetHelpStringContext,
10157 ICreateTypeLib2_fnSetHelpStringDll
10160 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10161 REFIID riid, void **object)
10163 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10165 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10168 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10170 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10172 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10175 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10177 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10179 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10182 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10183 REFGUID guid)
10185 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10187 TRACE("%p %s\n", This, debugstr_guid(guid));
10189 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10191 return S_OK;
10194 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10195 UINT typeFlags)
10197 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10198 WORD old_flags;
10199 HRESULT hres;
10201 TRACE("%p %x\n", This, typeFlags);
10203 if (typeFlags & TYPEFLAG_FDUAL) {
10204 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10205 ITypeLib *stdole;
10206 ITypeInfo *dispatch;
10207 HREFTYPE hreftype;
10208 HRESULT hres;
10210 hres = LoadTypeLib(stdole2tlb, &stdole);
10211 if(FAILED(hres))
10212 return hres;
10214 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10215 ITypeLib_Release(stdole);
10216 if(FAILED(hres))
10217 return hres;
10219 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10220 ITypeInfo_Release(dispatch);
10221 if(FAILED(hres))
10222 return hres;
10225 old_flags = This->typeattr.wTypeFlags;
10226 This->typeattr.wTypeFlags = typeFlags;
10228 hres = ICreateTypeInfo2_LayOut(iface);
10229 if (FAILED(hres)) {
10230 This->typeattr.wTypeFlags = old_flags;
10231 return hres;
10234 return S_OK;
10237 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10238 LPOLESTR doc)
10240 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10242 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10244 if (!doc)
10245 return E_INVALIDARG;
10247 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10249 return S_OK;
10252 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10253 DWORD helpContext)
10255 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10257 TRACE("%p %d\n", This, helpContext);
10259 This->dwHelpContext = helpContext;
10261 return S_OK;
10264 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10265 WORD majorVerNum, WORD minorVerNum)
10267 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10269 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10271 This->typeattr.wMajorVerNum = majorVerNum;
10272 This->typeattr.wMinorVerNum = minorVerNum;
10274 return S_OK;
10277 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10278 ITypeInfo *typeInfo, HREFTYPE *refType)
10280 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10281 UINT index;
10282 ITypeLib *container;
10283 TLBRefType *ref_type;
10284 TLBImpLib *implib;
10285 TYPEATTR *typeattr;
10286 TLIBATTR *libattr;
10287 HRESULT hres;
10289 TRACE("%p %p %p\n", This, typeInfo, refType);
10291 if (!typeInfo || !refType)
10292 return E_INVALIDARG;
10294 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10295 if (FAILED(hres))
10296 return hres;
10298 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10299 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10301 ITypeLib_Release(container);
10303 *refType = target->hreftype;
10305 return S_OK;
10308 hres = ITypeLib_GetLibAttr(container, &libattr);
10309 if (FAILED(hres)) {
10310 ITypeLib_Release(container);
10311 return hres;
10314 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10315 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10316 implib->lcid == libattr->lcid &&
10317 implib->wVersionMajor == libattr->wMajorVerNum &&
10318 implib->wVersionMinor == libattr->wMinorVerNum)
10319 break;
10322 if(&implib->entry == &This->pTypeLib->implib_list){
10323 implib = heap_alloc_zero(sizeof(TLBImpLib));
10325 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10326 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10327 implib->name = SysAllocString(our_container->path);
10328 }else{
10329 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10330 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10331 if(FAILED(hres)){
10332 implib->name = NULL;
10333 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10337 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10338 implib->lcid = libattr->lcid;
10339 implib->wVersionMajor = libattr->wMajorVerNum;
10340 implib->wVersionMinor = libattr->wMinorVerNum;
10342 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10345 ITypeLib_ReleaseTLibAttr(container, libattr);
10346 ITypeLib_Release(container);
10348 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10349 if (FAILED(hres))
10350 return hres;
10352 index = 0;
10353 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10354 if(ref_type->index == TLB_REF_USE_GUID &&
10355 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10356 ref_type->tkind == typeattr->typekind)
10357 break;
10358 ++index;
10361 if(&ref_type->entry == &This->pTypeLib->ref_list){
10362 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10364 ref_type->tkind = typeattr->typekind;
10365 ref_type->pImpTLInfo = implib;
10366 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10368 ref_type->index = TLB_REF_USE_GUID;
10370 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10372 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10375 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10377 *refType = ref_type->reference | 0x1;
10379 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10380 This->pTypeLib->dispatch_href = *refType;
10382 return S_OK;
10385 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10386 UINT index, FUNCDESC *funcDesc)
10388 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10389 TLBFuncDesc tmp_func_desc, *func_desc;
10390 int buf_size, i;
10391 char *buffer;
10392 HRESULT hres;
10394 TRACE("%p %u %p\n", This, index, funcDesc);
10396 if (!funcDesc || funcDesc->oVft & 3)
10397 return E_INVALIDARG;
10399 switch (This->typeattr.typekind) {
10400 case TKIND_MODULE:
10401 if (funcDesc->funckind != FUNC_STATIC)
10402 return TYPE_E_BADMODULEKIND;
10403 break;
10404 case TKIND_DISPATCH:
10405 if (funcDesc->funckind != FUNC_DISPATCH)
10406 return TYPE_E_BADMODULEKIND;
10407 break;
10408 default:
10409 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10410 return TYPE_E_BADMODULEKIND;
10413 if (index > This->typeattr.cFuncs)
10414 return TYPE_E_ELEMENTNOTFOUND;
10416 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10417 !funcDesc->cParams)
10418 return TYPE_E_INCONSISTENTPROPFUNCS;
10420 #ifdef _WIN64
10421 if(This->pTypeLib->syskind == SYS_WIN64 &&
10422 funcDesc->oVft % 8 != 0)
10423 return E_INVALIDARG;
10424 #endif
10426 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10427 TLBFuncDesc_Constructor(&tmp_func_desc);
10429 tmp_func_desc.funcdesc = *funcDesc;
10431 if (tmp_func_desc.funcdesc.oVft != 0)
10432 tmp_func_desc.funcdesc.oVft |= 1;
10434 if (funcDesc->cScodes && funcDesc->lprgscode) {
10435 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10436 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10437 } else {
10438 tmp_func_desc.funcdesc.lprgscode = NULL;
10439 tmp_func_desc.funcdesc.cScodes = 0;
10442 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10443 for (i = 0; i < funcDesc->cParams; ++i) {
10444 buf_size += sizeof(ELEMDESC);
10445 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10447 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10448 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10450 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10451 if (FAILED(hres)) {
10452 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10453 heap_free(tmp_func_desc.funcdesc.lprgscode);
10454 return hres;
10457 for (i = 0; i < funcDesc->cParams; ++i) {
10458 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10459 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10460 if (FAILED(hres)) {
10461 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10462 heap_free(tmp_func_desc.funcdesc.lprgscode);
10463 return hres;
10465 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10466 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10467 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10468 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10469 if (FAILED(hres)) {
10470 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10471 heap_free(tmp_func_desc.funcdesc.lprgscode);
10472 return hres;
10477 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10479 if (This->funcdescs) {
10480 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10481 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10483 if (index < This->typeattr.cFuncs) {
10484 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10485 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10486 func_desc = This->funcdescs + index;
10487 } else
10488 func_desc = This->funcdescs + This->typeattr.cFuncs;
10490 /* move custdata lists to the new memory location */
10491 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10492 if(index != i){
10493 TLBFuncDesc *fd = &This->funcdescs[i];
10494 if(fd->custdata_list.prev == fd->custdata_list.next)
10495 list_init(&fd->custdata_list);
10496 else{
10497 fd->custdata_list.prev->next = &fd->custdata_list;
10498 fd->custdata_list.next->prev = &fd->custdata_list;
10502 } else
10503 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10505 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10506 list_init(&func_desc->custdata_list);
10508 ++This->typeattr.cFuncs;
10510 This->needs_layout = TRUE;
10512 return S_OK;
10515 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10516 UINT index, HREFTYPE refType)
10518 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10519 TLBImplType *impl_type;
10520 HRESULT hres;
10522 TRACE("%p %u %d\n", This, index, refType);
10524 switch(This->typeattr.typekind){
10525 case TKIND_COCLASS: {
10526 if (index == -1) {
10527 FIXME("Unhandled index: -1\n");
10528 return E_NOTIMPL;
10531 if(index != This->typeattr.cImplTypes)
10532 return TYPE_E_ELEMENTNOTFOUND;
10534 break;
10536 case TKIND_INTERFACE:
10537 case TKIND_DISPATCH:
10538 if (index != 0 || This->typeattr.cImplTypes)
10539 return TYPE_E_ELEMENTNOTFOUND;
10540 break;
10541 default:
10542 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10543 return E_NOTIMPL;
10546 if (This->impltypes){
10547 UINT i;
10549 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10550 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10552 if (index < This->typeattr.cImplTypes) {
10553 memmove(This->impltypes + index + 1, This->impltypes + index,
10554 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10555 impl_type = This->impltypes + index;
10556 } else
10557 impl_type = This->impltypes + This->typeattr.cImplTypes;
10559 /* move custdata lists to the new memory location */
10560 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10561 if(index != i){
10562 TLBImplType *it = &This->impltypes[i];
10563 if(it->custdata_list.prev == it->custdata_list.next)
10564 list_init(&it->custdata_list);
10565 else{
10566 it->custdata_list.prev->next = &it->custdata_list;
10567 it->custdata_list.next->prev = &it->custdata_list;
10571 } else
10572 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10574 memset(impl_type, 0, sizeof(TLBImplType));
10575 TLBImplType_Constructor(impl_type);
10576 impl_type->hRef = refType;
10578 ++This->typeattr.cImplTypes;
10580 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10581 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10583 hres = ICreateTypeInfo2_LayOut(iface);
10584 if (FAILED(hres))
10585 return hres;
10587 return S_OK;
10590 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10591 UINT index, INT implTypeFlags)
10593 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10594 TLBImplType *impl_type = &This->impltypes[index];
10596 TRACE("%p %u %x\n", This, index, implTypeFlags);
10598 if (This->typeattr.typekind != TKIND_COCLASS)
10599 return TYPE_E_BADMODULEKIND;
10601 if (index >= This->typeattr.cImplTypes)
10602 return TYPE_E_ELEMENTNOTFOUND;
10604 impl_type->implflags = implTypeFlags;
10606 return S_OK;
10609 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10610 WORD alignment)
10612 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10614 TRACE("%p %d\n", This, alignment);
10616 This->typeattr.cbAlignment = alignment;
10618 return S_OK;
10621 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10622 LPOLESTR schema)
10624 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10626 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10628 if (!schema)
10629 return E_INVALIDARG;
10631 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10633 This->typeattr.lpstrSchema = This->Schema->str;
10635 return S_OK;
10638 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10639 UINT index, VARDESC *varDesc)
10641 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10642 TLBVarDesc *var_desc;
10644 TRACE("%p %u %p\n", This, index, varDesc);
10646 if (This->vardescs){
10647 UINT i;
10649 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10650 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10652 if (index < This->typeattr.cVars) {
10653 memmove(This->vardescs + index + 1, This->vardescs + index,
10654 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10655 var_desc = This->vardescs + index;
10656 } else
10657 var_desc = This->vardescs + This->typeattr.cVars;
10659 /* move custdata lists to the new memory location */
10660 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10661 if(index != i){
10662 TLBVarDesc *var = &This->vardescs[i];
10663 if(var->custdata_list.prev == var->custdata_list.next)
10664 list_init(&var->custdata_list);
10665 else{
10666 var->custdata_list.prev->next = &var->custdata_list;
10667 var->custdata_list.next->prev = &var->custdata_list;
10671 } else
10672 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10674 TLBVarDesc_Constructor(var_desc);
10675 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10676 var_desc->vardesc = *var_desc->vardesc_create;
10678 ++This->typeattr.cVars;
10680 This->needs_layout = TRUE;
10682 return S_OK;
10685 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10686 UINT index, LPOLESTR *names, UINT numNames)
10688 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10689 TLBFuncDesc *func_desc = &This->funcdescs[index];
10690 int i;
10692 TRACE("%p %u %p %u\n", This, index, names, numNames);
10694 if (!names)
10695 return E_INVALIDARG;
10697 if (index >= This->typeattr.cFuncs || numNames == 0)
10698 return TYPE_E_ELEMENTNOTFOUND;
10700 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10701 if(numNames > func_desc->funcdesc.cParams)
10702 return TYPE_E_ELEMENTNOTFOUND;
10703 } else
10704 if(numNames > func_desc->funcdesc.cParams + 1)
10705 return TYPE_E_ELEMENTNOTFOUND;
10707 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10708 TLBFuncDesc *iter = &This->funcdescs[i];
10709 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10710 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10711 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10712 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10713 continue;
10714 return TYPE_E_AMBIGUOUSNAME;
10718 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10720 for (i = 1; i < numNames; ++i) {
10721 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10722 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10725 return S_OK;
10728 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10729 UINT index, LPOLESTR name)
10731 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10733 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10735 if(!name)
10736 return E_INVALIDARG;
10738 if(index >= This->typeattr.cVars)
10739 return TYPE_E_ELEMENTNOTFOUND;
10741 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10742 return S_OK;
10745 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10746 TYPEDESC *tdescAlias)
10748 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10749 HRESULT hr;
10751 TRACE("%p %p\n", This, tdescAlias);
10753 if(!tdescAlias)
10754 return E_INVALIDARG;
10756 if(This->typeattr.typekind != TKIND_ALIAS)
10757 return TYPE_E_BADMODULEKIND;
10759 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
10760 if(FAILED(hr))
10761 return hr;
10763 heap_free(This->tdescAlias);
10764 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10765 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10767 return S_OK;
10770 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10771 UINT index, LPOLESTR dllName, LPOLESTR procName)
10773 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10774 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10775 return E_NOTIMPL;
10778 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10779 UINT index, LPOLESTR docString)
10781 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10782 TLBFuncDesc *func_desc = &This->funcdescs[index];
10784 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10786 if(!docString)
10787 return E_INVALIDARG;
10789 if(index >= This->typeattr.cFuncs)
10790 return TYPE_E_ELEMENTNOTFOUND;
10792 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10794 return S_OK;
10797 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10798 UINT index, LPOLESTR docString)
10800 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10801 TLBVarDesc *var_desc = &This->vardescs[index];
10803 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10805 if(!docString)
10806 return E_INVALIDARG;
10808 if(index >= This->typeattr.cVars)
10809 return TYPE_E_ELEMENTNOTFOUND;
10811 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10813 return S_OK;
10816 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10817 UINT index, DWORD helpContext)
10819 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10820 TLBFuncDesc *func_desc = &This->funcdescs[index];
10822 TRACE("%p %u %d\n", This, index, helpContext);
10824 if(index >= This->typeattr.cFuncs)
10825 return TYPE_E_ELEMENTNOTFOUND;
10827 func_desc->helpcontext = helpContext;
10829 return S_OK;
10832 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10833 UINT index, DWORD helpContext)
10835 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10836 TLBVarDesc *var_desc = &This->vardescs[index];
10838 TRACE("%p %u %d\n", This, index, helpContext);
10840 if(index >= This->typeattr.cVars)
10841 return TYPE_E_ELEMENTNOTFOUND;
10843 var_desc->HelpContext = helpContext;
10845 return S_OK;
10848 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10849 UINT index, BSTR bstrMops)
10851 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10852 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10853 return E_NOTIMPL;
10856 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10857 IDLDESC *idlDesc)
10859 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10861 TRACE("%p %p\n", This, idlDesc);
10863 if (!idlDesc)
10864 return E_INVALIDARG;
10866 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
10867 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
10869 return S_OK;
10872 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10874 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10875 ITypeInfo *tinfo;
10876 TLBFuncDesc *func_desc;
10877 UINT user_vft = 0, i, depth = 0;
10878 HRESULT hres = S_OK;
10880 TRACE("%p\n", This);
10882 This->needs_layout = FALSE;
10884 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10885 if (FAILED(hres))
10886 return hres;
10888 if (This->typeattr.typekind == TKIND_INTERFACE) {
10889 ITypeInfo *inh;
10890 TYPEATTR *attr;
10891 HREFTYPE inh_href;
10893 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10895 if (SUCCEEDED(hres)) {
10896 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10898 if (SUCCEEDED(hres)) {
10899 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10900 if (FAILED(hres)) {
10901 ITypeInfo_Release(inh);
10902 ITypeInfo_Release(tinfo);
10903 return hres;
10905 This->typeattr.cbSizeVft = attr->cbSizeVft;
10906 ITypeInfo_ReleaseTypeAttr(inh, attr);
10909 ++depth;
10910 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10911 if(SUCCEEDED(hres)){
10912 ITypeInfo *next;
10913 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10914 if(SUCCEEDED(hres)){
10915 ITypeInfo_Release(inh);
10916 inh = next;
10919 }while(SUCCEEDED(hres));
10920 hres = S_OK;
10922 ITypeInfo_Release(inh);
10923 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10924 This->typeattr.cbSizeVft = 0;
10925 hres = S_OK;
10926 } else {
10927 ITypeInfo_Release(tinfo);
10928 return hres;
10930 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10931 This->typeattr.cbSizeVft = 0;
10932 hres = S_OK;
10933 } else {
10934 ITypeInfo_Release(tinfo);
10935 return hres;
10937 } else if (This->typeattr.typekind == TKIND_DISPATCH)
10938 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
10939 else
10940 This->typeattr.cbSizeVft = 0;
10942 func_desc = This->funcdescs;
10943 i = 0;
10944 while (i < This->typeattr.cFuncs) {
10945 if (!(func_desc->funcdesc.oVft & 0x1))
10946 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
10948 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10949 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10951 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
10953 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10954 TLBFuncDesc *iter;
10955 UINT j = 0;
10956 BOOL reset = FALSE;
10958 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10960 iter = This->funcdescs;
10961 while (j < This->typeattr.cFuncs) {
10962 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10963 if (!reset) {
10964 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
10965 reset = TRUE;
10966 } else
10967 ++func_desc->funcdesc.memid;
10968 iter = This->funcdescs;
10969 j = 0;
10970 } else {
10971 ++iter;
10972 ++j;
10977 ++func_desc;
10978 ++i;
10981 if (user_vft > This->typeattr.cbSizeVft)
10982 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10984 for(i = 0; i < This->typeattr.cVars; ++i){
10985 TLBVarDesc *var_desc = &This->vardescs[i];
10986 if(var_desc->vardesc.memid == MEMBERID_NIL){
10987 UINT j = 0;
10988 BOOL reset = FALSE;
10989 TLBVarDesc *iter;
10991 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
10993 iter = This->vardescs;
10994 while (j < This->typeattr.cVars) {
10995 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
10996 if (!reset) {
10997 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
10998 reset = TRUE;
10999 } else
11000 ++var_desc->vardesc.memid;
11001 iter = This->vardescs;
11002 j = 0;
11003 } else {
11004 ++iter;
11005 ++j;
11011 ITypeInfo_Release(tinfo);
11012 return hres;
11015 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11016 UINT index)
11018 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11019 FIXME("%p %u - stub\n", This, index);
11020 return E_NOTIMPL;
11023 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11024 MEMBERID memid, INVOKEKIND invKind)
11026 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11027 FIXME("%p %x %d - stub\n", This, memid, invKind);
11028 return E_NOTIMPL;
11031 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11032 UINT index)
11034 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11035 FIXME("%p %u - stub\n", This, index);
11036 return E_NOTIMPL;
11039 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11040 MEMBERID memid)
11042 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11043 FIXME("%p %x - stub\n", This, memid);
11044 return E_NOTIMPL;
11047 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11048 UINT index)
11050 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11051 FIXME("%p %u - stub\n", This, index);
11052 return E_NOTIMPL;
11055 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11056 REFGUID guid, VARIANT *varVal)
11058 TLBGuid *tlbguid;
11060 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11062 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11064 if (!guid || !varVal)
11065 return E_INVALIDARG;
11067 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11069 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11072 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11073 UINT index, REFGUID guid, VARIANT *varVal)
11075 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11076 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11077 return E_NOTIMPL;
11080 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11081 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11083 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11084 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11085 return E_NOTIMPL;
11088 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11089 UINT index, REFGUID guid, VARIANT *varVal)
11091 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11092 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11093 return E_NOTIMPL;
11096 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11097 UINT index, REFGUID guid, VARIANT *varVal)
11099 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11100 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11101 return E_NOTIMPL;
11104 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11105 ULONG helpStringContext)
11107 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11109 TRACE("%p %u\n", This, helpStringContext);
11111 This->dwHelpStringContext = helpStringContext;
11113 return S_OK;
11116 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11117 UINT index, ULONG helpStringContext)
11119 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11120 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11121 return E_NOTIMPL;
11124 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11125 UINT index, ULONG helpStringContext)
11127 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11128 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11129 return E_NOTIMPL;
11132 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11134 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11135 FIXME("%p - stub\n", This);
11136 return E_NOTIMPL;
11139 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11140 LPOLESTR name)
11142 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11144 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11146 if (!name)
11147 return E_INVALIDARG;
11149 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11151 return S_OK;
11154 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11155 ICreateTypeInfo2_fnQueryInterface,
11156 ICreateTypeInfo2_fnAddRef,
11157 ICreateTypeInfo2_fnRelease,
11158 ICreateTypeInfo2_fnSetGuid,
11159 ICreateTypeInfo2_fnSetTypeFlags,
11160 ICreateTypeInfo2_fnSetDocString,
11161 ICreateTypeInfo2_fnSetHelpContext,
11162 ICreateTypeInfo2_fnSetVersion,
11163 ICreateTypeInfo2_fnAddRefTypeInfo,
11164 ICreateTypeInfo2_fnAddFuncDesc,
11165 ICreateTypeInfo2_fnAddImplType,
11166 ICreateTypeInfo2_fnSetImplTypeFlags,
11167 ICreateTypeInfo2_fnSetAlignment,
11168 ICreateTypeInfo2_fnSetSchema,
11169 ICreateTypeInfo2_fnAddVarDesc,
11170 ICreateTypeInfo2_fnSetFuncAndParamNames,
11171 ICreateTypeInfo2_fnSetVarName,
11172 ICreateTypeInfo2_fnSetTypeDescAlias,
11173 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11174 ICreateTypeInfo2_fnSetFuncDocString,
11175 ICreateTypeInfo2_fnSetVarDocString,
11176 ICreateTypeInfo2_fnSetFuncHelpContext,
11177 ICreateTypeInfo2_fnSetVarHelpContext,
11178 ICreateTypeInfo2_fnSetMops,
11179 ICreateTypeInfo2_fnSetTypeIdldesc,
11180 ICreateTypeInfo2_fnLayOut,
11181 ICreateTypeInfo2_fnDeleteFuncDesc,
11182 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11183 ICreateTypeInfo2_fnDeleteVarDesc,
11184 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11185 ICreateTypeInfo2_fnDeleteImplType,
11186 ICreateTypeInfo2_fnSetCustData,
11187 ICreateTypeInfo2_fnSetFuncCustData,
11188 ICreateTypeInfo2_fnSetParamCustData,
11189 ICreateTypeInfo2_fnSetVarCustData,
11190 ICreateTypeInfo2_fnSetImplTypeCustData,
11191 ICreateTypeInfo2_fnSetHelpStringContext,
11192 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11193 ICreateTypeInfo2_fnSetVarHelpStringContext,
11194 ICreateTypeInfo2_fnInvalidate,
11195 ICreateTypeInfo2_fnSetName
11198 /******************************************************************************
11199 * ClearCustData (OLEAUT32.171)
11201 * Clear a custom data type's data.
11203 * PARAMS
11204 * lpCust [I] The custom data type instance
11206 * RETURNS
11207 * Nothing.
11209 void WINAPI ClearCustData(CUSTDATA *lpCust)
11211 if (lpCust && lpCust->cCustData)
11213 if (lpCust->prgCustData)
11215 DWORD i;
11217 for (i = 0; i < lpCust->cCustData; i++)
11218 VariantClear(&lpCust->prgCustData[i].varValue);
11220 CoTaskMemFree(lpCust->prgCustData);
11221 lpCust->prgCustData = NULL;
11223 lpCust->cCustData = 0;