wined3d: Pass a texture and sub-resource index to wined3d_volume_download_data().
[wine.git] / dlls / oleaut32 / typelib.c
blob517e515af7b960da85766597d90f8de4cf42328d
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 LCID lcid;
1237 MEMBERID memidConstructor;
1238 MEMBERID memidDestructor;
1239 LPOLESTR lpstrSchema;
1240 ULONG cbSizeInstance;
1241 TYPEKIND typekind;
1242 WORD cFuncs;
1243 WORD cVars;
1244 WORD cImplTypes;
1245 WORD cbSizeVft;
1246 WORD cbAlignment;
1247 WORD wTypeFlags;
1248 WORD wMajorVerNum;
1249 WORD wMinorVerNum;
1250 TYPEDESC *tdescAlias;
1251 IDLDESC idldescType;
1253 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1254 int index; /* index in this typelib; */
1255 HREFTYPE hreftype; /* hreftype for app object binding */
1256 /* type libs seem to store the doc strings in ascii
1257 * so why should we do it in unicode?
1259 const TLBString *Name;
1260 const TLBString *DocString;
1261 const TLBString *DllName;
1262 const TLBString *Schema;
1263 DWORD dwHelpContext;
1264 DWORD dwHelpStringContext;
1266 /* functions */
1267 TLBFuncDesc *funcdescs;
1269 /* variables */
1270 TLBVarDesc *vardescs;
1272 /* Implemented Interfaces */
1273 TLBImplType *impltypes;
1275 struct list *pcustdata_list;
1276 struct list custdata_list;
1277 } ITypeInfoImpl;
1279 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1281 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1284 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1286 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1289 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1291 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1294 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1296 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1299 static const ITypeInfo2Vtbl tinfvt;
1300 static const ITypeCompVtbl tcompvt;
1301 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1303 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1304 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1306 typedef struct tagTLBContext
1308 unsigned int oStart; /* start of TLB in file */
1309 unsigned int pos; /* current pos */
1310 unsigned int length; /* total length */
1311 void *mapping; /* memory mapping */
1312 MSFT_SegDir * pTblDir;
1313 ITypeLibImpl* pLibInfo;
1314 } TLBContext;
1317 static inline BSTR TLB_get_bstr(const TLBString *str)
1319 return str != NULL ? str->str : NULL;
1322 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1324 if(!str)
1325 return 1;
1326 return memcmp(left, str->str, len);
1329 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1331 return guid != NULL ? &guid->guid : NULL;
1334 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1336 return guid != NULL ? &guid->guid : &GUID_NULL;
1339 static int get_ptr_size(SYSKIND syskind)
1341 switch(syskind){
1342 case SYS_WIN64:
1343 return 8;
1344 case SYS_WIN32:
1345 case SYS_MAC:
1346 case SYS_WIN16:
1347 return 4;
1349 WARN("Unhandled syskind: 0x%x\n", syskind);
1350 return 4;
1354 debug
1356 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1357 if (pTD->vt & VT_RESERVED)
1358 szVarType += strlen(strcpy(szVarType, "reserved | "));
1359 if (pTD->vt & VT_BYREF)
1360 szVarType += strlen(strcpy(szVarType, "ref to "));
1361 if (pTD->vt & VT_ARRAY)
1362 szVarType += strlen(strcpy(szVarType, "array of "));
1363 if (pTD->vt & VT_VECTOR)
1364 szVarType += strlen(strcpy(szVarType, "vector of "));
1365 switch(pTD->vt & VT_TYPEMASK) {
1366 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1367 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1368 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1369 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1370 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1371 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1372 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1373 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1374 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1375 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1376 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1377 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1378 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1379 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1380 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1381 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1382 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1383 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1384 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1385 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1386 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1387 pTD->u.hreftype); break;
1388 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1389 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1390 case VT_PTR: sprintf(szVarType, "ptr to ");
1391 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1392 break;
1393 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1394 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1395 break;
1396 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1397 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1398 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1399 break;
1401 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1405 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1406 char buf[200];
1407 USHORT flags = edesc->u.paramdesc.wParamFlags;
1408 dump_TypeDesc(&edesc->tdesc,buf);
1409 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1410 MESSAGE("\t\tu.paramdesc.wParamFlags");
1411 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1412 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1413 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1414 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1415 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1416 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1417 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1418 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1419 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1421 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1422 int i;
1423 MESSAGE("memid is %08x\n",funcdesc->memid);
1424 for (i=0;i<funcdesc->cParams;i++) {
1425 MESSAGE("Param %d:\n",i);
1426 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1428 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1429 switch (funcdesc->funckind) {
1430 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1431 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1432 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1433 case FUNC_STATIC: MESSAGE("static");break;
1434 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1435 default: MESSAGE("unknown");break;
1437 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1438 switch (funcdesc->invkind) {
1439 case INVOKE_FUNC: MESSAGE("func");break;
1440 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1441 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1442 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1444 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1445 switch (funcdesc->callconv) {
1446 case CC_CDECL: MESSAGE("cdecl");break;
1447 case CC_PASCAL: MESSAGE("pascal");break;
1448 case CC_STDCALL: MESSAGE("stdcall");break;
1449 case CC_SYSCALL: MESSAGE("syscall");break;
1450 default:break;
1452 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1453 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1454 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1456 MESSAGE("\telemdescFunc (return value type):\n");
1457 dump_ELEMDESC(&funcdesc->elemdescFunc);
1460 static const char * const typekind_desc[] =
1462 "TKIND_ENUM",
1463 "TKIND_RECORD",
1464 "TKIND_MODULE",
1465 "TKIND_INTERFACE",
1466 "TKIND_DISPATCH",
1467 "TKIND_COCLASS",
1468 "TKIND_ALIAS",
1469 "TKIND_UNION",
1470 "TKIND_MAX"
1473 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1475 int i;
1476 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1477 for (i=0;i<pfd->funcdesc.cParams;i++)
1478 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1481 dump_FUNCDESC(&(pfd->funcdesc));
1483 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1484 if(pfd->Entry == NULL)
1485 MESSAGE("\tentry: (null)\n");
1486 else if(pfd->Entry == (void*)-1)
1487 MESSAGE("\tentry: invalid\n");
1488 else if(IS_INTRESOURCE(pfd->Entry))
1489 MESSAGE("\tentry: %p\n", pfd->Entry);
1490 else
1491 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1493 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1495 while (n)
1497 dump_TLBFuncDescOne(pfd);
1498 ++pfd;
1499 --n;
1502 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1504 while (n)
1506 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1507 ++pvd;
1508 --n;
1512 static void dump_TLBImpLib(const TLBImpLib *import)
1514 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1515 debugstr_w(import->name));
1516 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1517 import->wVersionMinor, import->lcid, import->offset);
1520 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1522 TLBRefType *ref;
1524 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1526 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1527 if(ref->index == -1)
1528 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1529 else
1530 TRACE_(typelib)("type no: %d\n", ref->index);
1532 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1534 TRACE_(typelib)("in lib\n");
1535 dump_TLBImpLib(ref->pImpTLInfo);
1540 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1542 if(!impl)
1543 return;
1544 while (n) {
1545 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1546 impl->hRef, impl->implflags);
1547 ++impl;
1548 --n;
1552 static void dump_DispParms(const DISPPARAMS * pdp)
1554 unsigned int index;
1556 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1558 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1560 TRACE("named args:\n");
1561 for (index = 0; index < pdp->cNamedArgs; index++)
1562 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1565 if (pdp->cArgs && pdp->rgvarg)
1567 TRACE("args:\n");
1568 for (index = 0; index < pdp->cArgs; index++)
1569 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1573 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1575 TRACE("%p ref=%u\n", pty, pty->ref);
1576 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1577 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1578 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1579 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1580 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1581 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1582 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1583 if (TRACE_ON(ole))
1584 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1585 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1586 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1589 static void dump_VARDESC(const VARDESC *v)
1591 MESSAGE("memid %d\n",v->memid);
1592 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1593 MESSAGE("oInst %d\n",v->u.oInst);
1594 dump_ELEMDESC(&(v->elemdescVar));
1595 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1596 MESSAGE("varkind %d\n",v->varkind);
1599 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1601 /* VT_LPWSTR is largest type that, may appear in type description */
1602 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1603 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1604 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1605 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1606 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1607 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1608 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1609 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1612 static void TLB_abort(void)
1614 DebugBreak();
1617 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1619 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1620 if (!ret) ERR("cannot allocate memory\n");
1621 return ret;
1624 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1626 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1627 if (!ret) ERR("cannot allocate memory\n");
1628 return ret;
1631 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1633 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1636 void heap_free(void *ptr)
1638 HeapFree(GetProcessHeap(), 0, ptr);
1641 /* returns the size required for a deep copy of a typedesc into a
1642 * flat buffer */
1643 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1645 SIZE_T size = 0;
1647 if (alloc_initial_space)
1648 size += sizeof(TYPEDESC);
1650 switch (tdesc->vt)
1652 case VT_PTR:
1653 case VT_SAFEARRAY:
1654 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1655 break;
1656 case VT_CARRAY:
1657 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1658 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1659 break;
1661 return size;
1664 /* deep copy a typedesc into a flat buffer */
1665 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1667 if (!dest)
1669 dest = buffer;
1670 buffer = (char *)buffer + sizeof(TYPEDESC);
1673 *dest = *src;
1675 switch (src->vt)
1677 case VT_PTR:
1678 case VT_SAFEARRAY:
1679 dest->u.lptdesc = buffer;
1680 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1681 break;
1682 case VT_CARRAY:
1683 dest->u.lpadesc = buffer;
1684 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1685 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1686 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1687 break;
1689 return buffer;
1692 /* free custom data allocated by MSFT_CustData */
1693 static inline void TLB_FreeCustData(struct list *custdata_list)
1695 TLBCustData *cd, *cdn;
1696 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1698 list_remove(&cd->entry);
1699 VariantClear(&cd->data);
1700 heap_free(cd);
1704 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1706 DWORD len;
1707 BSTR ret;
1709 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1710 ret = SysAllocStringLen(NULL, len - 1);
1711 if (!ret) return ret;
1712 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1713 return ret;
1716 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1717 UINT n, MEMBERID memid)
1719 while(n){
1720 if(funcdescs->funcdesc.memid == memid)
1721 return funcdescs;
1722 ++funcdescs;
1723 --n;
1725 return NULL;
1728 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1729 UINT n, MEMBERID memid)
1731 while(n){
1732 if(vardescs->vardesc.memid == memid)
1733 return vardescs;
1734 ++vardescs;
1735 --n;
1737 return NULL;
1740 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1741 UINT n, const OLECHAR *name)
1743 while(n){
1744 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1745 return vardescs;
1746 ++vardescs;
1747 --n;
1749 return NULL;
1752 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1754 TLBCustData *cust_data;
1755 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1756 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1757 return cust_data;
1758 return NULL;
1761 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1762 UINT n, const OLECHAR *name)
1764 while(n){
1765 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1766 return *typeinfos;
1767 ++typeinfos;
1768 --n;
1770 return NULL;
1773 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1775 list_init(&var_desc->custdata_list);
1778 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1780 TLBVarDesc *ret;
1782 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1783 if(!ret)
1784 return NULL;
1786 while(n){
1787 TLBVarDesc_Constructor(&ret[n-1]);
1788 --n;
1791 return ret;
1794 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1796 TLBParDesc *ret;
1798 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1799 if(!ret)
1800 return NULL;
1802 while(n){
1803 list_init(&ret[n-1].custdata_list);
1804 --n;
1807 return ret;
1810 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1812 list_init(&func_desc->custdata_list);
1815 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1817 TLBFuncDesc *ret;
1819 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1820 if(!ret)
1821 return NULL;
1823 while(n){
1824 TLBFuncDesc_Constructor(&ret[n-1]);
1825 --n;
1828 return ret;
1831 static void TLBImplType_Constructor(TLBImplType *impl)
1833 list_init(&impl->custdata_list);
1836 static TLBImplType *TLBImplType_Alloc(UINT n)
1838 TLBImplType *ret;
1840 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1841 if(!ret)
1842 return NULL;
1844 while(n){
1845 TLBImplType_Constructor(&ret[n-1]);
1846 --n;
1849 return ret;
1852 static TLBGuid *TLB_append_guid(struct list *guid_list,
1853 const GUID *new_guid, HREFTYPE hreftype)
1855 TLBGuid *guid;
1857 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1858 if (IsEqualGUID(&guid->guid, new_guid))
1859 return guid;
1862 guid = heap_alloc(sizeof(TLBGuid));
1863 if (!guid)
1864 return NULL;
1866 memcpy(&guid->guid, new_guid, sizeof(GUID));
1867 guid->hreftype = hreftype;
1869 list_add_tail(guid_list, &guid->entry);
1871 return guid;
1874 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1876 TLBCustData *cust_data;
1878 switch(V_VT(var)){
1879 case VT_I4:
1880 case VT_R4:
1881 case VT_UI4:
1882 case VT_INT:
1883 case VT_UINT:
1884 case VT_HRESULT:
1885 case VT_BSTR:
1886 break;
1887 default:
1888 return DISP_E_BADVARTYPE;
1891 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1893 if (!cust_data) {
1894 cust_data = heap_alloc(sizeof(TLBCustData));
1895 if (!cust_data)
1896 return E_OUTOFMEMORY;
1898 cust_data->guid = tlbguid;
1899 VariantInit(&cust_data->data);
1901 list_add_tail(custdata_list, &cust_data->entry);
1902 }else
1903 VariantClear(&cust_data->data);
1905 return VariantCopy(&cust_data->data, var);
1908 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1910 TLBString *str;
1912 if(!new_str)
1913 return NULL;
1915 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1916 if (strcmpW(str->str, new_str) == 0)
1917 return str;
1920 str = heap_alloc(sizeof(TLBString));
1921 if (!str)
1922 return NULL;
1924 str->str = SysAllocString(new_str);
1925 if (!str->str) {
1926 heap_free(str);
1927 return NULL;
1930 list_add_tail(string_list, &str->entry);
1932 return str;
1935 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1936 ULONG *size, WORD *align)
1938 ITypeInfo *other;
1939 TYPEATTR *attr;
1940 HRESULT hr;
1942 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1943 if(FAILED(hr))
1944 return hr;
1946 hr = ITypeInfo_GetTypeAttr(other, &attr);
1947 if(FAILED(hr)){
1948 ITypeInfo_Release(other);
1949 return hr;
1952 if(size)
1953 *size = attr->cbSizeInstance;
1954 if(align)
1955 *align = attr->cbAlignment;
1957 ITypeInfo_ReleaseTypeAttr(other, attr);
1958 ITypeInfo_Release(other);
1960 return S_OK;
1963 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1964 TYPEDESC *tdesc, ULONG *size, WORD *align)
1966 ULONG i, sub, ptr_size;
1967 HRESULT hr;
1969 ptr_size = get_ptr_size(sys);
1971 switch(tdesc->vt){
1972 case VT_VOID:
1973 *size = 0;
1974 break;
1975 case VT_I1:
1976 case VT_UI1:
1977 *size = 1;
1978 break;
1979 case VT_I2:
1980 case VT_BOOL:
1981 case VT_UI2:
1982 *size = 2;
1983 break;
1984 case VT_I4:
1985 case VT_R4:
1986 case VT_ERROR:
1987 case VT_UI4:
1988 case VT_INT:
1989 case VT_UINT:
1990 case VT_HRESULT:
1991 *size = 4;
1992 break;
1993 case VT_R8:
1994 case VT_I8:
1995 case VT_UI8:
1996 *size = 8;
1997 break;
1998 case VT_BSTR:
1999 case VT_DISPATCH:
2000 case VT_UNKNOWN:
2001 case VT_PTR:
2002 case VT_SAFEARRAY:
2003 case VT_LPSTR:
2004 case VT_LPWSTR:
2005 *size = ptr_size;
2006 break;
2007 case VT_DATE:
2008 *size = sizeof(DATE);
2009 break;
2010 case VT_VARIANT:
2011 *size = sizeof(VARIANT);
2012 #ifdef _WIN64
2013 if(sys == SYS_WIN32)
2014 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2015 #endif
2016 break;
2017 case VT_DECIMAL:
2018 *size = sizeof(DECIMAL);
2019 break;
2020 case VT_CY:
2021 *size = sizeof(CY);
2022 break;
2023 case VT_CARRAY:
2024 *size = 0;
2025 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2026 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2027 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2028 if(FAILED(hr))
2029 return hr;
2030 *size *= sub;
2031 return S_OK;
2032 case VT_USERDEFINED:
2033 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2034 default:
2035 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2036 return E_FAIL;
2039 if(align){
2040 if(*size < 4)
2041 *align = *size;
2042 else
2043 *align = 4;
2046 return S_OK;
2049 /**********************************************************************
2051 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2054 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2056 if (where != DO_NOT_SEEK)
2058 where += pcx->oStart;
2059 if (where > pcx->length)
2061 /* FIXME */
2062 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2063 TLB_abort();
2065 pcx->pos = where;
2069 /* read function */
2070 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2072 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2073 pcx->pos, count, pcx->oStart, pcx->length, where);
2075 MSFT_Seek(pcx, where);
2076 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2077 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2078 pcx->pos += count;
2079 return count;
2082 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2083 LONG where )
2085 DWORD ret;
2087 ret = MSFT_Read(buffer, count, pcx, where);
2088 FromLEDWords(buffer, ret);
2090 return ret;
2093 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2094 LONG where )
2096 DWORD ret;
2098 ret = MSFT_Read(buffer, count, pcx, where);
2099 FromLEWords(buffer, ret);
2101 return ret;
2104 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2106 TLBGuid *guid;
2107 MSFT_GuidEntry entry;
2108 int offs = 0;
2110 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2111 while (1) {
2112 if (offs >= pcx->pTblDir->pGuidTab.length)
2113 return S_OK;
2115 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2117 guid = heap_alloc(sizeof(TLBGuid));
2119 guid->offset = offs;
2120 guid->guid = entry.guid;
2121 guid->hreftype = entry.hreftype;
2123 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2125 offs += sizeof(MSFT_GuidEntry);
2129 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2131 TLBGuid *ret;
2133 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2134 if(ret->offset == offset){
2135 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2136 return ret;
2140 return NULL;
2143 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2145 MSFT_NameIntro niName;
2147 if (offset < 0)
2149 ERR_(typelib)("bad offset %d\n", offset);
2150 return -1;
2153 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2154 pcx->pTblDir->pNametab.offset+offset);
2156 return niName.hreftype;
2159 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2161 char *string;
2162 MSFT_NameIntro intro;
2163 INT16 len_piece;
2164 int offs = 0, lengthInChars;
2166 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2167 while (1) {
2168 TLBString *tlbstr;
2170 if (offs >= pcx->pTblDir->pNametab.length)
2171 return S_OK;
2173 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2174 intro.namelen &= 0xFF;
2175 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2176 if(len_piece % 4)
2177 len_piece = (len_piece + 4) & ~0x3;
2178 if(len_piece < 8)
2179 len_piece = 8;
2181 string = heap_alloc(len_piece + 1);
2182 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2183 string[intro.namelen] = '\0';
2185 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2186 string, -1, NULL, 0);
2187 if (!lengthInChars) {
2188 heap_free(string);
2189 return E_UNEXPECTED;
2192 tlbstr = heap_alloc(sizeof(TLBString));
2194 tlbstr->offset = offs;
2195 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2196 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2198 heap_free(string);
2200 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2202 offs += len_piece;
2206 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2208 TLBString *tlbstr;
2210 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2211 if (tlbstr->offset == offset) {
2212 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2213 return tlbstr;
2217 return NULL;
2220 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2222 TLBString *tlbstr;
2224 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2225 if (tlbstr->offset == offset) {
2226 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2227 return tlbstr;
2231 return NULL;
2235 * read a value and fill a VARIANT structure
2237 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2239 int size;
2241 TRACE_(typelib)("\n");
2243 if(offset <0) { /* data are packed in here */
2244 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2245 V_I4(pVar) = offset & 0x3ffffff;
2246 return;
2248 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2249 pcx->pTblDir->pCustData.offset + offset );
2250 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2251 switch (V_VT(pVar)){
2252 case VT_EMPTY: /* FIXME: is this right? */
2253 case VT_NULL: /* FIXME: is this right? */
2254 case VT_I2 : /* this should not happen */
2255 case VT_I4 :
2256 case VT_R4 :
2257 case VT_ERROR :
2258 case VT_BOOL :
2259 case VT_I1 :
2260 case VT_UI1 :
2261 case VT_UI2 :
2262 case VT_UI4 :
2263 case VT_INT :
2264 case VT_UINT :
2265 case VT_VOID : /* FIXME: is this right? */
2266 case VT_HRESULT :
2267 size=4; break;
2268 case VT_R8 :
2269 case VT_CY :
2270 case VT_DATE :
2271 case VT_I8 :
2272 case VT_UI8 :
2273 case VT_DECIMAL : /* FIXME: is this right? */
2274 case VT_FILETIME :
2275 size=8;break;
2276 /* pointer types with known behaviour */
2277 case VT_BSTR :{
2278 char * ptr;
2279 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2280 if(size == -1){
2281 V_BSTR(pVar) = NULL;
2282 }else{
2283 ptr = heap_alloc_zero(size);
2284 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2285 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2286 /* FIXME: do we need a AtoW conversion here? */
2287 V_UNION(pVar, bstrVal[size])='\0';
2288 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2289 heap_free(ptr);
2292 size=-4; break;
2293 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2294 case VT_DISPATCH :
2295 case VT_VARIANT :
2296 case VT_UNKNOWN :
2297 case VT_PTR :
2298 case VT_SAFEARRAY :
2299 case VT_CARRAY :
2300 case VT_USERDEFINED :
2301 case VT_LPSTR :
2302 case VT_LPWSTR :
2303 case VT_BLOB :
2304 case VT_STREAM :
2305 case VT_STORAGE :
2306 case VT_STREAMED_OBJECT :
2307 case VT_STORED_OBJECT :
2308 case VT_BLOB_OBJECT :
2309 case VT_CF :
2310 case VT_CLSID :
2311 default:
2312 size=0;
2313 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2314 V_VT(pVar));
2317 if(size>0) /* (big|small) endian correct? */
2318 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2319 return;
2322 * create a linked list with custom data
2324 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2326 MSFT_CDGuid entry;
2327 TLBCustData* pNew;
2328 int count=0;
2330 TRACE_(typelib)("\n");
2332 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2334 while(offset >=0){
2335 count++;
2336 pNew=heap_alloc_zero(sizeof(TLBCustData));
2337 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2338 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2339 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2340 list_add_head(custdata_list, &pNew->entry);
2341 offset = entry.next;
2343 return count;
2346 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2348 if(type <0)
2349 pTd->vt=type & VT_TYPEMASK;
2350 else
2351 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2353 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2356 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2358 return (invkind == INVOKE_PROPERTYGET ||
2359 invkind == INVOKE_PROPERTYPUT ||
2360 invkind == INVOKE_PROPERTYPUTREF);
2363 static void
2364 MSFT_DoFuncs(TLBContext* pcx,
2365 ITypeInfoImpl* pTI,
2366 int cFuncs,
2367 int cVars,
2368 int offset,
2369 TLBFuncDesc** pptfd)
2372 * member information is stored in a data structure at offset
2373 * indicated by the memoffset field of the typeinfo structure
2374 * There are several distinctive parts.
2375 * The first part starts with a field that holds the total length
2376 * of this (first) part excluding this field. Then follow the records,
2377 * for each member there is one record.
2379 * The first entry is always the length of the record (including this
2380 * length word).
2381 * The rest of the record depends on the type of the member. If there is
2382 * a field indicating the member type (function, variable, interface, etc)
2383 * I have not found it yet. At this time we depend on the information
2384 * in the type info and the usual order how things are stored.
2386 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2387 * for each member;
2389 * Third is an equal sized array with file offsets to the name entry
2390 * of each member.
2392 * The fourth and last (?) part is an array with offsets to the records
2393 * in the first part of this file segment.
2396 int infolen, nameoffset, reclength, i;
2397 int recoffset = offset + sizeof(INT);
2399 char *recbuf = heap_alloc(0xffff);
2400 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2401 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2403 TRACE_(typelib)("\n");
2405 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2407 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2408 ptfd = *pptfd;
2409 for ( i = 0; i < cFuncs ; i++ )
2411 int optional;
2413 /* name, eventually add to a hash table */
2414 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2415 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2417 /* read the function information record */
2418 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2420 reclength &= 0xffff;
2422 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2424 /* size without argument data */
2425 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2426 if (pFuncRec->FKCCIC & 0x1000)
2427 optional -= pFuncRec->nrargs * sizeof(INT);
2429 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2430 ptfd->helpcontext = pFuncRec->HelpContext;
2432 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2433 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2435 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2437 if (pFuncRec->FKCCIC & 0x2000 )
2439 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2440 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2441 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2443 else
2444 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2446 else
2447 ptfd->Entry = (TLBString*)-1;
2449 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2450 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2452 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2453 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2455 /* fill the FuncDesc Structure */
2456 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2457 offset + infolen + ( i + 1) * sizeof(INT));
2459 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2460 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2461 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2462 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2463 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2464 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2465 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2467 /* nameoffset is sometimes -1 on the second half of a propget/propput
2468 * pair of functions */
2469 if ((nameoffset == -1) && (i > 0) &&
2470 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2471 TLB_is_propgetput(ptfd->funcdesc.invkind))
2472 ptfd->Name = ptfd_prev->Name;
2473 else
2474 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2476 MSFT_GetTdesc(pcx,
2477 pFuncRec->DataType,
2478 &ptfd->funcdesc.elemdescFunc.tdesc);
2480 /* do the parameters/arguments */
2481 if(pFuncRec->nrargs)
2483 int j = 0;
2484 MSFT_ParameterInfo paraminfo;
2486 ptfd->funcdesc.lprgelemdescParam =
2487 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2489 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2491 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2492 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2494 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2496 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2498 MSFT_GetTdesc(pcx,
2499 paraminfo.DataType,
2500 &elemdesc->tdesc);
2502 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2504 /* name */
2505 if (paraminfo.oName != -1)
2506 ptfd->pParamDesc[j].Name =
2507 MSFT_ReadName( pcx, paraminfo.oName );
2508 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2510 /* default value */
2511 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2512 (pFuncRec->FKCCIC & 0x1000) )
2514 INT* pInt = (INT *)((char *)pFuncRec +
2515 reclength -
2516 (pFuncRec->nrargs * 4) * sizeof(INT) );
2518 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2520 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2521 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2523 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2524 pInt[j], pcx);
2526 else
2527 elemdesc->u.paramdesc.pparamdescex = NULL;
2529 /* custom info */
2530 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2531 j*sizeof(pFuncRec->oArgCustData[0])) &&
2532 pFuncRec->FKCCIC & 0x80 )
2534 MSFT_CustData(pcx,
2535 pFuncRec->oArgCustData[j],
2536 &ptfd->pParamDesc[j].custdata_list);
2539 /* SEEK value = jump to offset,
2540 * from there jump to the end of record,
2541 * go back by (j-1) arguments
2543 MSFT_ReadLEDWords( &paraminfo ,
2544 sizeof(MSFT_ParameterInfo), pcx,
2545 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2546 * sizeof(MSFT_ParameterInfo)));
2550 /* scode is not used: archaic win16 stuff FIXME: right? */
2551 ptfd->funcdesc.cScodes = 0 ;
2552 ptfd->funcdesc.lprgscode = NULL ;
2554 ptfd_prev = ptfd;
2555 ++ptfd;
2556 recoffset += reclength;
2558 heap_free(recbuf);
2561 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2562 int cVars, int offset, TLBVarDesc ** pptvd)
2564 int infolen, nameoffset, reclength;
2565 char recbuf[256];
2566 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2567 TLBVarDesc *ptvd;
2568 int i;
2569 int recoffset;
2571 TRACE_(typelib)("\n");
2573 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2574 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2575 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2576 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2577 recoffset += offset+sizeof(INT);
2578 for(i=0;i<cVars;i++, ++ptvd){
2579 /* name, eventually add to a hash table */
2580 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2581 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2582 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2583 /* read the variable information record */
2584 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2585 reclength &= 0xff;
2586 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2588 /* optional data */
2589 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2590 ptvd->HelpContext = pVarRec->HelpContext;
2592 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2593 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2595 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2596 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2598 /* fill the VarDesc Structure */
2599 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2600 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2601 ptvd->vardesc.varkind = pVarRec->VarKind;
2602 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2603 MSFT_GetTdesc(pcx, pVarRec->DataType,
2604 &ptvd->vardesc.elemdescVar.tdesc);
2605 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2606 if(pVarRec->VarKind == VAR_CONST ){
2607 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2608 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2609 pVarRec->OffsValue, pcx);
2610 } else
2611 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2612 recoffset += reclength;
2616 /* process Implemented Interfaces of a com class */
2617 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2618 int offset)
2620 int i;
2621 MSFT_RefRecord refrec;
2622 TLBImplType *pImpl;
2624 TRACE_(typelib)("\n");
2626 pTI->impltypes = TLBImplType_Alloc(count);
2627 pImpl = pTI->impltypes;
2628 for(i=0;i<count;i++){
2629 if(offset<0) break; /* paranoia */
2630 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2631 pImpl->hRef = refrec.reftype;
2632 pImpl->implflags=refrec.flags;
2633 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2634 offset=refrec.onext;
2635 ++pImpl;
2639 #ifdef _WIN64
2640 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2641 * and some structures, and fix the alignment */
2642 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2644 if(info->typekind == TKIND_ALIAS){
2645 switch(info->tdescAlias->vt){
2646 case VT_BSTR:
2647 case VT_DISPATCH:
2648 case VT_UNKNOWN:
2649 case VT_PTR:
2650 case VT_SAFEARRAY:
2651 case VT_LPSTR:
2652 case VT_LPWSTR:
2653 info->cbSizeInstance = sizeof(void*);
2654 info->cbAlignment = sizeof(void*);
2655 break;
2656 case VT_CARRAY:
2657 case VT_USERDEFINED:
2658 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->cbSizeInstance, &info->cbAlignment);
2659 break;
2660 case VT_VARIANT:
2661 info->cbSizeInstance = sizeof(VARIANT);
2662 info->cbAlignment = 8;
2663 default:
2664 if(info->cbSizeInstance < sizeof(void*))
2665 info->cbAlignment = info->cbSizeInstance;
2666 else
2667 info->cbAlignment = sizeof(void*);
2668 break;
2670 }else if(info->typekind == TKIND_INTERFACE ||
2671 info->typekind == TKIND_DISPATCH ||
2672 info->typekind == TKIND_COCLASS){
2673 info->cbSizeInstance = sizeof(void*);
2674 info->cbAlignment = sizeof(void*);
2677 #endif
2680 * process a typeinfo record
2682 static ITypeInfoImpl * MSFT_DoTypeInfo(
2683 TLBContext *pcx,
2684 int count,
2685 ITypeLibImpl * pLibInfo)
2687 MSFT_TypeInfoBase tiBase;
2688 ITypeInfoImpl *ptiRet;
2690 TRACE_(typelib)("count=%u\n", count);
2692 ptiRet = ITypeInfoImpl_Constructor();
2693 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2694 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2696 /* this is where we are coming from */
2697 ptiRet->pTypeLib = pLibInfo;
2698 ptiRet->index=count;
2700 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2701 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2702 ptiRet->lpstrSchema=NULL; /* reserved */
2703 ptiRet->cbSizeInstance=tiBase.size;
2704 ptiRet->typekind=tiBase.typekind & 0xF;
2705 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2706 ptiRet->cVars=HIWORD(tiBase.cElement);
2707 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2708 ptiRet->wTypeFlags=tiBase.flags;
2709 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2710 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2711 ptiRet->cImplTypes=tiBase.cImplTypes;
2712 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2713 if(ptiRet->typekind == TKIND_ALIAS){
2714 TYPEDESC tmp;
2715 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2716 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2717 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2720 /* FIXME: */
2721 /* IDLDESC idldescType; *//* never saw this one != zero */
2723 /* name, eventually add to a hash table */
2724 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2725 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2726 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2727 /* help info */
2728 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2729 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2730 ptiRet->dwHelpContext=tiBase.helpcontext;
2732 if (ptiRet->typekind == TKIND_MODULE)
2733 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2735 /* note: InfoType's Help file and HelpStringDll come from the containing
2736 * library. Further HelpString and Docstring appear to be the same thing :(
2738 /* functions */
2739 if(ptiRet->cFuncs >0 )
2740 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2741 ptiRet->cVars,
2742 tiBase.memoffset, &ptiRet->funcdescs);
2743 /* variables */
2744 if(ptiRet->cVars >0 )
2745 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2746 ptiRet->cVars,
2747 tiBase.memoffset, &ptiRet->vardescs);
2748 if(ptiRet->cImplTypes >0 ) {
2749 switch(ptiRet->typekind)
2751 case TKIND_COCLASS:
2752 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2753 tiBase.datatype1);
2754 break;
2755 case TKIND_DISPATCH:
2756 /* This is not -1 when the interface is a non-base dual interface or
2757 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2758 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2759 not this interface.
2762 if (tiBase.datatype1 != -1)
2764 ptiRet->impltypes = TLBImplType_Alloc(1);
2765 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2767 break;
2768 default:
2769 ptiRet->impltypes = TLBImplType_Alloc(1);
2770 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2771 break;
2774 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2776 TRACE_(typelib)("%s guid: %s kind:%s\n",
2777 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2778 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2779 typekind_desc[ptiRet->typekind]);
2780 if (TRACE_ON(typelib))
2781 dump_TypeInfo(ptiRet);
2783 return ptiRet;
2786 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2788 char *string;
2789 INT16 len_str, len_piece;
2790 int offs = 0, lengthInChars;
2792 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2793 while (1) {
2794 TLBString *tlbstr;
2796 if (offs >= pcx->pTblDir->pStringtab.length)
2797 return S_OK;
2799 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2800 len_piece = len_str + sizeof(INT16);
2801 if(len_piece % 4)
2802 len_piece = (len_piece + 4) & ~0x3;
2803 if(len_piece < 8)
2804 len_piece = 8;
2806 string = heap_alloc(len_piece + 1);
2807 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2808 string[len_str] = '\0';
2810 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2811 string, -1, NULL, 0);
2812 if (!lengthInChars) {
2813 heap_free(string);
2814 return E_UNEXPECTED;
2817 tlbstr = heap_alloc(sizeof(TLBString));
2819 tlbstr->offset = offs;
2820 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2821 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2823 heap_free(string);
2825 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2827 offs += len_piece;
2831 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2833 TLBRefType *ref;
2834 int offs = 0;
2836 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2837 while (offs < pcx->pTblDir->pImpInfo.length) {
2838 MSFT_ImpInfo impinfo;
2839 TLBImpLib *pImpLib;
2841 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2843 ref = heap_alloc_zero(sizeof(TLBRefType));
2844 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2846 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2847 if(pImpLib->offset==impinfo.oImpFile)
2848 break;
2850 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2851 ref->reference = offs;
2852 ref->pImpTLInfo = pImpLib;
2853 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2854 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2855 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2856 ref->index = TLB_REF_USE_GUID;
2857 } else
2858 ref->index = impinfo.oGuid;
2859 }else{
2860 ERR("Cannot find a reference\n");
2861 ref->reference = -1;
2862 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2865 offs += sizeof(impinfo);
2868 return S_OK;
2871 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2872 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2873 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2874 * tradeoff here.
2876 static struct list tlb_cache = LIST_INIT(tlb_cache);
2877 static CRITICAL_SECTION cache_section;
2878 static CRITICAL_SECTION_DEBUG cache_section_debug =
2880 0, 0, &cache_section,
2881 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2882 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2884 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2887 typedef struct TLB_PEFile
2889 IUnknown IUnknown_iface;
2890 LONG refs;
2891 HMODULE dll;
2892 HRSRC typelib_resource;
2893 HGLOBAL typelib_global;
2894 LPVOID typelib_base;
2895 } TLB_PEFile;
2897 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2899 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2902 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2904 if (IsEqualIID(riid, &IID_IUnknown))
2906 *ppv = iface;
2907 IUnknown_AddRef(iface);
2908 return S_OK;
2910 *ppv = NULL;
2911 return E_NOINTERFACE;
2914 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2916 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2917 return InterlockedIncrement(&This->refs);
2920 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2922 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2923 ULONG refs = InterlockedDecrement(&This->refs);
2924 if (!refs)
2926 if (This->typelib_global)
2927 FreeResource(This->typelib_global);
2928 if (This->dll)
2929 FreeLibrary(This->dll);
2930 heap_free(This);
2932 return refs;
2935 static const IUnknownVtbl TLB_PEFile_Vtable =
2937 TLB_PEFile_QueryInterface,
2938 TLB_PEFile_AddRef,
2939 TLB_PEFile_Release
2942 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2944 TLB_PEFile *This;
2945 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2947 This = heap_alloc(sizeof(TLB_PEFile));
2948 if (!This)
2949 return E_OUTOFMEMORY;
2951 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2952 This->refs = 1;
2953 This->dll = NULL;
2954 This->typelib_resource = NULL;
2955 This->typelib_global = NULL;
2956 This->typelib_base = NULL;
2958 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2959 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2961 if (This->dll)
2963 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2964 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2965 if (This->typelib_resource)
2967 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2968 if (This->typelib_global)
2970 This->typelib_base = LockResource(This->typelib_global);
2972 if (This->typelib_base)
2974 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2975 *ppBase = This->typelib_base;
2976 *ppFile = &This->IUnknown_iface;
2977 return S_OK;
2982 TRACE("No TYPELIB resource found\n");
2983 hr = E_FAIL;
2986 TLB_PEFile_Release(&This->IUnknown_iface);
2987 return hr;
2990 typedef struct TLB_NEFile
2992 IUnknown IUnknown_iface;
2993 LONG refs;
2994 LPVOID typelib_base;
2995 } TLB_NEFile;
2997 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2999 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
3002 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3004 if (IsEqualIID(riid, &IID_IUnknown))
3006 *ppv = iface;
3007 IUnknown_AddRef(iface);
3008 return S_OK;
3010 *ppv = NULL;
3011 return E_NOINTERFACE;
3014 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3016 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3017 return InterlockedIncrement(&This->refs);
3020 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3022 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3023 ULONG refs = InterlockedDecrement(&This->refs);
3024 if (!refs)
3026 heap_free(This->typelib_base);
3027 heap_free(This);
3029 return refs;
3032 static const IUnknownVtbl TLB_NEFile_Vtable =
3034 TLB_NEFile_QueryInterface,
3035 TLB_NEFile_AddRef,
3036 TLB_NEFile_Release
3039 /***********************************************************************
3040 * read_xx_header [internal]
3042 static int read_xx_header( HFILE lzfd )
3044 IMAGE_DOS_HEADER mzh;
3045 char magic[3];
3047 LZSeek( lzfd, 0, SEEK_SET );
3048 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3049 return 0;
3050 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3051 return 0;
3053 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3054 if ( 2 != LZRead( lzfd, magic, 2 ) )
3055 return 0;
3057 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3059 if ( magic[0] == 'N' && magic[1] == 'E' )
3060 return IMAGE_OS2_SIGNATURE;
3061 if ( magic[0] == 'P' && magic[1] == 'E' )
3062 return IMAGE_NT_SIGNATURE;
3064 magic[2] = '\0';
3065 WARN("Can't handle %s files.\n", magic );
3066 return 0;
3070 /***********************************************************************
3071 * find_ne_resource [internal]
3073 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3074 DWORD *resLen, DWORD *resOff )
3076 IMAGE_OS2_HEADER nehd;
3077 NE_TYPEINFO *typeInfo;
3078 NE_NAMEINFO *nameInfo;
3079 DWORD nehdoffset;
3080 LPBYTE resTab;
3081 DWORD resTabSize;
3082 int count;
3084 /* Read in NE header */
3085 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3086 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3088 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3089 if ( !resTabSize )
3091 TRACE("No resources in NE dll\n" );
3092 return FALSE;
3095 /* Read in resource table */
3096 resTab = heap_alloc( resTabSize );
3097 if ( !resTab ) return FALSE;
3099 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3100 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3102 heap_free( resTab );
3103 return FALSE;
3106 /* Find resource */
3107 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3109 if (!IS_INTRESOURCE(typeid)) /* named type */
3111 BYTE len = strlen( typeid );
3112 while (typeInfo->type_id)
3114 if (!(typeInfo->type_id & 0x8000))
3116 BYTE *p = resTab + typeInfo->type_id;
3117 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3119 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3120 typeInfo->count * sizeof(NE_NAMEINFO));
3123 else /* numeric type id */
3125 WORD id = LOWORD(typeid) | 0x8000;
3126 while (typeInfo->type_id)
3128 if (typeInfo->type_id == id) goto found_type;
3129 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3130 typeInfo->count * sizeof(NE_NAMEINFO));
3133 TRACE("No typeid entry found for %p\n", typeid );
3134 heap_free( resTab );
3135 return FALSE;
3137 found_type:
3138 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3140 if (!IS_INTRESOURCE(resid)) /* named resource */
3142 BYTE len = strlen( resid );
3143 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3145 BYTE *p = resTab + nameInfo->id;
3146 if (nameInfo->id & 0x8000) continue;
3147 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3150 else /* numeric resource id */
3152 WORD id = LOWORD(resid) | 0x8000;
3153 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3154 if (nameInfo->id == id) goto found_name;
3156 TRACE("No resid entry found for %p\n", typeid );
3157 heap_free( resTab );
3158 return FALSE;
3160 found_name:
3161 /* Return resource data */
3162 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3163 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3165 heap_free( resTab );
3166 return TRUE;
3169 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3171 HFILE lzfd = -1;
3172 OFSTRUCT ofs;
3173 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3174 TLB_NEFile *This;
3176 This = heap_alloc(sizeof(TLB_NEFile));
3177 if (!This) return E_OUTOFMEMORY;
3179 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3180 This->refs = 1;
3181 This->typelib_base = NULL;
3183 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3184 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3186 DWORD reslen, offset;
3187 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3189 This->typelib_base = heap_alloc(reslen);
3190 if( !This->typelib_base )
3191 hr = E_OUTOFMEMORY;
3192 else
3194 LZSeek( lzfd, offset, SEEK_SET );
3195 reslen = LZRead( lzfd, This->typelib_base, reslen );
3196 LZClose( lzfd );
3197 *ppBase = This->typelib_base;
3198 *pdwTLBLength = reslen;
3199 *ppFile = &This->IUnknown_iface;
3200 return S_OK;
3205 if( lzfd >= 0) LZClose( lzfd );
3206 TLB_NEFile_Release(&This->IUnknown_iface);
3207 return hr;
3210 typedef struct TLB_Mapping
3212 IUnknown IUnknown_iface;
3213 LONG refs;
3214 HANDLE file;
3215 HANDLE mapping;
3216 LPVOID typelib_base;
3217 } TLB_Mapping;
3219 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3221 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3224 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3226 if (IsEqualIID(riid, &IID_IUnknown))
3228 *ppv = iface;
3229 IUnknown_AddRef(iface);
3230 return S_OK;
3232 *ppv = NULL;
3233 return E_NOINTERFACE;
3236 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3238 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3239 return InterlockedIncrement(&This->refs);
3242 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3244 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3245 ULONG refs = InterlockedDecrement(&This->refs);
3246 if (!refs)
3248 if (This->typelib_base)
3249 UnmapViewOfFile(This->typelib_base);
3250 if (This->mapping)
3251 CloseHandle(This->mapping);
3252 if (This->file != INVALID_HANDLE_VALUE)
3253 CloseHandle(This->file);
3254 heap_free(This);
3256 return refs;
3259 static const IUnknownVtbl TLB_Mapping_Vtable =
3261 TLB_Mapping_QueryInterface,
3262 TLB_Mapping_AddRef,
3263 TLB_Mapping_Release
3266 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3268 TLB_Mapping *This;
3270 This = heap_alloc(sizeof(TLB_Mapping));
3271 if (!This)
3272 return E_OUTOFMEMORY;
3274 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3275 This->refs = 1;
3276 This->file = INVALID_HANDLE_VALUE;
3277 This->mapping = NULL;
3278 This->typelib_base = NULL;
3280 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3281 if (INVALID_HANDLE_VALUE != This->file)
3283 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3284 if (This->mapping)
3286 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3287 if(This->typelib_base)
3289 /* retrieve file size */
3290 *pdwTLBLength = GetFileSize(This->file, NULL);
3291 *ppBase = This->typelib_base;
3292 *ppFile = &This->IUnknown_iface;
3293 return S_OK;
3298 IUnknown_Release(&This->IUnknown_iface);
3299 return TYPE_E_CANTLOADLIBRARY;
3302 /****************************************************************************
3303 * TLB_ReadTypeLib
3305 * find the type of the typelib file and map the typelib resource into
3306 * the memory
3309 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3310 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3312 ITypeLibImpl *entry;
3313 HRESULT ret;
3314 INT index = 1;
3315 LPWSTR index_str, file = (LPWSTR)pszFileName;
3316 LPVOID pBase = NULL;
3317 DWORD dwTLBLength = 0;
3318 IUnknown *pFile = NULL;
3319 HANDLE h;
3321 *ppTypeLib = NULL;
3323 index_str = strrchrW(pszFileName, '\\');
3324 if(index_str && *++index_str != '\0')
3326 LPWSTR end_ptr;
3327 LONG idx = strtolW(index_str, &end_ptr, 10);
3328 if(*end_ptr == '\0')
3330 int str_len = index_str - pszFileName - 1;
3331 index = idx;
3332 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3333 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3334 file[str_len] = 0;
3338 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3340 if(strchrW(file, '\\'))
3342 lstrcpyW(pszPath, file);
3344 else
3346 int len = GetSystemDirectoryW(pszPath, cchPath);
3347 pszPath[len] = '\\';
3348 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3352 if(file != pszFileName) heap_free(file);
3354 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3355 if(h != INVALID_HANDLE_VALUE){
3356 FILE_NAME_INFORMATION size_info;
3357 BOOL br;
3359 /* GetFileInformationByHandleEx returns the path of the file without
3360 * WOW64 redirection */
3361 br = GetFileInformationByHandleEx(h, FileNameInfo, &size_info, sizeof(size_info));
3362 if(br || GetLastError() == ERROR_MORE_DATA){
3363 FILE_NAME_INFORMATION *info;
3364 DWORD size = sizeof(*info) + size_info.FileNameLength + sizeof(WCHAR);
3366 info = HeapAlloc(GetProcessHeap(), 0, size);
3368 br = GetFileInformationByHandleEx(h, FileNameInfo, info, size);
3369 if(br){
3370 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3371 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3374 HeapFree(GetProcessHeap(), 0, info);
3377 CloseHandle(h);
3380 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3382 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3383 EnterCriticalSection(&cache_section);
3384 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3386 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3388 TRACE("cache hit\n");
3389 *ppTypeLib = &entry->ITypeLib2_iface;
3390 ITypeLib2_AddRef(*ppTypeLib);
3391 LeaveCriticalSection(&cache_section);
3392 return S_OK;
3395 LeaveCriticalSection(&cache_section);
3397 /* now actually load and parse the typelib */
3399 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3400 if (ret == TYPE_E_CANTLOADLIBRARY)
3401 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3402 if (ret == TYPE_E_CANTLOADLIBRARY)
3403 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3404 if (SUCCEEDED(ret))
3406 if (dwTLBLength >= 4)
3408 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3409 if (dwSignature == MSFT_SIGNATURE)
3410 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3411 else if (dwSignature == SLTG_SIGNATURE)
3412 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3413 else
3415 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3416 ret = TYPE_E_CANTLOADLIBRARY;
3419 else
3420 ret = TYPE_E_CANTLOADLIBRARY;
3421 IUnknown_Release(pFile);
3424 if(*ppTypeLib) {
3425 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3427 TRACE("adding to cache\n");
3428 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3429 lstrcpyW(impl->path, pszPath);
3430 /* We should really canonicalise the path here. */
3431 impl->index = index;
3433 /* FIXME: check if it has added already in the meantime */
3434 EnterCriticalSection(&cache_section);
3435 list_add_head(&tlb_cache, &impl->entry);
3436 LeaveCriticalSection(&cache_section);
3437 ret = S_OK;
3439 else
3441 if(ret != E_FAIL)
3442 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3444 ret = TYPE_E_CANTLOADLIBRARY;
3448 return ret;
3451 /*================== ITypeLib(2) Methods ===================================*/
3453 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3455 ITypeLibImpl* pTypeLibImpl;
3457 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3458 if (!pTypeLibImpl) return NULL;
3460 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3461 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3462 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3463 pTypeLibImpl->ref = 1;
3465 list_init(&pTypeLibImpl->implib_list);
3466 list_init(&pTypeLibImpl->custdata_list);
3467 list_init(&pTypeLibImpl->name_list);
3468 list_init(&pTypeLibImpl->string_list);
3469 list_init(&pTypeLibImpl->guid_list);
3470 list_init(&pTypeLibImpl->ref_list);
3471 pTypeLibImpl->dispatch_href = -1;
3473 return pTypeLibImpl;
3476 /****************************************************************************
3477 * ITypeLib2_Constructor_MSFT
3479 * loading an MSFT typelib from an in-memory image
3481 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3483 TLBContext cx;
3484 LONG lPSegDir;
3485 MSFT_Header tlbHeader;
3486 MSFT_SegDir tlbSegDir;
3487 ITypeLibImpl * pTypeLibImpl;
3488 int i;
3490 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3492 pTypeLibImpl = TypeLibImpl_Constructor();
3493 if (!pTypeLibImpl) return NULL;
3495 /* get pointer to beginning of typelib data */
3496 cx.pos = 0;
3497 cx.oStart=0;
3498 cx.mapping = pLib;
3499 cx.pLibInfo = pTypeLibImpl;
3500 cx.length = dwTLBLength;
3502 /* read header */
3503 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3504 TRACE_(typelib)("header:\n");
3505 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3506 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3507 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3508 return NULL;
3510 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3512 /* there is a small amount of information here until the next important
3513 * part:
3514 * the segment directory . Try to calculate the amount of data */
3515 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3517 /* now read the segment directory */
3518 TRACE("read segment directory (at %d)\n",lPSegDir);
3519 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3520 cx.pTblDir = &tlbSegDir;
3522 /* just check two entries */
3523 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3525 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3526 heap_free(pTypeLibImpl);
3527 return NULL;
3530 MSFT_ReadAllNames(&cx);
3531 MSFT_ReadAllStrings(&cx);
3532 MSFT_ReadAllGuids(&cx);
3534 /* now fill our internal data */
3535 /* TLIBATTR fields */
3536 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3538 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3539 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3540 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3541 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3542 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3544 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3545 pTypeLibImpl->lcid = tlbHeader.lcid;
3547 /* name, eventually add to a hash table */
3548 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3550 /* help info */
3551 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3552 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3554 if( tlbHeader.varflags & HELPDLLFLAG)
3556 int offset;
3557 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3558 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3561 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3563 /* custom data */
3564 if(tlbHeader.CustomDataOffset >= 0)
3566 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3569 /* fill in type descriptions */
3570 if(tlbSegDir.pTypdescTab.length > 0)
3572 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3573 INT16 td[4];
3574 pTypeLibImpl->ctTypeDesc = cTD;
3575 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3576 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3577 for(i=0; i<cTD; )
3579 /* FIXME: add several sanity checks here */
3580 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3581 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3583 /* FIXME: check safearray */
3584 if(td[3] < 0)
3585 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3586 else
3587 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3589 else if(td[0] == VT_CARRAY)
3591 /* array descr table here */
3592 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3594 else if(td[0] == VT_USERDEFINED)
3596 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3598 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3601 /* second time around to fill the array subscript info */
3602 for(i=0;i<cTD;i++)
3604 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3605 if(tlbSegDir.pArrayDescriptions.offset>0)
3607 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3608 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3610 if(td[1]<0)
3611 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3612 else
3613 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3615 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3617 for(j = 0; j<td[2]; j++)
3619 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3620 sizeof(INT), &cx, DO_NOT_SEEK);
3621 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3622 sizeof(INT), &cx, DO_NOT_SEEK);
3625 else
3627 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3628 ERR("didn't find array description data\n");
3633 /* imported type libs */
3634 if(tlbSegDir.pImpFiles.offset>0)
3636 TLBImpLib *pImpLib;
3637 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3638 UINT16 size;
3640 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3642 char *name;
3644 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3645 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3646 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3648 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3649 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3650 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3651 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3653 size >>= 2;
3654 name = heap_alloc_zero(size+1);
3655 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3656 pImpLib->name = TLB_MultiByteToBSTR(name);
3657 heap_free(name);
3659 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3660 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3662 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3666 MSFT_ReadAllRefs(&cx);
3668 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3670 /* type infos */
3671 if(tlbHeader.nrtypeinfos >= 0 )
3673 ITypeInfoImpl **ppTI;
3675 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3677 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3679 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3681 ++ppTI;
3682 (pTypeLibImpl->TypeInfoCount)++;
3686 #ifdef _WIN64
3687 if(pTypeLibImpl->syskind == SYS_WIN32){
3688 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3689 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3691 #endif
3693 TRACE("(%p)\n", pTypeLibImpl);
3694 return &pTypeLibImpl->ITypeLib2_iface;
3698 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3700 char b[3];
3701 int i;
3702 short s;
3704 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3705 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3706 return FALSE;
3709 guid->Data4[0] = s >> 8;
3710 guid->Data4[1] = s & 0xff;
3712 b[2] = '\0';
3713 for(i = 0; i < 6; i++) {
3714 memcpy(b, str + 24 + 2 * i, 2);
3715 guid->Data4[i + 2] = strtol(b, NULL, 16);
3717 return TRUE;
3720 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3722 WORD bytelen;
3723 DWORD len;
3724 BSTR tmp_str;
3726 *pStr = NULL;
3727 bytelen = *(const WORD*)ptr;
3728 if(bytelen == 0xffff) return 2;
3730 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3731 tmp_str = SysAllocStringLen(NULL, len);
3732 if (tmp_str) {
3733 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3734 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3735 SysFreeString(tmp_str);
3737 return bytelen + 2;
3740 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3742 WORD bytelen;
3744 *str = NULL;
3745 bytelen = *(const WORD*)ptr;
3746 if(bytelen == 0xffff) return 2;
3747 *str = heap_alloc(bytelen + 1);
3748 memcpy(*str, ptr + 2, bytelen);
3749 (*str)[bytelen] = '\0';
3750 return bytelen + 2;
3753 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3755 BSTR tmp_str;
3756 TLBString *tlbstr;
3758 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3759 if (tlbstr->offset == offset)
3760 return tlbstr;
3763 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3764 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3765 SysFreeString(tmp_str);
3767 return tlbstr;
3770 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3772 char *ptr = pLibBlk;
3773 WORD w;
3775 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3776 FIXME("libblk magic = %04x\n", w);
3777 return 0;
3780 ptr += 6;
3781 if((w = *(WORD*)ptr) != 0xffff) {
3782 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3783 ptr += w;
3785 ptr += 2;
3787 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3789 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3791 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3792 ptr += 4;
3794 pTypeLibImpl->syskind = *(WORD*)ptr;
3795 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3796 ptr += 2;
3798 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3799 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3800 else
3801 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3802 ptr += 2;
3804 ptr += 4; /* skip res12 */
3806 pTypeLibImpl->libflags = *(WORD*)ptr;
3807 ptr += 2;
3809 pTypeLibImpl->ver_major = *(WORD*)ptr;
3810 ptr += 2;
3812 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3813 ptr += 2;
3815 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3816 ptr += sizeof(GUID);
3818 return ptr - (char*)pLibBlk;
3821 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3822 typedef struct
3824 unsigned int num;
3825 HREFTYPE refs[1];
3826 } sltg_ref_lookup_t;
3828 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3829 HREFTYPE *typelib_ref)
3831 if(table && typeinfo_ref < table->num)
3833 *typelib_ref = table->refs[typeinfo_ref];
3834 return S_OK;
3837 ERR_(typelib)("Unable to find reference\n");
3838 *typelib_ref = -1;
3839 return E_FAIL;
3842 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3844 BOOL done = FALSE;
3846 while(!done) {
3847 if((*pType & 0xe00) == 0xe00) {
3848 pTD->vt = VT_PTR;
3849 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3850 pTD = pTD->u.lptdesc;
3852 switch(*pType & 0x3f) {
3853 case VT_PTR:
3854 pTD->vt = VT_PTR;
3855 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3856 pTD = pTD->u.lptdesc;
3857 break;
3859 case VT_USERDEFINED:
3860 pTD->vt = VT_USERDEFINED;
3861 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3862 done = TRUE;
3863 break;
3865 case VT_CARRAY:
3867 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3868 array */
3870 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3872 pTD->vt = VT_CARRAY;
3873 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3874 pTD->u.lpadesc->cDims = pSA->cDims;
3875 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3876 pSA->cDims * sizeof(SAFEARRAYBOUND));
3878 pTD = &pTD->u.lpadesc->tdescElem;
3879 break;
3882 case VT_SAFEARRAY:
3884 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3885 useful? */
3887 pType++;
3888 pTD->vt = VT_SAFEARRAY;
3889 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3890 pTD = pTD->u.lptdesc;
3891 break;
3893 default:
3894 pTD->vt = *pType & 0x3f;
3895 done = TRUE;
3896 break;
3898 pType++;
3900 return pType;
3903 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3904 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3906 /* Handle [in/out] first */
3907 if((*pType & 0xc000) == 0xc000)
3908 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3909 else if(*pType & 0x8000)
3910 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3911 else if(*pType & 0x4000)
3912 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3913 else
3914 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3916 if(*pType & 0x2000)
3917 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3919 if(*pType & 0x80)
3920 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3922 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3926 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3927 char *pNameTable)
3929 unsigned int ref;
3930 char *name;
3931 TLBRefType *ref_type;
3932 sltg_ref_lookup_t *table;
3933 HREFTYPE typelib_ref;
3935 if(pRef->magic != SLTG_REF_MAGIC) {
3936 FIXME("Ref magic = %x\n", pRef->magic);
3937 return NULL;
3939 name = ( (char*)pRef->names + pRef->number);
3941 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3942 table->num = pRef->number >> 3;
3944 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3946 /* We don't want the first href to be 0 */
3947 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3949 for(ref = 0; ref < pRef->number >> 3; ref++) {
3950 char *refname;
3951 unsigned int lib_offs, type_num;
3953 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3955 name += SLTG_ReadStringA(name, &refname);
3956 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3957 FIXME_(typelib)("Can't sscanf ref\n");
3958 if(lib_offs != 0xffff) {
3959 TLBImpLib *import;
3961 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3962 if(import->offset == lib_offs)
3963 break;
3965 if(&import->entry == &pTL->implib_list) {
3966 char fname[MAX_PATH+1];
3967 int len;
3968 GUID tmpguid;
3970 import = heap_alloc_zero(sizeof(*import));
3971 import->offset = lib_offs;
3972 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3973 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3974 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3975 &import->wVersionMajor,
3976 &import->wVersionMinor,
3977 &import->lcid, fname) != 4) {
3978 FIXME_(typelib)("can't sscanf ref %s\n",
3979 pNameTable + lib_offs + 40);
3981 len = strlen(fname);
3982 if(fname[len-1] != '#')
3983 FIXME("fname = %s\n", fname);
3984 fname[len-1] = '\0';
3985 import->name = TLB_MultiByteToBSTR(fname);
3986 list_add_tail(&pTL->implib_list, &import->entry);
3988 ref_type->pImpTLInfo = import;
3990 /* Store a reference to IDispatch */
3991 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3992 pTL->dispatch_href = typelib_ref;
3994 } else { /* internal ref */
3995 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3997 ref_type->reference = typelib_ref;
3998 ref_type->index = type_num;
4000 heap_free(refname);
4001 list_add_tail(&pTL->ref_list, &ref_type->entry);
4003 table->refs[ref] = typelib_ref;
4004 typelib_ref += 4;
4006 if((BYTE)*name != SLTG_REF_MAGIC)
4007 FIXME_(typelib)("End of ref block magic = %x\n", *name);
4008 dump_TLBRefType(pTL);
4009 return table;
4012 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
4013 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
4015 SLTG_ImplInfo *info;
4016 TLBImplType *pImplType;
4017 /* I don't really get this structure, usually it's 0x16 bytes
4018 long, but iuser.tlb contains some that are 0x18 bytes long.
4019 That's ok because we can use the next ptr to jump to the next
4020 one. But how do we know the length of the last one? The WORD
4021 at offs 0x8 might be the clue. For now I'm just assuming that
4022 the last one is the regular 0x16 bytes. */
4024 info = (SLTG_ImplInfo*)pBlk;
4025 while(1){
4026 pTI->cImplTypes++;
4027 if(info->next == 0xffff)
4028 break;
4029 info = (SLTG_ImplInfo*)(pBlk + info->next);
4032 info = (SLTG_ImplInfo*)pBlk;
4033 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
4034 pImplType = pTI->impltypes;
4035 while(1) {
4036 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4037 pImplType->implflags = info->impltypeflags;
4038 ++pImplType;
4040 if(info->next == 0xffff)
4041 break;
4042 if(OneOnly)
4043 FIXME_(typelib)("Interface inheriting more than one interface\n");
4044 info = (SLTG_ImplInfo*)(pBlk + info->next);
4046 info++; /* see comment at top of function */
4047 return (char*)info;
4050 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4051 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4053 TLBVarDesc *pVarDesc;
4054 const TLBString *prevName = NULL;
4055 SLTG_Variable *pItem;
4056 unsigned short i;
4057 WORD *pType;
4059 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4061 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4062 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4064 pVarDesc->vardesc.memid = pItem->memid;
4066 if (pItem->magic != SLTG_VAR_MAGIC &&
4067 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4068 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4069 return;
4072 if (pItem->name == 0xfffe)
4073 pVarDesc->Name = prevName;
4074 else
4075 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4077 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4078 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4079 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4081 if(pItem->flags & 0x02)
4082 pType = &pItem->type;
4083 else
4084 pType = (WORD*)(pBlk + pItem->type);
4086 if (pItem->flags & ~0xda)
4087 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4089 SLTG_DoElem(pType, pBlk,
4090 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4092 if (TRACE_ON(typelib)) {
4093 char buf[300];
4094 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4095 TRACE_(typelib)("elemdescVar: %s\n", buf);
4098 if (pItem->flags & 0x40) {
4099 TRACE_(typelib)("VAR_DISPATCH\n");
4100 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4102 else if (pItem->flags & 0x10) {
4103 TRACE_(typelib)("VAR_CONST\n");
4104 pVarDesc->vardesc.varkind = VAR_CONST;
4105 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4106 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4107 if (pItem->flags & 0x08)
4108 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4109 else {
4110 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4112 case VT_LPSTR:
4113 case VT_LPWSTR:
4114 case VT_BSTR:
4116 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4117 BSTR str;
4118 TRACE_(typelib)("len = %u\n", len);
4119 if (len == 0xffff) {
4120 str = NULL;
4121 } else {
4122 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4123 str = SysAllocStringLen(NULL, alloc_len);
4124 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4126 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4127 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4128 break;
4130 case VT_I2:
4131 case VT_UI2:
4132 case VT_I4:
4133 case VT_UI4:
4134 case VT_INT:
4135 case VT_UINT:
4136 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4137 *(INT*)(pBlk + pItem->byte_offs);
4138 break;
4139 default:
4140 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4144 else {
4145 TRACE_(typelib)("VAR_PERINSTANCE\n");
4146 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4147 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4150 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4151 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4153 if (pItem->flags & 0x80)
4154 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4156 prevName = pVarDesc->Name;
4158 pTI->cVars = cVars;
4161 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4162 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4164 SLTG_Function *pFunc;
4165 unsigned short i;
4166 TLBFuncDesc *pFuncDesc;
4168 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4170 pFuncDesc = pTI->funcdescs;
4171 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4172 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4174 int param;
4175 WORD *pType, *pArg;
4177 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4178 case SLTG_FUNCTION_MAGIC:
4179 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4180 break;
4181 case SLTG_DISPATCH_FUNCTION_MAGIC:
4182 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4183 break;
4184 case SLTG_STATIC_FUNCTION_MAGIC:
4185 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4186 break;
4187 default:
4188 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4189 continue;
4191 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4193 pFuncDesc->funcdesc.memid = pFunc->dispid;
4194 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4195 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4196 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4197 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4198 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4200 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4201 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4203 if(pFunc->retnextopt & 0x80)
4204 pType = &pFunc->rettype;
4205 else
4206 pType = (WORD*)(pBlk + pFunc->rettype);
4208 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4210 pFuncDesc->funcdesc.lprgelemdescParam =
4211 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4212 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4214 pArg = (WORD*)(pBlk + pFunc->arg_off);
4216 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4217 char *paramName = pNameTable + *pArg;
4218 BOOL HaveOffs;
4219 /* If arg type follows then paramName points to the 2nd
4220 letter of the name, else the next WORD is an offset to
4221 the arg type and paramName points to the first letter.
4222 So let's take one char off paramName and see if we're
4223 pointing at an alpha-numeric char. However if *pArg is
4224 0xffff or 0xfffe then the param has no name, the former
4225 meaning that the next WORD is the type, the latter
4226 meaning that the next WORD is an offset to the type. */
4228 HaveOffs = FALSE;
4229 if(*pArg == 0xffff)
4230 paramName = NULL;
4231 else if(*pArg == 0xfffe) {
4232 paramName = NULL;
4233 HaveOffs = TRUE;
4235 else if(paramName[-1] && !isalnum(paramName[-1]))
4236 HaveOffs = TRUE;
4238 pArg++;
4240 if(HaveOffs) { /* the next word is an offset to type */
4241 pType = (WORD*)(pBlk + *pArg);
4242 SLTG_DoElem(pType, pBlk,
4243 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4244 pArg++;
4245 } else {
4246 if(paramName)
4247 paramName--;
4248 pArg = SLTG_DoElem(pArg, pBlk,
4249 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4252 /* Are we an optional param ? */
4253 if(pFuncDesc->funcdesc.cParams - param <=
4254 pFuncDesc->funcdesc.cParamsOpt)
4255 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4257 if(paramName) {
4258 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4259 paramName - pNameTable, pTI->pTypeLib);
4260 } else {
4261 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4265 pTI->cFuncs = cFuncs;
4268 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4269 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4270 SLTG_TypeInfoTail *pTITail)
4272 char *pFirstItem;
4273 sltg_ref_lookup_t *ref_lookup = NULL;
4275 if(pTIHeader->href_table != 0xffffffff) {
4276 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4277 pNameTable);
4280 pFirstItem = pBlk;
4282 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4283 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4285 heap_free(ref_lookup);
4289 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4290 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4291 const SLTG_TypeInfoTail *pTITail)
4293 char *pFirstItem;
4294 sltg_ref_lookup_t *ref_lookup = NULL;
4296 if(pTIHeader->href_table != 0xffffffff) {
4297 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4298 pNameTable);
4301 pFirstItem = pBlk;
4303 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4304 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4307 if (pTITail->funcs_off != 0xffff)
4308 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4310 heap_free(ref_lookup);
4312 if (TRACE_ON(typelib))
4313 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4316 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4317 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4318 const SLTG_TypeInfoTail *pTITail)
4320 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4323 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4324 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4325 const SLTG_TypeInfoTail *pTITail)
4327 WORD *pType;
4328 sltg_ref_lookup_t *ref_lookup = NULL;
4330 if (pTITail->simple_alias) {
4331 /* if simple alias, no more processing required */
4332 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4333 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4334 return;
4337 if(pTIHeader->href_table != 0xffffffff) {
4338 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4339 pNameTable);
4342 /* otherwise it is an offset to a type */
4343 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4345 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4346 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4348 heap_free(ref_lookup);
4351 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4352 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4353 const SLTG_TypeInfoTail *pTITail)
4355 sltg_ref_lookup_t *ref_lookup = NULL;
4356 if (pTIHeader->href_table != 0xffffffff)
4357 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4358 pNameTable);
4360 if (pTITail->vars_off != 0xffff)
4361 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4363 if (pTITail->funcs_off != 0xffff)
4364 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4366 if (pTITail->impls_off != 0xffff)
4367 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4369 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4370 * of dispinterface functions including the IDispatch ones, so
4371 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4372 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4374 heap_free(ref_lookup);
4375 if (TRACE_ON(typelib))
4376 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4379 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4380 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4381 const SLTG_TypeInfoTail *pTITail)
4383 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4386 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4387 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4388 const SLTG_TypeInfoTail *pTITail)
4390 sltg_ref_lookup_t *ref_lookup = NULL;
4391 if (pTIHeader->href_table != 0xffffffff)
4392 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4393 pNameTable);
4395 if (pTITail->vars_off != 0xffff)
4396 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4398 if (pTITail->funcs_off != 0xffff)
4399 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4400 heap_free(ref_lookup);
4401 if (TRACE_ON(typelib))
4402 dump_TypeInfo(pTI);
4405 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4406 manageable copy of it into this */
4407 typedef struct {
4408 WORD small_no;
4409 char *index_name;
4410 char *other_name;
4411 WORD res1a;
4412 WORD name_offs;
4413 WORD more_bytes;
4414 char *extra;
4415 WORD res20;
4416 DWORD helpcontext;
4417 WORD res26;
4418 GUID uuid;
4419 } SLTG_InternalOtherTypeInfo;
4421 /****************************************************************************
4422 * ITypeLib2_Constructor_SLTG
4424 * loading a SLTG typelib from an in-memory image
4426 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4428 ITypeLibImpl *pTypeLibImpl;
4429 SLTG_Header *pHeader;
4430 SLTG_BlkEntry *pBlkEntry;
4431 SLTG_Magic *pMagic;
4432 SLTG_Index *pIndex;
4433 SLTG_Pad9 *pPad9;
4434 LPVOID pBlk, pFirstBlk;
4435 SLTG_LibBlk *pLibBlk;
4436 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4437 char *pAfterOTIBlks = NULL;
4438 char *pNameTable, *ptr;
4439 int i;
4440 DWORD len, order;
4441 ITypeInfoImpl **ppTypeInfoImpl;
4443 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4446 pTypeLibImpl = TypeLibImpl_Constructor();
4447 if (!pTypeLibImpl) return NULL;
4449 pHeader = pLib;
4451 TRACE_(typelib)("header:\n");
4452 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4453 pHeader->nrOfFileBlks );
4454 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4455 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4456 pHeader->SLTG_magic);
4457 return NULL;
4460 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4461 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4463 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4464 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4466 /* Next we have a magic block */
4467 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4469 /* Let's see if we're still in sync */
4470 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4471 sizeof(SLTG_COMPOBJ_MAGIC))) {
4472 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4473 return NULL;
4475 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4476 sizeof(SLTG_DIR_MAGIC))) {
4477 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4478 return NULL;
4481 pIndex = (SLTG_Index*)(pMagic+1);
4483 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4485 pFirstBlk = pPad9 + 1;
4487 /* We'll set up a ptr to the main library block, which is the last one. */
4489 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4490 pBlkEntry[order].next != 0;
4491 order = pBlkEntry[order].next - 1) {
4492 pBlk = (char*)pBlk + pBlkEntry[order].len;
4494 pLibBlk = pBlk;
4496 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4498 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4499 interspersed */
4501 len += 0x40;
4503 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4505 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4508 ptr = (char*)pLibBlk + len;
4510 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4511 WORD w, extra;
4512 len = 0;
4514 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4516 w = *(WORD*)(ptr + 2);
4517 if(w != 0xffff) {
4518 len += w;
4519 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4520 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4521 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4523 w = *(WORD*)(ptr + 4 + len);
4524 if(w != 0xffff) {
4525 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4526 len += w;
4527 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4528 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4529 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4531 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4532 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4533 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4534 if(extra) {
4535 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4536 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4537 len += extra;
4539 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4540 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4541 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4542 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4543 len += sizeof(SLTG_OtherTypeInfo);
4544 ptr += len;
4547 pAfterOTIBlks = ptr;
4549 /* Skip this WORD and get the next DWORD */
4550 len = *(DWORD*)(pAfterOTIBlks + 2);
4552 /* Now add this to pLibBLk look at what we're pointing at and
4553 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4554 dust and we should be pointing at the beginning of the name
4555 table */
4557 pNameTable = (char*)pLibBlk + len;
4559 switch(*(WORD*)pNameTable) {
4560 case 0xffff:
4561 break;
4562 case 0x0200:
4563 pNameTable += 0x20;
4564 break;
4565 default:
4566 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4567 break;
4570 pNameTable += 0x216;
4572 pNameTable += 2;
4574 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4576 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4579 /* Hopefully we now have enough ptrs set up to actually read in
4580 some TypeInfos. It's not clear which order to do them in, so
4581 I'll just follow the links along the BlkEntry chain and read
4582 them in the order in which they are in the file */
4584 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4585 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4587 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4588 pBlkEntry[order].next != 0;
4589 order = pBlkEntry[order].next - 1, i++) {
4591 SLTG_TypeInfoHeader *pTIHeader;
4592 SLTG_TypeInfoTail *pTITail;
4593 SLTG_MemberHeader *pMemHeader;
4595 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4596 FIXME_(typelib)("Index strings don't match\n");
4597 heap_free(pOtherTypeInfoBlks);
4598 return NULL;
4601 pTIHeader = pBlk;
4602 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4603 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4604 heap_free(pOtherTypeInfoBlks);
4605 return NULL;
4607 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4608 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4609 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4611 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4612 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4613 (*ppTypeInfoImpl)->index = i;
4614 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4615 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4616 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4617 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4618 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4619 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4620 (*ppTypeInfoImpl)->wTypeFlags =
4621 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4623 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4624 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4626 if((pTIHeader->typeflags1 & 7) != 2)
4627 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4628 if(pTIHeader->typeflags3 != 2)
4629 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4631 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4632 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4633 typekind_desc[pTIHeader->typekind],
4634 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4635 (*ppTypeInfoImpl)->wTypeFlags);
4637 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4639 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4641 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4642 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4643 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4645 switch(pTIHeader->typekind) {
4646 case TKIND_ENUM:
4647 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4648 pTIHeader, pTITail);
4649 break;
4651 case TKIND_RECORD:
4652 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4653 pTIHeader, pTITail);
4654 break;
4656 case TKIND_INTERFACE:
4657 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4658 pTIHeader, pTITail);
4659 break;
4661 case TKIND_COCLASS:
4662 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4663 pTIHeader, pTITail);
4664 break;
4666 case TKIND_ALIAS:
4667 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4668 pTIHeader, pTITail);
4669 break;
4671 case TKIND_DISPATCH:
4672 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4673 pTIHeader, pTITail);
4674 break;
4676 case TKIND_MODULE:
4677 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4678 pTIHeader, pTITail);
4679 break;
4681 default:
4682 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4683 break;
4687 /* could get cFuncs, cVars and cImplTypes from here
4688 but we've already set those */
4689 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4690 X(06);
4691 X(16);
4692 X(18);
4693 X(1a);
4694 X(1e);
4695 X(24);
4696 X(26);
4697 X(2a);
4698 X(2c);
4699 X(2e);
4700 X(30);
4701 X(32);
4702 X(34);
4703 #undef X
4704 ++ppTypeInfoImpl;
4705 pBlk = (char*)pBlk + pBlkEntry[order].len;
4708 if(i != pTypeLibImpl->TypeInfoCount) {
4709 FIXME("Somehow processed %d TypeInfos\n", i);
4710 heap_free(pOtherTypeInfoBlks);
4711 return NULL;
4714 heap_free(pOtherTypeInfoBlks);
4715 return &pTypeLibImpl->ITypeLib2_iface;
4718 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4720 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4722 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4724 if(IsEqualIID(riid, &IID_IUnknown) ||
4725 IsEqualIID(riid,&IID_ITypeLib)||
4726 IsEqualIID(riid,&IID_ITypeLib2))
4728 *ppv = &This->ITypeLib2_iface;
4730 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4731 IsEqualIID(riid, &IID_ICreateTypeLib2))
4733 *ppv = &This->ICreateTypeLib2_iface;
4735 else
4737 *ppv = NULL;
4738 TRACE("-- Interface: E_NOINTERFACE\n");
4739 return E_NOINTERFACE;
4742 IUnknown_AddRef((IUnknown*)*ppv);
4743 return S_OK;
4746 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4748 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4749 ULONG ref = InterlockedIncrement(&This->ref);
4751 TRACE("(%p) ref=%u\n", This, ref);
4753 return ref;
4756 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4758 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4759 ULONG ref = InterlockedDecrement(&This->ref);
4761 TRACE("(%p) ref=%u\n",This, ref);
4763 if (!ref)
4765 TLBImpLib *pImpLib, *pImpLibNext;
4766 TLBRefType *ref_type;
4767 TLBString *tlbstr, *tlbstr_next;
4768 TLBGuid *tlbguid, *tlbguid_next;
4769 void *cursor2;
4770 int i;
4772 /* remove cache entry */
4773 if(This->path)
4775 TRACE("removing from cache list\n");
4776 EnterCriticalSection(&cache_section);
4777 if(This->entry.next)
4778 list_remove(&This->entry);
4779 LeaveCriticalSection(&cache_section);
4780 heap_free(This->path);
4782 TRACE(" destroying ITypeLib(%p)\n",This);
4784 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4785 list_remove(&tlbstr->entry);
4786 SysFreeString(tlbstr->str);
4787 heap_free(tlbstr);
4790 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4791 list_remove(&tlbstr->entry);
4792 SysFreeString(tlbstr->str);
4793 heap_free(tlbstr);
4796 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4797 list_remove(&tlbguid->entry);
4798 heap_free(tlbguid);
4801 TLB_FreeCustData(&This->custdata_list);
4803 for (i = 0; i < This->ctTypeDesc; i++)
4804 if (This->pTypeDesc[i].vt == VT_CARRAY)
4805 heap_free(This->pTypeDesc[i].u.lpadesc);
4807 heap_free(This->pTypeDesc);
4809 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4811 if (pImpLib->pImpTypeLib)
4812 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4813 SysFreeString(pImpLib->name);
4815 list_remove(&pImpLib->entry);
4816 heap_free(pImpLib);
4819 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4821 list_remove(&ref_type->entry);
4822 heap_free(ref_type);
4825 for (i = 0; i < This->TypeInfoCount; ++i){
4826 heap_free(This->typeinfos[i]->tdescAlias);
4827 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4829 heap_free(This->typeinfos);
4830 heap_free(This);
4831 return 0;
4834 return ref;
4837 /* ITypeLib::GetTypeInfoCount
4839 * Returns the number of type descriptions in the type library
4841 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4843 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4844 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4845 return This->TypeInfoCount;
4848 /* ITypeLib::GetTypeInfo
4850 * retrieves the specified type description in the library.
4852 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4853 ITypeLib2 *iface,
4854 UINT index,
4855 ITypeInfo **ppTInfo)
4857 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4859 TRACE("%p %u %p\n", This, index, ppTInfo);
4861 if(!ppTInfo)
4862 return E_INVALIDARG;
4864 if(index >= This->TypeInfoCount)
4865 return TYPE_E_ELEMENTNOTFOUND;
4867 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4868 ITypeInfo_AddRef(*ppTInfo);
4870 return S_OK;
4874 /* ITypeLibs::GetTypeInfoType
4876 * Retrieves the type of a type description.
4878 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4879 ITypeLib2 *iface,
4880 UINT index,
4881 TYPEKIND *pTKind)
4883 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4885 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4887 if(!pTKind)
4888 return E_INVALIDARG;
4890 if(index >= This->TypeInfoCount)
4891 return TYPE_E_ELEMENTNOTFOUND;
4893 *pTKind = This->typeinfos[index]->typekind;
4895 return S_OK;
4898 /* ITypeLib::GetTypeInfoOfGuid
4900 * Retrieves the type description that corresponds to the specified GUID.
4903 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4904 ITypeLib2 *iface,
4905 REFGUID guid,
4906 ITypeInfo **ppTInfo)
4908 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4909 int i;
4911 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4913 for(i = 0; i < This->TypeInfoCount; ++i){
4914 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4915 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4916 ITypeInfo_AddRef(*ppTInfo);
4917 return S_OK;
4921 return TYPE_E_ELEMENTNOTFOUND;
4924 /* ITypeLib::GetLibAttr
4926 * Retrieves the structure that contains the library's attributes.
4929 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4930 ITypeLib2 *iface,
4931 LPTLIBATTR *attr)
4933 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4935 TRACE("(%p, %p)\n", This, attr);
4937 if (!attr) return E_INVALIDARG;
4939 *attr = heap_alloc(sizeof(**attr));
4940 if (!*attr) return E_OUTOFMEMORY;
4942 (*attr)->guid = *TLB_get_guid_null(This->guid);
4943 (*attr)->lcid = This->set_lcid;
4944 (*attr)->syskind = This->syskind;
4945 (*attr)->wMajorVerNum = This->ver_major;
4946 (*attr)->wMinorVerNum = This->ver_minor;
4947 (*attr)->wLibFlags = This->libflags;
4949 return S_OK;
4952 /* ITypeLib::GetTypeComp
4954 * Enables a client compiler to bind to a library's types, variables,
4955 * constants, and global functions.
4958 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4959 ITypeLib2 *iface,
4960 ITypeComp **ppTComp)
4962 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4964 TRACE("(%p)->(%p)\n",This,ppTComp);
4965 *ppTComp = &This->ITypeComp_iface;
4966 ITypeComp_AddRef(*ppTComp);
4968 return S_OK;
4971 /* ITypeLib::GetDocumentation
4973 * Retrieves the library's documentation string, the complete Help file name
4974 * and path, and the context identifier for the library Help topic in the Help
4975 * file.
4977 * On a successful return all non-null BSTR pointers will have been set,
4978 * possibly to NULL.
4980 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4981 ITypeLib2 *iface,
4982 INT index,
4983 BSTR *pBstrName,
4984 BSTR *pBstrDocString,
4985 DWORD *pdwHelpContext,
4986 BSTR *pBstrHelpFile)
4988 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4989 HRESULT result = E_INVALIDARG;
4990 ITypeInfo *pTInfo;
4992 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4993 This, index,
4994 pBstrName, pBstrDocString,
4995 pdwHelpContext, pBstrHelpFile);
4997 if(index<0)
4999 /* documentation for the typelib */
5000 if(pBstrName)
5002 if (This->Name)
5004 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
5005 goto memerr1;
5007 else
5008 *pBstrName = NULL;
5010 if(pBstrDocString)
5012 if (This->DocString)
5014 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
5015 goto memerr2;
5017 else
5018 *pBstrDocString = NULL;
5020 if(pdwHelpContext)
5022 *pdwHelpContext = This->dwHelpContext;
5024 if(pBstrHelpFile)
5026 if (This->HelpFile)
5028 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5029 goto memerr3;
5031 else
5032 *pBstrHelpFile = NULL;
5035 result = S_OK;
5037 else
5039 /* for a typeinfo */
5040 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5042 if(SUCCEEDED(result))
5044 result = ITypeInfo_GetDocumentation(pTInfo,
5045 MEMBERID_NIL,
5046 pBstrName,
5047 pBstrDocString,
5048 pdwHelpContext, pBstrHelpFile);
5050 ITypeInfo_Release(pTInfo);
5053 return result;
5054 memerr3:
5055 if (pBstrDocString) SysFreeString (*pBstrDocString);
5056 memerr2:
5057 if (pBstrName) SysFreeString (*pBstrName);
5058 memerr1:
5059 return STG_E_INSUFFICIENTMEMORY;
5062 /* ITypeLib::IsName
5064 * Indicates whether a passed-in string contains the name of a type or member
5065 * described in the library.
5068 static HRESULT WINAPI ITypeLib2_fnIsName(
5069 ITypeLib2 *iface,
5070 LPOLESTR szNameBuf,
5071 ULONG lHashVal,
5072 BOOL *pfName)
5074 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5075 int tic;
5076 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5078 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5079 pfName);
5081 *pfName=TRUE;
5082 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5083 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5084 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5085 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5086 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5087 int pc;
5088 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5089 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5090 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5091 goto ITypeLib2_fnIsName_exit;
5094 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
5095 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5096 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5100 *pfName=FALSE;
5102 ITypeLib2_fnIsName_exit:
5103 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5104 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5106 return S_OK;
5109 /* ITypeLib::FindName
5111 * Finds occurrences of a type description in a type library. This may be used
5112 * to quickly verify that a name exists in a type library.
5115 static HRESULT WINAPI ITypeLib2_fnFindName(
5116 ITypeLib2 *iface,
5117 LPOLESTR name,
5118 ULONG hash,
5119 ITypeInfo **ppTInfo,
5120 MEMBERID *memid,
5121 UINT16 *found)
5123 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5124 int tic;
5125 UINT count = 0;
5126 UINT len;
5128 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5130 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5131 return E_INVALIDARG;
5133 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5134 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5135 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5136 TLBVarDesc *var;
5137 UINT fdc;
5139 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5140 memid[count] = MEMBERID_NIL;
5141 goto ITypeLib2_fnFindName_exit;
5144 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5145 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5147 if(!TLB_str_memcmp(name, func->Name, len)) {
5148 memid[count] = func->funcdesc.memid;
5149 goto ITypeLib2_fnFindName_exit;
5153 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
5154 if (var) {
5155 memid[count] = var->vardesc.memid;
5156 goto ITypeLib2_fnFindName_exit;
5159 continue;
5160 ITypeLib2_fnFindName_exit:
5161 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5162 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5163 count++;
5165 TRACE("found %d typeinfos\n", count);
5167 *found = count;
5169 return S_OK;
5172 /* ITypeLib::ReleaseTLibAttr
5174 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5177 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5178 ITypeLib2 *iface,
5179 TLIBATTR *pTLibAttr)
5181 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5182 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5183 heap_free(pTLibAttr);
5186 /* ITypeLib2::GetCustData
5188 * gets the custom data
5190 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5191 ITypeLib2 * iface,
5192 REFGUID guid,
5193 VARIANT *pVarVal)
5195 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5196 TLBCustData *pCData;
5198 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5200 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5201 if(!pCData)
5202 return TYPE_E_ELEMENTNOTFOUND;
5204 VariantInit(pVarVal);
5205 VariantCopy(pVarVal, &pCData->data);
5207 return S_OK;
5210 /* ITypeLib2::GetLibStatistics
5212 * Returns statistics about a type library that are required for efficient
5213 * sizing of hash tables.
5216 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5217 ITypeLib2 * iface,
5218 ULONG *pcUniqueNames,
5219 ULONG *pcchUniqueNames)
5221 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5223 FIXME("(%p): stub!\n", This);
5225 if(pcUniqueNames) *pcUniqueNames=1;
5226 if(pcchUniqueNames) *pcchUniqueNames=1;
5227 return S_OK;
5230 /* ITypeLib2::GetDocumentation2
5232 * Retrieves the library's documentation string, the complete Help file name
5233 * and path, the localization context to use, and the context ID for the
5234 * library Help topic in the Help file.
5237 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5238 ITypeLib2 * iface,
5239 INT index,
5240 LCID lcid,
5241 BSTR *pbstrHelpString,
5242 DWORD *pdwHelpStringContext,
5243 BSTR *pbstrHelpStringDll)
5245 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5246 HRESULT result;
5247 ITypeInfo *pTInfo;
5249 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5251 /* the help string should be obtained from the helpstringdll,
5252 * using the _DLLGetDocumentation function, based on the supplied
5253 * lcid. Nice to do sometime...
5255 if(index<0)
5257 /* documentation for the typelib */
5258 if(pbstrHelpString)
5259 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5260 if(pdwHelpStringContext)
5261 *pdwHelpStringContext=This->dwHelpContext;
5262 if(pbstrHelpStringDll)
5263 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5265 result = S_OK;
5267 else
5269 /* for a typeinfo */
5270 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5272 if(SUCCEEDED(result))
5274 ITypeInfo2 * pTInfo2;
5275 result = ITypeInfo_QueryInterface(pTInfo,
5276 &IID_ITypeInfo2,
5277 (LPVOID*) &pTInfo2);
5279 if(SUCCEEDED(result))
5281 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5282 MEMBERID_NIL,
5283 lcid,
5284 pbstrHelpString,
5285 pdwHelpStringContext,
5286 pbstrHelpStringDll);
5288 ITypeInfo2_Release(pTInfo2);
5291 ITypeInfo_Release(pTInfo);
5294 return result;
5297 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5299 TLBCustData *pCData;
5300 unsigned int ct;
5301 CUSTDATAITEM *cdi;
5303 ct = list_count(custdata_list);
5305 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5306 if(!pCustData->prgCustData)
5307 return E_OUTOFMEMORY;
5309 pCustData->cCustData = ct;
5311 cdi = pCustData->prgCustData;
5312 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5313 cdi->guid = *TLB_get_guid_null(pCData->guid);
5314 VariantCopy(&cdi->varValue, &pCData->data);
5315 ++cdi;
5318 return S_OK;
5322 /* ITypeLib2::GetAllCustData
5324 * Gets all custom data items for the library.
5327 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5328 ITypeLib2 * iface,
5329 CUSTDATA *pCustData)
5331 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5332 TRACE("(%p)->(%p)\n", This, pCustData);
5333 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5336 static const ITypeLib2Vtbl tlbvt = {
5337 ITypeLib2_fnQueryInterface,
5338 ITypeLib2_fnAddRef,
5339 ITypeLib2_fnRelease,
5340 ITypeLib2_fnGetTypeInfoCount,
5341 ITypeLib2_fnGetTypeInfo,
5342 ITypeLib2_fnGetTypeInfoType,
5343 ITypeLib2_fnGetTypeInfoOfGuid,
5344 ITypeLib2_fnGetLibAttr,
5345 ITypeLib2_fnGetTypeComp,
5346 ITypeLib2_fnGetDocumentation,
5347 ITypeLib2_fnIsName,
5348 ITypeLib2_fnFindName,
5349 ITypeLib2_fnReleaseTLibAttr,
5351 ITypeLib2_fnGetCustData,
5352 ITypeLib2_fnGetLibStatistics,
5353 ITypeLib2_fnGetDocumentation2,
5354 ITypeLib2_fnGetAllCustData
5358 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5360 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5362 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5365 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5367 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5369 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5372 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5374 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5376 return ITypeLib2_Release(&This->ITypeLib2_iface);
5379 static HRESULT WINAPI ITypeLibComp_fnBind(
5380 ITypeComp * iface,
5381 OLECHAR * szName,
5382 ULONG lHash,
5383 WORD wFlags,
5384 ITypeInfo ** ppTInfo,
5385 DESCKIND * pDescKind,
5386 BINDPTR * pBindPtr)
5388 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5389 BOOL typemismatch = FALSE;
5390 int i;
5392 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5394 *pDescKind = DESCKIND_NONE;
5395 pBindPtr->lptcomp = NULL;
5396 *ppTInfo = NULL;
5398 for(i = 0; i < This->TypeInfoCount; ++i){
5399 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5400 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5402 /* FIXME: check wFlags here? */
5403 /* FIXME: we should use a hash table to look this info up using lHash
5404 * instead of an O(n) search */
5405 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5406 (pTypeInfo->typekind == TKIND_MODULE))
5408 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5410 *pDescKind = DESCKIND_TYPECOMP;
5411 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5412 ITypeComp_AddRef(pBindPtr->lptcomp);
5413 TRACE("module or enum: %s\n", debugstr_w(szName));
5414 return S_OK;
5418 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5419 (pTypeInfo->typekind == TKIND_ENUM))
5421 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5422 HRESULT hr;
5424 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5425 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5427 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5428 return S_OK;
5430 else if (hr == TYPE_E_TYPEMISMATCH)
5431 typemismatch = TRUE;
5434 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5435 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5437 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5438 HRESULT hr;
5439 ITypeInfo *subtypeinfo;
5440 BINDPTR subbindptr;
5441 DESCKIND subdesckind;
5443 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5444 &subtypeinfo, &subdesckind, &subbindptr);
5445 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5447 TYPEDESC tdesc_appobject;
5448 const VARDESC vardesc_appobject =
5450 -2, /* memid */
5451 NULL, /* lpstrSchema */
5453 0 /* oInst */
5456 /* ELEMDESC */
5458 /* TYPEDESC */
5460 &tdesc_appobject
5462 VT_PTR
5465 0, /* wVarFlags */
5466 VAR_STATIC /* varkind */
5469 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5470 tdesc_appobject.vt = VT_USERDEFINED;
5472 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5474 /* cleanup things filled in by Bind call so we can put our
5475 * application object data in there instead */
5476 switch (subdesckind)
5478 case DESCKIND_FUNCDESC:
5479 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5480 break;
5481 case DESCKIND_VARDESC:
5482 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5483 break;
5484 default:
5485 break;
5487 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5489 if (pTypeInfo->hreftype == -1)
5490 FIXME("no hreftype for interface %p\n", pTypeInfo);
5492 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5493 if (FAILED(hr))
5494 return hr;
5496 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5497 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5498 ITypeInfo_AddRef(*ppTInfo);
5499 return S_OK;
5501 else if (hr == TYPE_E_TYPEMISMATCH)
5502 typemismatch = TRUE;
5506 if (typemismatch)
5508 TRACE("type mismatch %s\n", debugstr_w(szName));
5509 return TYPE_E_TYPEMISMATCH;
5511 else
5513 TRACE("name not found %s\n", debugstr_w(szName));
5514 return S_OK;
5518 static HRESULT WINAPI ITypeLibComp_fnBindType(
5519 ITypeComp * iface,
5520 OLECHAR * szName,
5521 ULONG lHash,
5522 ITypeInfo ** ppTInfo,
5523 ITypeComp ** ppTComp)
5525 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5526 ITypeInfoImpl *info;
5528 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5530 if(!szName || !ppTInfo || !ppTComp)
5531 return E_INVALIDARG;
5533 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5534 if(!info){
5535 *ppTInfo = NULL;
5536 *ppTComp = NULL;
5537 return S_OK;
5540 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5541 ITypeInfo_AddRef(*ppTInfo);
5542 *ppTComp = &info->ITypeComp_iface;
5543 ITypeComp_AddRef(*ppTComp);
5545 return S_OK;
5548 static const ITypeCompVtbl tlbtcvt =
5551 ITypeLibComp_fnQueryInterface,
5552 ITypeLibComp_fnAddRef,
5553 ITypeLibComp_fnRelease,
5555 ITypeLibComp_fnBind,
5556 ITypeLibComp_fnBindType
5559 /*================== ITypeInfo(2) Methods ===================================*/
5560 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5562 ITypeInfoImpl *pTypeInfoImpl;
5564 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5565 if (pTypeInfoImpl)
5567 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5568 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5569 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5570 pTypeInfoImpl->ref = 0;
5571 pTypeInfoImpl->hreftype = -1;
5572 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5573 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5574 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5575 list_init(pTypeInfoImpl->pcustdata_list);
5577 TRACE("(%p)\n", pTypeInfoImpl);
5578 return pTypeInfoImpl;
5581 /* ITypeInfo::QueryInterface
5583 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5584 ITypeInfo2 *iface,
5585 REFIID riid,
5586 VOID **ppvObject)
5588 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5590 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5592 *ppvObject=NULL;
5593 if(IsEqualIID(riid, &IID_IUnknown) ||
5594 IsEqualIID(riid,&IID_ITypeInfo)||
5595 IsEqualIID(riid,&IID_ITypeInfo2))
5596 *ppvObject = This;
5597 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5598 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5599 *ppvObject = &This->ICreateTypeInfo2_iface;
5601 if(*ppvObject){
5602 ITypeInfo2_AddRef(iface);
5603 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5604 return S_OK;
5606 TRACE("-- Interface: E_NOINTERFACE\n");
5607 return E_NOINTERFACE;
5610 /* ITypeInfo::AddRef
5612 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5614 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5615 ULONG ref = InterlockedIncrement(&This->ref);
5617 TRACE("(%p)->ref is %u\n",This, ref);
5619 if (ref == 1 /* incremented from 0 */)
5620 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5622 return ref;
5625 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5627 UINT i;
5629 TRACE("destroying ITypeInfo(%p)\n",This);
5631 for (i = 0; i < This->cFuncs; ++i)
5633 int j;
5634 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5635 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5637 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5638 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5639 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5640 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5642 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5643 heap_free(pFInfo->pParamDesc);
5644 TLB_FreeCustData(&pFInfo->custdata_list);
5646 heap_free(This->funcdescs);
5648 for(i = 0; i < This->cVars; ++i)
5650 TLBVarDesc *pVInfo = &This->vardescs[i];
5651 if (pVInfo->vardesc_create) {
5652 TLB_FreeVarDesc(pVInfo->vardesc_create);
5653 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5654 VariantClear(pVInfo->vardesc.u.lpvarValue);
5655 heap_free(pVInfo->vardesc.u.lpvarValue);
5657 TLB_FreeCustData(&pVInfo->custdata_list);
5659 heap_free(This->vardescs);
5661 if(This->impltypes){
5662 for (i = 0; i < This->cImplTypes; ++i){
5663 TLBImplType *pImpl = &This->impltypes[i];
5664 TLB_FreeCustData(&pImpl->custdata_list);
5666 heap_free(This->impltypes);
5669 TLB_FreeCustData(&This->custdata_list);
5671 heap_free(This);
5674 /* ITypeInfo::Release
5676 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5678 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5679 ULONG ref = InterlockedDecrement(&This->ref);
5681 TRACE("(%p)->(%u)\n",This, ref);
5683 if (!ref)
5685 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5686 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5687 if (not_attached_to_typelib)
5688 heap_free(This);
5689 /* otherwise This will be freed when typelib is freed */
5692 return ref;
5695 /* ITypeInfo::GetTypeAttr
5697 * Retrieves a TYPEATTR structure that contains the attributes of the type
5698 * description.
5701 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5702 LPTYPEATTR *ppTypeAttr)
5704 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5705 SIZE_T size;
5707 TRACE("(%p)\n",This);
5709 size = sizeof(**ppTypeAttr);
5710 if (This->typekind == TKIND_ALIAS && This->tdescAlias)
5711 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5713 *ppTypeAttr = heap_alloc(size);
5714 if (!*ppTypeAttr)
5715 return E_OUTOFMEMORY;
5717 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5718 (*ppTypeAttr)->lcid = This->lcid;
5719 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5720 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5721 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5722 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5723 (*ppTypeAttr)->typekind = This->typekind;
5724 (*ppTypeAttr)->cFuncs = This->cFuncs;
5725 (*ppTypeAttr)->cVars = This->cVars;
5726 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5727 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5728 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5729 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5730 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5731 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5732 (*ppTypeAttr)->idldescType = This->idldescType;
5734 if (This->tdescAlias)
5735 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5736 This->tdescAlias, *ppTypeAttr + 1);
5737 else{
5738 (*ppTypeAttr)->tdescAlias.vt = VT_EMPTY;
5739 (*ppTypeAttr)->tdescAlias.u.lptdesc = NULL;
5742 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5743 /* This should include all the inherited funcs */
5744 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5745 /* This is always the size of IDispatch's vtbl */
5746 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5747 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5749 return S_OK;
5752 /* ITypeInfo::GetTypeComp
5754 * Retrieves the ITypeComp interface for the type description, which enables a
5755 * client compiler to bind to the type description's members.
5758 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5759 ITypeComp * *ppTComp)
5761 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5763 TRACE("(%p)->(%p)\n", This, ppTComp);
5765 *ppTComp = &This->ITypeComp_iface;
5766 ITypeComp_AddRef(*ppTComp);
5767 return S_OK;
5770 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5772 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5773 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5774 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5775 return size;
5778 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5780 *dest = *src;
5781 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5782 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5784 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5785 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5786 *buffer += sizeof(PARAMDESCEX);
5787 *pparamdescex_dest = *pparamdescex_src;
5788 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5789 VariantInit(&pparamdescex_dest->varDefaultValue);
5790 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5791 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5793 else
5794 dest->u.paramdesc.pparamdescex = NULL;
5795 return S_OK;
5798 static HRESULT TLB_SanitizeBSTR(BSTR str)
5800 UINT len = SysStringLen(str), i;
5801 for (i = 0; i < len; ++i)
5802 if (str[i] > 0x7f)
5803 str[i] = '?';
5804 return S_OK;
5807 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5809 if (V_VT(var) == VT_INT)
5810 return VariantChangeType(var, var, 0, VT_I4);
5811 else if (V_VT(var) == VT_UINT)
5812 return VariantChangeType(var, var, 0, VT_UI4);
5813 else if (V_VT(var) == VT_BSTR)
5814 return TLB_SanitizeBSTR(V_BSTR(var));
5816 return S_OK;
5819 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5821 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5822 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5825 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5827 FUNCDESC *dest;
5828 char *buffer;
5829 SIZE_T size = sizeof(*src);
5830 SHORT i;
5831 HRESULT hr;
5833 size += sizeof(*src->lprgscode) * src->cScodes;
5834 size += TLB_SizeElemDesc(&src->elemdescFunc);
5835 for (i = 0; i < src->cParams; i++)
5837 size += sizeof(ELEMDESC);
5838 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5841 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5842 if (!dest) return E_OUTOFMEMORY;
5844 *dest = *src;
5845 if (dispinterface) /* overwrite funckind */
5846 dest->funckind = FUNC_DISPATCH;
5847 buffer = (char *)(dest + 1);
5849 dest->oVft = dest->oVft & 0xFFFC;
5851 if (dest->cScodes) {
5852 dest->lprgscode = (SCODE *)buffer;
5853 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5854 buffer += sizeof(*src->lprgscode) * src->cScodes;
5855 } else
5856 dest->lprgscode = NULL;
5858 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5859 if (FAILED(hr))
5861 SysFreeString((BSTR)dest);
5862 return hr;
5865 if (dest->cParams) {
5866 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5867 buffer += sizeof(ELEMDESC) * src->cParams;
5868 for (i = 0; i < src->cParams; i++)
5870 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5871 if (FAILED(hr))
5872 break;
5874 if (FAILED(hr))
5876 /* undo the above actions */
5877 for (i = i - 1; i >= 0; i--)
5878 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5879 TLB_FreeElemDesc(&dest->elemdescFunc);
5880 SysFreeString((BSTR)dest);
5881 return hr;
5883 } else
5884 dest->lprgelemdescParam = NULL;
5886 /* special treatment for dispinterfaces: this makes functions appear
5887 * to return their [retval] value when it is really returning an
5888 * HRESULT */
5889 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5891 if (dest->cParams &&
5892 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5894 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5895 if (elemdesc->tdesc.vt != VT_PTR)
5897 ERR("elemdesc should have started with VT_PTR instead of:\n");
5898 if (ERR_ON(ole))
5899 dump_ELEMDESC(elemdesc);
5900 return E_UNEXPECTED;
5903 /* copy last parameter to the return value. we are using a flat
5904 * buffer so there is no danger of leaking memory in
5905 * elemdescFunc */
5906 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5908 /* remove the last parameter */
5909 dest->cParams--;
5911 else
5912 /* otherwise this function is made to appear to have no return
5913 * value */
5914 dest->elemdescFunc.tdesc.vt = VT_VOID;
5918 *dest_ptr = dest;
5919 return S_OK;
5922 static void TLB_FreeVarDesc(VARDESC *var_desc)
5924 TLB_FreeElemDesc(&var_desc->elemdescVar);
5925 if (var_desc->varkind == VAR_CONST)
5926 VariantClear(var_desc->u.lpvarValue);
5927 SysFreeString((BSTR)var_desc);
5930 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5932 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5934 if (index >= This->cFuncs)
5935 return TYPE_E_ELEMENTNOTFOUND;
5937 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5938 return S_OK;
5941 /* internal function to make the inherited interfaces' methods appear
5942 * part of the interface */
5943 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5944 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5946 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5947 HRESULT hr;
5948 UINT implemented_funcs = 0;
5950 if (funcs)
5951 *funcs = 0;
5952 else
5953 *hrefoffset = DISPATCH_HREF_OFFSET;
5955 if(This->impltypes)
5957 ITypeInfo *pSubTypeInfo;
5958 UINT sub_funcs;
5960 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5961 if (FAILED(hr))
5962 return hr;
5964 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5965 index,
5966 ppFuncDesc,
5967 &sub_funcs, hrefoffset);
5968 implemented_funcs += sub_funcs;
5969 ITypeInfo_Release(pSubTypeInfo);
5970 if (SUCCEEDED(hr))
5971 return hr;
5972 *hrefoffset += DISPATCH_HREF_OFFSET;
5975 if (funcs)
5976 *funcs = implemented_funcs + This->cFuncs;
5977 else
5978 *hrefoffset = 0;
5980 if (index < implemented_funcs)
5981 return E_INVALIDARG;
5982 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5983 ppFuncDesc);
5986 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5988 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5989 while (TRUE)
5991 switch (pTypeDesc->vt)
5993 case VT_USERDEFINED:
5994 pTypeDesc->u.hreftype += hrefoffset;
5995 return;
5996 case VT_PTR:
5997 case VT_SAFEARRAY:
5998 pTypeDesc = pTypeDesc->u.lptdesc;
5999 break;
6000 case VT_CARRAY:
6001 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
6002 break;
6003 default:
6004 return;
6009 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
6011 SHORT i;
6012 for (i = 0; i < pFuncDesc->cParams; i++)
6013 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
6014 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
6017 /* ITypeInfo::GetFuncDesc
6019 * Retrieves the FUNCDESC structure that contains information about a
6020 * specified function.
6023 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
6024 LPFUNCDESC *ppFuncDesc)
6026 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6027 const FUNCDESC *internal_funcdesc;
6028 HRESULT hr;
6029 UINT hrefoffset = 0;
6031 TRACE("(%p) index %d\n", This, index);
6033 if (!ppFuncDesc)
6034 return E_INVALIDARG;
6036 if (This->needs_layout)
6037 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6039 if (This->typekind == TKIND_DISPATCH)
6040 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6041 &internal_funcdesc, NULL,
6042 &hrefoffset);
6043 else
6044 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6045 &internal_funcdesc);
6046 if (FAILED(hr))
6048 WARN("description for function %d not found\n", index);
6049 return hr;
6052 hr = TLB_AllocAndInitFuncDesc(
6053 internal_funcdesc,
6054 ppFuncDesc,
6055 This->typekind == TKIND_DISPATCH);
6057 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
6058 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6060 TRACE("-- 0x%08x\n", hr);
6061 return hr;
6064 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6066 VARDESC *dest;
6067 char *buffer;
6068 SIZE_T size = sizeof(*src);
6069 HRESULT hr;
6071 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6072 if (src->varkind == VAR_CONST)
6073 size += sizeof(VARIANT);
6074 size += TLB_SizeElemDesc(&src->elemdescVar);
6076 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6077 if (!dest) return E_OUTOFMEMORY;
6079 *dest = *src;
6080 buffer = (char *)(dest + 1);
6081 if (src->lpstrSchema)
6083 int len;
6084 dest->lpstrSchema = (LPOLESTR)buffer;
6085 len = strlenW(src->lpstrSchema);
6086 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6087 buffer += (len + 1) * sizeof(WCHAR);
6090 if (src->varkind == VAR_CONST)
6092 HRESULT hr;
6094 dest->u.lpvarValue = (VARIANT *)buffer;
6095 *dest->u.lpvarValue = *src->u.lpvarValue;
6096 buffer += sizeof(VARIANT);
6097 VariantInit(dest->u.lpvarValue);
6098 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6099 if (FAILED(hr))
6101 SysFreeString((BSTR)dest);
6102 return hr;
6105 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6106 if (FAILED(hr))
6108 if (src->varkind == VAR_CONST)
6109 VariantClear(dest->u.lpvarValue);
6110 SysFreeString((BSTR)dest);
6111 return hr;
6113 *dest_ptr = dest;
6114 return S_OK;
6117 /* ITypeInfo::GetVarDesc
6119 * Retrieves a VARDESC structure that describes the specified variable.
6122 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6123 LPVARDESC *ppVarDesc)
6125 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6126 const TLBVarDesc *pVDesc = &This->vardescs[index];
6128 TRACE("(%p) index %d\n", This, index);
6130 if(index >= This->cVars)
6131 return TYPE_E_ELEMENTNOTFOUND;
6133 if (This->needs_layout)
6134 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6136 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6139 /* ITypeInfo_GetNames
6141 * Retrieves the variable with the specified member ID (or the name of the
6142 * property or method and its parameters) that correspond to the specified
6143 * function ID.
6145 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6146 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6148 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6149 const TLBFuncDesc *pFDesc;
6150 const TLBVarDesc *pVDesc;
6151 int i;
6152 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6154 if(!rgBstrNames)
6155 return E_INVALIDARG;
6157 *pcNames = 0;
6159 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
6160 if(pFDesc)
6162 if(!cMaxNames || !pFDesc->Name)
6163 return S_OK;
6165 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6166 ++(*pcNames);
6168 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6169 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6170 return S_OK;
6171 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6172 ++(*pcNames);
6174 return S_OK;
6177 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
6178 if(pVDesc)
6180 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6181 *pcNames=1;
6183 else
6185 if(This->impltypes &&
6186 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
6187 /* recursive search */
6188 ITypeInfo *pTInfo;
6189 HRESULT result;
6190 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6191 if(SUCCEEDED(result))
6193 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6194 ITypeInfo_Release(pTInfo);
6195 return result;
6197 WARN("Could not search inherited interface!\n");
6199 else
6201 WARN("no names found\n");
6203 *pcNames=0;
6204 return TYPE_E_ELEMENTNOTFOUND;
6206 return S_OK;
6210 /* ITypeInfo::GetRefTypeOfImplType
6212 * If a type description describes a COM class, it retrieves the type
6213 * description of the implemented interface types. For an interface,
6214 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6215 * if any exist.
6218 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6219 ITypeInfo2 *iface,
6220 UINT index,
6221 HREFTYPE *pRefType)
6223 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6224 HRESULT hr = S_OK;
6226 TRACE("(%p) index %d\n", This, index);
6227 if (TRACE_ON(ole)) dump_TypeInfo(This);
6229 if(index==(UINT)-1)
6231 /* only valid on dual interfaces;
6232 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6235 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6237 *pRefType = -2;
6239 else
6241 hr = TYPE_E_ELEMENTNOTFOUND;
6244 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6246 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6247 *pRefType = This->pTypeLib->dispatch_href;
6249 else
6251 if(index >= This->cImplTypes)
6252 hr = TYPE_E_ELEMENTNOTFOUND;
6253 else{
6254 *pRefType = This->impltypes[index].hRef;
6255 if(This->typekind == TKIND_INTERFACE)
6256 *pRefType |= 0x2;
6260 if(TRACE_ON(ole))
6262 if(SUCCEEDED(hr))
6263 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6264 else
6265 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6268 return hr;
6271 /* ITypeInfo::GetImplTypeFlags
6273 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6274 * or base interface in a type description.
6276 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6277 UINT index, INT *pImplTypeFlags)
6279 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6281 TRACE("(%p) index %d\n", This, index);
6283 if(!pImplTypeFlags)
6284 return E_INVALIDARG;
6286 if(This->typekind == TKIND_DISPATCH && index == 0){
6287 *pImplTypeFlags = 0;
6288 return S_OK;
6291 if(index >= This->cImplTypes)
6292 return TYPE_E_ELEMENTNOTFOUND;
6294 *pImplTypeFlags = This->impltypes[index].implflags;
6296 return S_OK;
6299 /* GetIDsOfNames
6300 * Maps between member names and member IDs, and parameter names and
6301 * parameter IDs.
6303 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6304 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6306 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6307 const TLBVarDesc *pVDesc;
6308 HRESULT ret=S_OK;
6309 UINT i, fdc;
6311 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6312 cNames);
6314 /* init out parameters in case of failure */
6315 for (i = 0; i < cNames; i++)
6316 pMemId[i] = MEMBERID_NIL;
6318 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6319 int j;
6320 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6321 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6322 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6323 for(i=1; i < cNames; i++){
6324 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6325 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6326 break;
6327 if( j<pFDesc->funcdesc.cParams)
6328 pMemId[i]=j;
6329 else
6330 ret=DISP_E_UNKNOWNNAME;
6332 TRACE("-- 0x%08x\n", ret);
6333 return ret;
6336 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6337 if(pVDesc){
6338 if(cNames)
6339 *pMemId = pVDesc->vardesc.memid;
6340 return ret;
6342 /* not found, see if it can be found in an inherited interface */
6343 if(This->impltypes) {
6344 /* recursive search */
6345 ITypeInfo *pTInfo;
6346 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6347 if(SUCCEEDED(ret)){
6348 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6349 ITypeInfo_Release(pTInfo);
6350 return ret;
6352 WARN("Could not search inherited interface!\n");
6353 } else
6354 WARN("no names found\n");
6355 return DISP_E_UNKNOWNNAME;
6359 #ifdef __i386__
6361 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6362 __ASM_GLOBAL_FUNC( call_method,
6363 "pushl %ebp\n\t"
6364 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6365 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6366 "movl %esp,%ebp\n\t"
6367 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6368 "pushl %esi\n\t"
6369 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6370 "pushl %edi\n\t"
6371 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6372 "movl 12(%ebp),%edx\n\t"
6373 "movl %esp,%edi\n\t"
6374 "shll $2,%edx\n\t"
6375 "jz 1f\n\t"
6376 "subl %edx,%edi\n\t"
6377 "andl $~15,%edi\n\t"
6378 "movl %edi,%esp\n\t"
6379 "movl 12(%ebp),%ecx\n\t"
6380 "movl 16(%ebp),%esi\n\t"
6381 "cld\n\t"
6382 "rep; movsl\n"
6383 "1:\tcall *8(%ebp)\n\t"
6384 "subl %esp,%edi\n\t"
6385 "movl 20(%ebp),%ecx\n\t"
6386 "movl %edi,(%ecx)\n\t"
6387 "leal -8(%ebp),%esp\n\t"
6388 "popl %edi\n\t"
6389 __ASM_CFI(".cfi_same_value %edi\n\t")
6390 "popl %esi\n\t"
6391 __ASM_CFI(".cfi_same_value %esi\n\t")
6392 "popl %ebp\n\t"
6393 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6394 __ASM_CFI(".cfi_same_value %ebp\n\t")
6395 "ret" )
6397 /* same function but returning floating point */
6398 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6400 /* ITypeInfo::Invoke
6402 * Invokes a method, or accesses a property of an object, that implements the
6403 * interface described by the type description.
6405 DWORD
6406 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6407 DWORD res;
6408 int stack_offset;
6410 if (TRACE_ON(ole)) {
6411 int i;
6412 TRACE("Calling %p(",func);
6413 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6414 if (nrargs > 30) TRACE("...");
6415 TRACE(")\n");
6418 switch (callconv) {
6419 case CC_STDCALL:
6420 case CC_CDECL:
6421 res = call_method( func, nrargs, args, &stack_offset );
6422 break;
6423 default:
6424 FIXME("unsupported calling convention %d\n",callconv);
6425 res = -1;
6426 break;
6428 TRACE("returns %08x\n",res);
6429 return res;
6432 #elif defined(__x86_64__)
6434 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6435 __ASM_GLOBAL_FUNC( call_method,
6436 "pushq %rbp\n\t"
6437 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6438 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6439 "movq %rsp,%rbp\n\t"
6440 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6441 "pushq %rsi\n\t"
6442 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6443 "pushq %rdi\n\t"
6444 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6445 "movq %rcx,%rax\n\t"
6446 "movq $4,%rcx\n\t"
6447 "cmp %rcx,%rdx\n\t"
6448 "cmovgq %rdx,%rcx\n\t"
6449 "leaq 0(,%rcx,8),%rdx\n\t"
6450 "subq %rdx,%rsp\n\t"
6451 "andq $~15,%rsp\n\t"
6452 "movq %rsp,%rdi\n\t"
6453 "movq %r8,%rsi\n\t"
6454 "rep; movsq\n\t"
6455 "movq 0(%rsp),%rcx\n\t"
6456 "movq 8(%rsp),%rdx\n\t"
6457 "movq 16(%rsp),%r8\n\t"
6458 "movq 24(%rsp),%r9\n\t"
6459 "movq 0(%rsp),%xmm0\n\t"
6460 "movq 8(%rsp),%xmm1\n\t"
6461 "movq 16(%rsp),%xmm2\n\t"
6462 "movq 24(%rsp),%xmm3\n\t"
6463 "callq *%rax\n\t"
6464 "leaq -16(%rbp),%rsp\n\t"
6465 "popq %rdi\n\t"
6466 __ASM_CFI(".cfi_same_value %rdi\n\t")
6467 "popq %rsi\n\t"
6468 __ASM_CFI(".cfi_same_value %rsi\n\t")
6469 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6470 "popq %rbp\n\t"
6471 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6472 __ASM_CFI(".cfi_same_value %rbp\n\t")
6473 "ret")
6475 /* same function but returning floating point */
6476 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6478 #endif /* __x86_64__ */
6480 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6482 HRESULT hr = S_OK;
6483 ITypeInfo *tinfo2 = NULL;
6484 TYPEATTR *tattr = NULL;
6486 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6487 if (hr)
6489 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6490 "hr = 0x%08x\n",
6491 tdesc->u.hreftype, hr);
6492 return hr;
6494 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6495 if (hr)
6497 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6498 ITypeInfo_Release(tinfo2);
6499 return hr;
6502 switch (tattr->typekind)
6504 case TKIND_ENUM:
6505 *vt |= VT_I4;
6506 break;
6508 case TKIND_ALIAS:
6509 tdesc = &tattr->tdescAlias;
6510 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6511 break;
6513 case TKIND_INTERFACE:
6514 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6515 *vt |= VT_DISPATCH;
6516 else
6517 *vt |= VT_UNKNOWN;
6518 break;
6520 case TKIND_DISPATCH:
6521 *vt |= VT_DISPATCH;
6522 break;
6524 case TKIND_COCLASS:
6525 *vt |= VT_DISPATCH;
6526 break;
6528 case TKIND_RECORD:
6529 FIXME("TKIND_RECORD unhandled.\n");
6530 hr = E_NOTIMPL;
6531 break;
6533 case TKIND_UNION:
6534 FIXME("TKIND_UNION unhandled.\n");
6535 hr = E_NOTIMPL;
6536 break;
6538 default:
6539 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6540 hr = E_NOTIMPL;
6541 break;
6543 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6544 ITypeInfo_Release(tinfo2);
6545 return hr;
6548 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6550 HRESULT hr = S_OK;
6552 /* enforce only one level of pointer indirection */
6553 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6555 tdesc = tdesc->u.lptdesc;
6557 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6558 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6559 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6560 if ((tdesc->vt == VT_USERDEFINED) ||
6561 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6563 VARTYPE vt_userdefined = 0;
6564 const TYPEDESC *tdesc_userdefined = tdesc;
6565 if (tdesc->vt == VT_PTR)
6567 vt_userdefined = VT_BYREF;
6568 tdesc_userdefined = tdesc->u.lptdesc;
6570 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6571 if ((hr == S_OK) &&
6572 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6573 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6575 *vt |= vt_userdefined;
6576 return S_OK;
6579 *vt = VT_BYREF;
6582 switch (tdesc->vt)
6584 case VT_HRESULT:
6585 *vt |= VT_ERROR;
6586 break;
6587 case VT_USERDEFINED:
6588 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6589 break;
6590 case VT_VOID:
6591 case VT_CARRAY:
6592 case VT_PTR:
6593 case VT_LPSTR:
6594 case VT_LPWSTR:
6595 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6596 hr = DISP_E_BADVARTYPE;
6597 break;
6598 case VT_SAFEARRAY:
6599 *vt |= VT_ARRAY;
6600 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6601 break;
6602 case VT_INT:
6603 *vt |= VT_I4;
6604 break;
6605 case VT_UINT:
6606 *vt |= VT_UI4;
6607 break;
6608 default:
6609 *vt |= tdesc->vt;
6610 break;
6612 return hr;
6615 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6617 ITypeInfo *tinfo2;
6618 TYPEATTR *tattr;
6619 HRESULT hres;
6621 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6622 if(FAILED(hres))
6623 return hres;
6625 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6626 if(FAILED(hres)) {
6627 ITypeInfo_Release(tinfo2);
6628 return hres;
6631 switch(tattr->typekind) {
6632 case TKIND_ALIAS:
6633 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6634 break;
6636 case TKIND_INTERFACE:
6637 case TKIND_DISPATCH:
6638 *guid = tattr->guid;
6639 break;
6641 default:
6642 ERR("Unexpected typekind %d\n", tattr->typekind);
6643 hres = E_UNEXPECTED;
6646 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6647 ITypeInfo_Release(tinfo2);
6648 return hres;
6651 /***********************************************************************
6652 * DispCallFunc (OLEAUT32.@)
6654 * Invokes a function of the specified calling convention, passing the
6655 * specified arguments and returns the result.
6657 * PARAMS
6658 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6659 * oVft [I] The offset in the vtable. See notes.
6660 * cc [I] Calling convention of the function to call.
6661 * vtReturn [I] The return type of the function.
6662 * cActuals [I] Number of parameters.
6663 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6664 * prgpvarg [I] The arguments to pass.
6665 * pvargResult [O] The return value of the function. Can be NULL.
6667 * RETURNS
6668 * Success: S_OK.
6669 * Failure: HRESULT code.
6671 * NOTES
6672 * The HRESULT return value of this function is not affected by the return
6673 * value of the user supplied function, which is returned in pvargResult.
6675 * If pvInstance is NULL then a non-object function is to be called and oVft
6676 * is the address of the function to call.
6678 * The cc parameter can be one of the following values:
6679 *|CC_FASTCALL
6680 *|CC_CDECL
6681 *|CC_PASCAL
6682 *|CC_STDCALL
6683 *|CC_FPFASTCALL
6684 *|CC_SYSCALL
6685 *|CC_MPWCDECL
6686 *|CC_MPWPASCAL
6689 HRESULT WINAPI
6690 DispCallFunc(
6691 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6692 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6694 #ifdef __i386__
6695 int argspos, stack_offset;
6696 void *func;
6697 UINT i;
6698 DWORD *args;
6700 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6701 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6702 pvargResult, V_VT(pvargResult));
6704 if (cc != CC_STDCALL && cc != CC_CDECL)
6706 FIXME("unsupported calling convention %d\n",cc);
6707 return E_INVALIDARG;
6710 /* maximum size for an argument is sizeof(VARIANT) */
6711 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6713 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6714 argspos = 1;
6715 if (pvInstance)
6717 const FARPROC *vtable = *(FARPROC **)pvInstance;
6718 func = vtable[oVft/sizeof(void *)];
6719 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6721 else func = (void *)oVft;
6723 for (i = 0; i < cActuals; i++)
6725 VARIANT *arg = prgpvarg[i];
6727 switch (prgvt[i])
6729 case VT_EMPTY:
6730 break;
6731 case VT_I8:
6732 case VT_UI8:
6733 case VT_R8:
6734 case VT_DATE:
6735 case VT_CY:
6736 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6737 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6738 break;
6739 case VT_DECIMAL:
6740 case VT_VARIANT:
6741 memcpy( &args[argspos], arg, sizeof(*arg) );
6742 argspos += sizeof(*arg) / sizeof(DWORD);
6743 break;
6744 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6745 args[argspos++] = V_BOOL(arg);
6746 break;
6747 default:
6748 args[argspos++] = V_UI4(arg);
6749 break;
6751 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6754 switch (vtReturn)
6756 case VT_EMPTY:
6757 call_method( func, argspos - 1, args + 1, &stack_offset );
6758 break;
6759 case VT_R4:
6760 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6761 break;
6762 case VT_R8:
6763 case VT_DATE:
6764 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6765 break;
6766 case VT_DECIMAL:
6767 case VT_VARIANT:
6768 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6769 call_method( func, argspos, args, &stack_offset );
6770 break;
6771 case VT_I8:
6772 case VT_UI8:
6773 case VT_CY:
6774 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6775 break;
6776 case VT_HRESULT:
6777 WARN("invalid return type %u\n", vtReturn);
6778 heap_free( args );
6779 return E_INVALIDARG;
6780 default:
6781 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6782 break;
6784 heap_free( args );
6785 if (stack_offset && cc == CC_STDCALL)
6787 WARN( "stack pointer off by %d\n", stack_offset );
6788 return DISP_E_BADCALLEE;
6790 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6791 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6792 return S_OK;
6794 #elif defined(__x86_64__)
6795 int argspos;
6796 UINT i;
6797 DWORD_PTR *args;
6798 void *func;
6800 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6801 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6802 pvargResult, V_VT(pvargResult));
6804 if (cc != CC_STDCALL && cc != CC_CDECL)
6806 FIXME("unsupported calling convention %d\n",cc);
6807 return E_INVALIDARG;
6810 /* maximum size for an argument is sizeof(DWORD_PTR) */
6811 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6813 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6814 argspos = 1;
6815 if (pvInstance)
6817 const FARPROC *vtable = *(FARPROC **)pvInstance;
6818 func = vtable[oVft/sizeof(void *)];
6819 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6821 else func = (void *)oVft;
6823 for (i = 0; i < cActuals; i++)
6825 VARIANT *arg = prgpvarg[i];
6827 switch (prgvt[i])
6829 case VT_DECIMAL:
6830 case VT_VARIANT:
6831 args[argspos++] = (ULONG_PTR)arg;
6832 break;
6833 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6834 args[argspos++] = V_BOOL(arg);
6835 break;
6836 default:
6837 args[argspos++] = V_UI8(arg);
6838 break;
6840 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6843 switch (vtReturn)
6845 case VT_R4:
6846 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6847 break;
6848 case VT_R8:
6849 case VT_DATE:
6850 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6851 break;
6852 case VT_DECIMAL:
6853 case VT_VARIANT:
6854 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6855 call_method( func, argspos, args );
6856 break;
6857 case VT_HRESULT:
6858 WARN("invalid return type %u\n", vtReturn);
6859 heap_free( args );
6860 return E_INVALIDARG;
6861 default:
6862 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6863 break;
6865 heap_free( args );
6866 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6867 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6868 return S_OK;
6870 #else
6871 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6872 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6873 return E_NOTIMPL;
6874 #endif
6877 static inline BOOL func_restricted( const FUNCDESC *desc )
6879 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6882 #define INVBUF_ELEMENT_SIZE \
6883 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6884 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6885 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6886 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6887 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6888 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6889 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6890 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6892 static HRESULT WINAPI ITypeInfo_fnInvoke(
6893 ITypeInfo2 *iface,
6894 VOID *pIUnk,
6895 MEMBERID memid,
6896 UINT16 wFlags,
6897 DISPPARAMS *pDispParams,
6898 VARIANT *pVarResult,
6899 EXCEPINFO *pExcepInfo,
6900 UINT *pArgErr)
6902 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6903 int i;
6904 unsigned int var_index;
6905 TYPEKIND type_kind;
6906 HRESULT hres;
6907 const TLBFuncDesc *pFuncInfo;
6908 UINT fdc;
6910 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6911 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6914 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6915 return DISP_E_MEMBERNOTFOUND;
6917 if (!pDispParams)
6919 ERR("NULL pDispParams not allowed\n");
6920 return E_INVALIDARG;
6923 dump_DispParms(pDispParams);
6925 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6927 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6928 pDispParams->cNamedArgs, pDispParams->cArgs);
6929 return E_INVALIDARG;
6932 /* we do this instead of using GetFuncDesc since it will return a fake
6933 * FUNCDESC for dispinterfaces and we want the real function description */
6934 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6935 pFuncInfo = &This->funcdescs[fdc];
6936 if ((memid == pFuncInfo->funcdesc.memid) &&
6937 (wFlags & pFuncInfo->funcdesc.invkind) &&
6938 !func_restricted( &pFuncInfo->funcdesc ))
6939 break;
6942 if (fdc < This->cFuncs) {
6943 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6945 if (TRACE_ON(ole))
6947 TRACE("invoking:\n");
6948 dump_TLBFuncDescOne(pFuncInfo);
6951 switch (func_desc->funckind) {
6952 case FUNC_PUREVIRTUAL:
6953 case FUNC_VIRTUAL: {
6954 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6955 VARIANT varresult;
6956 VARIANT retval; /* pointer for storing byref retvals in */
6957 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6958 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6959 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6960 UINT cNamedArgs = pDispParams->cNamedArgs;
6961 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6962 UINT vargs_converted=0;
6964 hres = S_OK;
6966 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6968 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6970 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6971 hres = DISP_E_PARAMNOTFOUND;
6972 goto func_fail;
6976 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6978 ERR("functions with the vararg attribute do not support named arguments\n");
6979 hres = DISP_E_NONAMEDARGS;
6980 goto func_fail;
6983 for (i = 0; i < func_desc->cParams; i++)
6985 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6986 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6987 if (FAILED(hres))
6988 goto func_fail;
6991 TRACE("changing args\n");
6992 for (i = 0; i < func_desc->cParams; i++)
6994 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6995 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6996 VARIANTARG *src_arg;
6998 if (wParamFlags & PARAMFLAG_FLCID)
7000 VARIANTARG *arg;
7001 arg = prgpvarg[i] = &rgvarg[i];
7002 V_VT(arg) = VT_I4;
7003 V_I4(arg) = This->pTypeLib->lcid;
7004 continue;
7007 src_arg = NULL;
7009 if (cNamedArgs)
7011 USHORT j;
7012 for (j = 0; j < cNamedArgs; j++)
7013 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7015 src_arg = &pDispParams->rgvarg[j];
7016 break;
7020 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7022 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7023 vargs_converted++;
7026 if (wParamFlags & PARAMFLAG_FRETVAL)
7028 /* under most conditions the caller is not allowed to
7029 * pass in a dispparam arg in the index of what would be
7030 * the retval parameter. however, there is an exception
7031 * where the extra parameter is used in an extra
7032 * IDispatch::Invoke below */
7033 if ((i < pDispParams->cArgs) &&
7034 ((func_desc->cParams != 1) || !pVarResult ||
7035 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7037 hres = DISP_E_BADPARAMCOUNT;
7038 break;
7041 /* note: this check is placed so that if the caller passes
7042 * in a VARIANTARG for the retval we just ignore it, like
7043 * native does */
7044 if (i == func_desc->cParams - 1)
7046 VARIANTARG *arg;
7047 arg = prgpvarg[i] = &rgvarg[i];
7048 memset(arg, 0, sizeof(*arg));
7049 V_VT(arg) = rgvt[i];
7050 memset(&retval, 0, sizeof(retval));
7051 V_BYREF(arg) = &retval;
7053 else
7055 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7056 hres = E_UNEXPECTED;
7057 break;
7060 else if (src_arg)
7062 TRACE("%s\n", debugstr_variant(src_arg));
7064 if(rgvt[i]!=V_VT(src_arg))
7066 if (rgvt[i] == VT_VARIANT)
7067 hres = VariantCopy(&rgvarg[i], src_arg);
7068 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7070 if (rgvt[i] == V_VT(src_arg))
7071 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7072 else
7074 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7075 if (wParamFlags & PARAMFLAG_FIN)
7076 hres = VariantCopy(&missing_arg[i], src_arg);
7077 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7079 V_VT(&rgvarg[i]) = rgvt[i];
7081 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7083 SAFEARRAY *a;
7084 SAFEARRAYBOUND bound;
7085 VARIANT *v;
7086 LONG j;
7087 bound.lLbound = 0;
7088 bound.cElements = pDispParams->cArgs-i;
7089 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7091 ERR("SafeArrayCreate failed\n");
7092 break;
7094 hres = SafeArrayAccessData(a, (LPVOID)&v);
7095 if (hres != S_OK)
7097 ERR("SafeArrayAccessData failed with %x\n", hres);
7098 SafeArrayDestroy(a);
7099 break;
7101 for (j = 0; j < bound.cElements; j++)
7102 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7103 hres = SafeArrayUnaccessData(a);
7104 if (hres != S_OK)
7106 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7107 SafeArrayDestroy(a);
7108 break;
7110 if (rgvt[i] & VT_BYREF)
7111 V_BYREF(&rgvarg[i]) = &a;
7112 else
7113 V_ARRAY(&rgvarg[i]) = a;
7114 V_VT(&rgvarg[i]) = rgvt[i];
7116 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7118 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7119 if (wParamFlags & PARAMFLAG_FIN)
7120 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7121 else
7122 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7123 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7124 V_VT(&rgvarg[i]) = rgvt[i];
7126 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7128 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7129 V_VT(&rgvarg[i]) = rgvt[i];
7131 else
7133 /* FIXME: this doesn't work for VT_BYREF arguments if
7134 * they are not the same type as in the paramdesc */
7135 V_VT(&rgvarg[i]) = V_VT(src_arg);
7136 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7137 V_VT(&rgvarg[i]) = rgvt[i];
7140 if (FAILED(hres))
7142 ERR("failed to convert param %d to %s from %s\n", i,
7143 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7144 break;
7146 prgpvarg[i] = &rgvarg[i];
7148 else
7150 prgpvarg[i] = src_arg;
7153 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7154 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7155 && V_UNKNOWN(prgpvarg[i])) {
7156 IUnknown *userdefined_iface;
7157 GUID guid;
7159 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7160 if(FAILED(hres))
7161 break;
7163 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7164 if(FAILED(hres)) {
7165 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7166 break;
7169 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7170 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7173 else if (wParamFlags & PARAMFLAG_FOPT)
7175 VARIANTARG *arg;
7176 arg = prgpvarg[i] = &rgvarg[i];
7177 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7179 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7180 if (FAILED(hres))
7181 break;
7183 else
7185 VARIANTARG *missing_arg;
7186 /* if the function wants a pointer to a variant then
7187 * set that up, otherwise just pass the VT_ERROR in
7188 * the argument by value */
7189 if (rgvt[i] & VT_BYREF)
7191 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7192 V_VT(arg) = VT_VARIANT | VT_BYREF;
7193 V_VARIANTREF(arg) = missing_arg;
7195 else
7196 missing_arg = arg;
7197 V_VT(missing_arg) = VT_ERROR;
7198 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7201 else
7203 hres = DISP_E_BADPARAMCOUNT;
7204 break;
7207 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7209 /* VT_VOID is a special case for return types, so it is not
7210 * handled in the general function */
7211 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7212 V_VT(&varresult) = VT_EMPTY;
7213 else
7215 V_VT(&varresult) = 0;
7216 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7217 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7220 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7221 V_VT(&varresult), func_desc->cParams, rgvt,
7222 prgpvarg, &varresult);
7224 vargs_converted = 0;
7226 for (i = 0; i < func_desc->cParams; i++)
7228 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7229 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7231 if (wParamFlags & PARAMFLAG_FLCID)
7232 continue;
7233 else if (wParamFlags & PARAMFLAG_FRETVAL)
7235 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7237 if (pVarResult)
7239 VariantInit(pVarResult);
7240 /* deref return value */
7241 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7244 VARIANT_ClearInd(prgpvarg[i]);
7246 else if (vargs_converted < pDispParams->cArgs)
7248 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7249 if (wParamFlags & PARAMFLAG_FOUT)
7251 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7253 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7255 if (FAILED(hres))
7257 ERR("failed to convert param %d to vt %d\n", i,
7258 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7259 break;
7263 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7264 func_desc->cParamsOpt < 0 &&
7265 i == func_desc->cParams-1)
7267 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7268 LONG j, ubound;
7269 VARIANT *v;
7270 hres = SafeArrayGetUBound(a, 1, &ubound);
7271 if (hres != S_OK)
7273 ERR("SafeArrayGetUBound failed with %x\n", hres);
7274 break;
7276 hres = SafeArrayAccessData(a, (LPVOID)&v);
7277 if (hres != S_OK)
7279 ERR("SafeArrayAccessData failed with %x\n", hres);
7280 break;
7282 for (j = 0; j <= ubound; j++)
7283 VariantClear(&v[j]);
7284 hres = SafeArrayUnaccessData(a);
7285 if (hres != S_OK)
7287 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7288 break;
7291 VariantClear(&rgvarg[i]);
7292 vargs_converted++;
7294 else if (wParamFlags & PARAMFLAG_FOPT)
7296 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7297 VariantClear(&rgvarg[i]);
7300 VariantClear(&missing_arg[i]);
7303 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7305 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7306 hres = DISP_E_EXCEPTION;
7307 if (pExcepInfo)
7309 IErrorInfo *pErrorInfo;
7310 pExcepInfo->scode = V_ERROR(&varresult);
7311 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7313 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7314 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7315 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7316 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7318 IErrorInfo_Release(pErrorInfo);
7322 if (V_VT(&varresult) != VT_ERROR)
7324 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7326 if (pVarResult)
7328 VariantClear(pVarResult);
7329 *pVarResult = varresult;
7331 else
7332 VariantClear(&varresult);
7335 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7336 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7337 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7338 (pDispParams->cArgs != 0))
7340 if (V_VT(pVarResult) == VT_DISPATCH)
7342 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7343 /* Note: not VariantClear; we still need the dispatch
7344 * pointer to be valid */
7345 VariantInit(pVarResult);
7346 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7347 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7348 pDispParams, pVarResult, pExcepInfo, pArgErr);
7349 IDispatch_Release(pDispatch);
7351 else
7353 VariantClear(pVarResult);
7354 hres = DISP_E_NOTACOLLECTION;
7358 func_fail:
7359 heap_free(buffer);
7360 break;
7362 case FUNC_DISPATCH: {
7363 IDispatch *disp;
7365 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7366 if (SUCCEEDED(hres)) {
7367 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7368 hres = IDispatch_Invoke(
7369 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7370 pVarResult,pExcepInfo,pArgErr
7372 if (FAILED(hres))
7373 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7374 IDispatch_Release(disp);
7375 } else
7376 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7377 break;
7379 default:
7380 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7381 hres = E_FAIL;
7382 break;
7385 TRACE("-- 0x%08x\n", hres);
7386 return hres;
7388 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7389 VARDESC *var_desc;
7391 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7392 if(FAILED(hres)) return hres;
7394 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7395 dump_VARDESC(var_desc);
7396 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7397 return E_NOTIMPL;
7400 /* not found, look for it in inherited interfaces */
7401 ITypeInfo2_GetTypeKind(iface, &type_kind);
7402 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7403 if(This->impltypes) {
7404 /* recursive search */
7405 ITypeInfo *pTInfo;
7406 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7407 if(SUCCEEDED(hres)){
7408 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7409 ITypeInfo_Release(pTInfo);
7410 return hres;
7412 WARN("Could not search inherited interface!\n");
7415 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7416 return DISP_E_MEMBERNOTFOUND;
7419 /* ITypeInfo::GetDocumentation
7421 * Retrieves the documentation string, the complete Help file name and path,
7422 * and the context ID for the Help topic for a specified type description.
7424 * (Can be tested by the Visual Basic Editor in Word for instance.)
7426 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7427 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7428 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7430 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7431 const TLBFuncDesc *pFDesc;
7432 const TLBVarDesc *pVDesc;
7433 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7434 " HelpContext(%p) HelpFile(%p)\n",
7435 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7436 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7437 if(pBstrName)
7438 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7439 if(pBstrDocString)
7440 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7441 if(pdwHelpContext)
7442 *pdwHelpContext=This->dwHelpContext;
7443 if(pBstrHelpFile)
7444 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7445 return S_OK;
7446 }else {/* for a member */
7447 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7448 if(pFDesc){
7449 if(pBstrName)
7450 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7451 if(pBstrDocString)
7452 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7453 if(pdwHelpContext)
7454 *pdwHelpContext=pFDesc->helpcontext;
7455 if(pBstrHelpFile)
7456 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7457 return S_OK;
7459 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7460 if(pVDesc){
7461 if(pBstrName)
7462 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7463 if(pBstrDocString)
7464 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7465 if(pdwHelpContext)
7466 *pdwHelpContext=pVDesc->HelpContext;
7467 if(pBstrHelpFile)
7468 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7469 return S_OK;
7473 if(This->impltypes &&
7474 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7475 /* recursive search */
7476 ITypeInfo *pTInfo;
7477 HRESULT result;
7478 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7479 if(SUCCEEDED(result)) {
7480 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7481 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7482 ITypeInfo_Release(pTInfo);
7483 return result;
7485 WARN("Could not search inherited interface!\n");
7488 WARN("member %d not found\n", memid);
7489 return TYPE_E_ELEMENTNOTFOUND;
7492 /* ITypeInfo::GetDllEntry
7494 * Retrieves a description or specification of an entry point for a function
7495 * in a DLL.
7497 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7498 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7499 WORD *pwOrdinal)
7501 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7502 const TLBFuncDesc *pFDesc;
7504 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7506 if (pBstrDllName) *pBstrDllName = NULL;
7507 if (pBstrName) *pBstrName = NULL;
7508 if (pwOrdinal) *pwOrdinal = 0;
7510 if (This->typekind != TKIND_MODULE)
7511 return TYPE_E_BADMODULEKIND;
7513 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7514 if(pFDesc){
7515 dump_TypeInfo(This);
7516 if (TRACE_ON(ole))
7517 dump_TLBFuncDescOne(pFDesc);
7519 if (pBstrDllName)
7520 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7522 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7523 if (pBstrName)
7524 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7525 if (pwOrdinal)
7526 *pwOrdinal = -1;
7527 return S_OK;
7529 if (pBstrName)
7530 *pBstrName = NULL;
7531 if (pwOrdinal)
7532 *pwOrdinal = LOWORD(pFDesc->Entry);
7533 return S_OK;
7535 return TYPE_E_ELEMENTNOTFOUND;
7538 /* internal function to make the inherited interfaces' methods appear
7539 * part of the interface */
7540 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7541 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7543 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7544 HRESULT hr;
7546 TRACE("%p, 0x%x\n", iface, *hRefType);
7548 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7550 ITypeInfo *pSubTypeInfo;
7552 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7553 if (FAILED(hr))
7554 return hr;
7556 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7557 hRefType, ppTInfo);
7558 ITypeInfo_Release(pSubTypeInfo);
7559 if (SUCCEEDED(hr))
7560 return hr;
7562 *hRefType -= DISPATCH_HREF_OFFSET;
7564 if (!(*hRefType & DISPATCH_HREF_MASK))
7565 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7566 else
7567 return E_FAIL;
7570 struct search_res_tlb_params
7572 const GUID *guid;
7573 ITypeLib *pTLib;
7576 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7578 struct search_res_tlb_params *params = (LPVOID)lParam;
7579 static const WCHAR formatW[] = {'\\','%','d',0};
7580 WCHAR szPath[MAX_PATH+1];
7581 ITypeLib *pTLib = NULL;
7582 HRESULT ret;
7583 DWORD len;
7585 if (IS_INTRESOURCE(lpszName) == FALSE)
7586 return TRUE;
7588 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7589 return TRUE;
7591 if (snprintfW(szPath + len, sizeof(szPath)/sizeof(WCHAR) - len, formatW, LOWORD(lpszName)) < 0)
7592 return TRUE;
7594 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7595 if (SUCCEEDED(ret))
7597 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7598 if (IsEqualGUID(params->guid, impl->guid))
7600 params->pTLib = pTLib;
7601 return FALSE; /* stop enumeration */
7603 ITypeLib_Release(pTLib);
7606 return TRUE;
7609 /* ITypeInfo::GetRefTypeInfo
7611 * If a type description references other type descriptions, it retrieves
7612 * the referenced type descriptions.
7614 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7615 ITypeInfo2 *iface,
7616 HREFTYPE hRefType,
7617 ITypeInfo **ppTInfo)
7619 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7620 HRESULT result = E_FAIL;
7622 if(!ppTInfo)
7623 return E_INVALIDARG;
7625 if ((INT)hRefType < 0) {
7626 ITypeInfoImpl *pTypeInfoImpl;
7628 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7629 !(This->typekind == TKIND_INTERFACE ||
7630 This->typekind == TKIND_DISPATCH))
7631 return TYPE_E_ELEMENTNOTFOUND;
7633 /* when we meet a DUAL typeinfo, we must create the alternate
7634 * version of it.
7636 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7638 *pTypeInfoImpl = *This;
7639 pTypeInfoImpl->ref = 0;
7640 list_init(&pTypeInfoImpl->custdata_list);
7642 if (This->typekind == TKIND_INTERFACE)
7643 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7644 else
7645 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7647 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7648 /* the AddRef implicitly adds a reference to the parent typelib, which
7649 * stops the copied data from being destroyed until the new typeinfo's
7650 * refcount goes to zero, but we need to signal to the new instance to
7651 * not free its data structures when it is destroyed */
7652 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7654 ITypeInfo_AddRef(*ppTInfo);
7656 result = S_OK;
7657 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7658 (This->typekind == TKIND_DISPATCH))
7660 HREFTYPE href_dispatch = hRefType;
7661 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7662 } else {
7663 TLBRefType *ref_type;
7664 ITypeLib *pTLib = NULL;
7665 UINT i;
7667 if(!(hRefType & 0x1)){
7668 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7670 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7672 result = S_OK;
7673 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7674 ITypeInfo_AddRef(*ppTInfo);
7675 goto end;
7680 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7682 if(ref_type->reference == (hRefType & (~0x3)))
7683 break;
7685 if(&ref_type->entry == &This->pTypeLib->ref_list)
7687 FIXME("Can't find pRefType for ref %x\n", hRefType);
7688 goto end;
7691 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7692 UINT Index;
7693 TRACE("internal reference\n");
7694 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7695 } else {
7696 if(ref_type->pImpTLInfo->pImpTypeLib) {
7697 TRACE("typeinfo in imported typelib that is already loaded\n");
7698 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7699 ITypeLib_AddRef(pTLib);
7700 result = S_OK;
7701 } else {
7702 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
7703 struct search_res_tlb_params params;
7704 BSTR libnam;
7706 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7708 /* Search in resource table */
7709 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
7710 params.pTLib = NULL;
7711 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
7712 pTLib = params.pTLib;
7713 result = S_OK;
7715 if (!pTLib)
7717 /* Search on disk */
7718 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7719 ref_type->pImpTLInfo->wVersionMajor,
7720 ref_type->pImpTLInfo->wVersionMinor,
7721 This->pTypeLib->syskind,
7722 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7723 if (FAILED(result))
7724 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7726 result = LoadTypeLib(libnam, &pTLib);
7727 SysFreeString(libnam);
7730 if(SUCCEEDED(result)) {
7731 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7732 ITypeLib_AddRef(pTLib);
7736 if(SUCCEEDED(result)) {
7737 if(ref_type->index == TLB_REF_USE_GUID)
7738 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7739 else
7740 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7742 if (pTLib != NULL)
7743 ITypeLib_Release(pTLib);
7746 end:
7747 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7748 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7749 return result;
7752 /* ITypeInfo::AddressOfMember
7754 * Retrieves the addresses of static functions or variables, such as those
7755 * defined in a DLL.
7757 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7758 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7760 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7761 HRESULT hr;
7762 BSTR dll, entry;
7763 WORD ordinal;
7764 HMODULE module;
7766 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7768 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7769 if (FAILED(hr))
7770 return hr;
7772 module = LoadLibraryW(dll);
7773 if (!module)
7775 ERR("couldn't load %s\n", debugstr_w(dll));
7776 SysFreeString(dll);
7777 SysFreeString(entry);
7778 return STG_E_FILENOTFOUND;
7780 /* FIXME: store library somewhere where we can free it */
7782 if (entry)
7784 LPSTR entryA;
7785 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7786 entryA = heap_alloc(len);
7787 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7789 *ppv = GetProcAddress(module, entryA);
7790 if (!*ppv)
7791 ERR("function not found %s\n", debugstr_a(entryA));
7793 heap_free(entryA);
7795 else
7797 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7798 if (!*ppv)
7799 ERR("function not found %d\n", ordinal);
7802 SysFreeString(dll);
7803 SysFreeString(entry);
7805 if (!*ppv)
7806 return TYPE_E_DLLFUNCTIONNOTFOUND;
7808 return S_OK;
7811 /* ITypeInfo::CreateInstance
7813 * Creates a new instance of a type that describes a component object class
7814 * (coclass).
7816 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7817 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7819 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7820 HRESULT hr;
7821 TYPEATTR *pTA;
7823 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7825 *ppvObj = NULL;
7827 if(pOuterUnk)
7829 WARN("Not able to aggregate\n");
7830 return CLASS_E_NOAGGREGATION;
7833 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7834 if(FAILED(hr)) return hr;
7836 if(pTA->typekind != TKIND_COCLASS)
7838 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7839 hr = E_INVALIDARG;
7840 goto end;
7843 hr = S_FALSE;
7844 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7846 IUnknown *pUnk;
7847 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7848 TRACE("GetActiveObject rets %08x\n", hr);
7849 if(hr == S_OK)
7851 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7852 IUnknown_Release(pUnk);
7856 if(hr != S_OK)
7857 hr = CoCreateInstance(&pTA->guid, NULL,
7858 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7859 riid, ppvObj);
7861 end:
7862 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7863 return hr;
7866 /* ITypeInfo::GetMops
7868 * Retrieves marshalling information.
7870 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7871 BSTR *pBstrMops)
7873 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7874 FIXME("(%p %d) stub!\n", This, memid);
7875 *pBstrMops = NULL;
7876 return S_OK;
7879 /* ITypeInfo::GetContainingTypeLib
7881 * Retrieves the containing type library and the index of the type description
7882 * within that type library.
7884 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7885 ITypeLib * *ppTLib, UINT *pIndex)
7887 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7889 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7890 if (pIndex) {
7891 *pIndex=This->index;
7892 TRACE("returning pIndex=%d\n", *pIndex);
7895 if (ppTLib) {
7896 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
7897 ITypeLib_AddRef(*ppTLib);
7898 TRACE("returning ppTLib=%p\n", *ppTLib);
7901 return S_OK;
7904 /* ITypeInfo::ReleaseTypeAttr
7906 * Releases a TYPEATTR previously returned by Get
7909 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7910 TYPEATTR* pTypeAttr)
7912 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7913 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7914 heap_free(pTypeAttr);
7917 /* ITypeInfo::ReleaseFuncDesc
7919 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7921 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7922 ITypeInfo2 *iface,
7923 FUNCDESC *pFuncDesc)
7925 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7926 SHORT i;
7928 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7930 for (i = 0; i < pFuncDesc->cParams; i++)
7931 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7932 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7934 SysFreeString((BSTR)pFuncDesc);
7937 /* ITypeInfo::ReleaseVarDesc
7939 * Releases a VARDESC previously returned by GetVarDesc.
7941 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7942 VARDESC *pVarDesc)
7944 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7945 TRACE("(%p)->(%p)\n", This, pVarDesc);
7947 TLB_FreeVarDesc(pVarDesc);
7950 /* ITypeInfo2::GetTypeKind
7952 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7955 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7956 TYPEKIND *pTypeKind)
7958 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7959 *pTypeKind=This->typekind;
7960 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7961 return S_OK;
7964 /* ITypeInfo2::GetTypeFlags
7966 * Returns the type flags without any allocations. This returns a DWORD type
7967 * flag, which expands the type flags without growing the TYPEATTR (type
7968 * attribute).
7971 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7973 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7974 *pTypeFlags=This->wTypeFlags;
7975 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7976 return S_OK;
7979 /* ITypeInfo2::GetFuncIndexOfMemId
7980 * Binds to a specific member based on a known DISPID, where the member name
7981 * is not known (for example, when binding to a default member).
7984 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7985 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7987 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7988 UINT fdc;
7989 HRESULT result;
7991 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7992 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7993 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7994 break;
7996 if(fdc < This->cFuncs) {
7997 *pFuncIndex = fdc;
7998 result = S_OK;
7999 } else
8000 result = TYPE_E_ELEMENTNOTFOUND;
8002 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8003 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8004 return result;
8007 /* TypeInfo2::GetVarIndexOfMemId
8009 * Binds to a specific member based on a known DISPID, where the member name
8010 * is not known (for example, when binding to a default member).
8013 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8014 MEMBERID memid, UINT *pVarIndex)
8016 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8017 TLBVarDesc *pVarInfo;
8019 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8021 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8022 if(!pVarInfo)
8023 return TYPE_E_ELEMENTNOTFOUND;
8025 *pVarIndex = (pVarInfo - This->vardescs);
8027 return S_OK;
8030 /* ITypeInfo2::GetCustData
8032 * Gets the custom data
8034 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8035 ITypeInfo2 * iface,
8036 REFGUID guid,
8037 VARIANT *pVarVal)
8039 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8040 TLBCustData *pCData;
8042 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8044 if(!guid || !pVarVal)
8045 return E_INVALIDARG;
8047 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8049 VariantInit( pVarVal);
8050 if (pCData)
8051 VariantCopy( pVarVal, &pCData->data);
8052 else
8053 VariantClear( pVarVal );
8054 return S_OK;
8057 /* ITypeInfo2::GetFuncCustData
8059 * Gets the custom data
8061 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8062 ITypeInfo2 * iface,
8063 UINT index,
8064 REFGUID guid,
8065 VARIANT *pVarVal)
8067 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8068 TLBCustData *pCData;
8069 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8071 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8073 if(index >= This->cFuncs)
8074 return TYPE_E_ELEMENTNOTFOUND;
8076 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8077 if(!pCData)
8078 return TYPE_E_ELEMENTNOTFOUND;
8080 VariantInit(pVarVal);
8081 VariantCopy(pVarVal, &pCData->data);
8083 return S_OK;
8086 /* ITypeInfo2::GetParamCustData
8088 * Gets the custom data
8090 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8091 ITypeInfo2 * iface,
8092 UINT indexFunc,
8093 UINT indexParam,
8094 REFGUID guid,
8095 VARIANT *pVarVal)
8097 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8098 TLBCustData *pCData;
8099 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8101 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8102 debugstr_guid(guid), pVarVal);
8104 if(indexFunc >= This->cFuncs)
8105 return TYPE_E_ELEMENTNOTFOUND;
8107 if(indexParam >= pFDesc->funcdesc.cParams)
8108 return TYPE_E_ELEMENTNOTFOUND;
8110 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8111 if(!pCData)
8112 return TYPE_E_ELEMENTNOTFOUND;
8114 VariantInit(pVarVal);
8115 VariantCopy(pVarVal, &pCData->data);
8117 return S_OK;
8120 /* ITypeInfo2::GetVarCustData
8122 * Gets the custom data
8124 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8125 ITypeInfo2 * iface,
8126 UINT index,
8127 REFGUID guid,
8128 VARIANT *pVarVal)
8130 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8131 TLBCustData *pCData;
8132 TLBVarDesc *pVDesc = &This->vardescs[index];
8134 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8136 if(index >= This->cVars)
8137 return TYPE_E_ELEMENTNOTFOUND;
8139 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8140 if(!pCData)
8141 return TYPE_E_ELEMENTNOTFOUND;
8143 VariantInit(pVarVal);
8144 VariantCopy(pVarVal, &pCData->data);
8146 return S_OK;
8149 /* ITypeInfo2::GetImplCustData
8151 * Gets the custom data
8153 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8154 ITypeInfo2 * iface,
8155 UINT index,
8156 REFGUID guid,
8157 VARIANT *pVarVal)
8159 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8160 TLBCustData *pCData;
8161 TLBImplType *pRDesc = &This->impltypes[index];
8163 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8165 if(index >= This->cImplTypes)
8166 return TYPE_E_ELEMENTNOTFOUND;
8168 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8169 if(!pCData)
8170 return TYPE_E_ELEMENTNOTFOUND;
8172 VariantInit(pVarVal);
8173 VariantCopy(pVarVal, &pCData->data);
8175 return S_OK;
8178 /* ITypeInfo2::GetDocumentation2
8180 * Retrieves the documentation string, the complete Help file name and path,
8181 * the localization context to use, and the context ID for the library Help
8182 * topic in the Help file.
8185 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8186 ITypeInfo2 * iface,
8187 MEMBERID memid,
8188 LCID lcid,
8189 BSTR *pbstrHelpString,
8190 DWORD *pdwHelpStringContext,
8191 BSTR *pbstrHelpStringDll)
8193 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8194 const TLBFuncDesc *pFDesc;
8195 const TLBVarDesc *pVDesc;
8196 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8197 "HelpStringContext(%p) HelpStringDll(%p)\n",
8198 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8199 pbstrHelpStringDll );
8200 /* the help string should be obtained from the helpstringdll,
8201 * using the _DLLGetDocumentation function, based on the supplied
8202 * lcid. Nice to do sometime...
8204 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8205 if(pbstrHelpString)
8206 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8207 if(pdwHelpStringContext)
8208 *pdwHelpStringContext=This->dwHelpStringContext;
8209 if(pbstrHelpStringDll)
8210 *pbstrHelpStringDll=
8211 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8212 return S_OK;
8213 }else {/* for a member */
8214 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
8215 if(pFDesc){
8216 if(pbstrHelpString)
8217 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8218 if(pdwHelpStringContext)
8219 *pdwHelpStringContext=pFDesc->HelpStringContext;
8220 if(pbstrHelpStringDll)
8221 *pbstrHelpStringDll=
8222 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8223 return S_OK;
8225 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8226 if(pVDesc){
8227 if(pbstrHelpString)
8228 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8229 if(pdwHelpStringContext)
8230 *pdwHelpStringContext=pVDesc->HelpStringContext;
8231 if(pbstrHelpStringDll)
8232 *pbstrHelpStringDll=
8233 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8234 return S_OK;
8237 return TYPE_E_ELEMENTNOTFOUND;
8240 /* ITypeInfo2::GetAllCustData
8242 * Gets all custom data items for the Type info.
8245 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8246 ITypeInfo2 * iface,
8247 CUSTDATA *pCustData)
8249 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8251 TRACE("%p %p\n", This, pCustData);
8253 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8256 /* ITypeInfo2::GetAllFuncCustData
8258 * Gets all custom data items for the specified Function
8261 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8262 ITypeInfo2 * iface,
8263 UINT index,
8264 CUSTDATA *pCustData)
8266 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8267 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8269 TRACE("%p %u %p\n", This, index, pCustData);
8271 if(index >= This->cFuncs)
8272 return TYPE_E_ELEMENTNOTFOUND;
8274 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8277 /* ITypeInfo2::GetAllParamCustData
8279 * Gets all custom data items for the Functions
8282 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8283 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8285 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8286 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8288 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8290 if(indexFunc >= This->cFuncs)
8291 return TYPE_E_ELEMENTNOTFOUND;
8293 if(indexParam >= pFDesc->funcdesc.cParams)
8294 return TYPE_E_ELEMENTNOTFOUND;
8296 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8299 /* ITypeInfo2::GetAllVarCustData
8301 * Gets all custom data items for the specified Variable
8304 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8305 UINT index, CUSTDATA *pCustData)
8307 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8308 TLBVarDesc * pVDesc = &This->vardescs[index];
8310 TRACE("%p %u %p\n", This, index, pCustData);
8312 if(index >= This->cVars)
8313 return TYPE_E_ELEMENTNOTFOUND;
8315 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8318 /* ITypeInfo2::GetAllImplCustData
8320 * Gets all custom data items for the specified implementation type
8323 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8324 ITypeInfo2 * iface,
8325 UINT index,
8326 CUSTDATA *pCustData)
8328 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8329 TLBImplType *pRDesc = &This->impltypes[index];
8331 TRACE("%p %u %p\n", This, index, pCustData);
8333 if(index >= This->cImplTypes)
8334 return TYPE_E_ELEMENTNOTFOUND;
8336 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8339 static const ITypeInfo2Vtbl tinfvt =
8342 ITypeInfo_fnQueryInterface,
8343 ITypeInfo_fnAddRef,
8344 ITypeInfo_fnRelease,
8346 ITypeInfo_fnGetTypeAttr,
8347 ITypeInfo_fnGetTypeComp,
8348 ITypeInfo_fnGetFuncDesc,
8349 ITypeInfo_fnGetVarDesc,
8350 ITypeInfo_fnGetNames,
8351 ITypeInfo_fnGetRefTypeOfImplType,
8352 ITypeInfo_fnGetImplTypeFlags,
8353 ITypeInfo_fnGetIDsOfNames,
8354 ITypeInfo_fnInvoke,
8355 ITypeInfo_fnGetDocumentation,
8356 ITypeInfo_fnGetDllEntry,
8357 ITypeInfo_fnGetRefTypeInfo,
8358 ITypeInfo_fnAddressOfMember,
8359 ITypeInfo_fnCreateInstance,
8360 ITypeInfo_fnGetMops,
8361 ITypeInfo_fnGetContainingTypeLib,
8362 ITypeInfo_fnReleaseTypeAttr,
8363 ITypeInfo_fnReleaseFuncDesc,
8364 ITypeInfo_fnReleaseVarDesc,
8366 ITypeInfo2_fnGetTypeKind,
8367 ITypeInfo2_fnGetTypeFlags,
8368 ITypeInfo2_fnGetFuncIndexOfMemId,
8369 ITypeInfo2_fnGetVarIndexOfMemId,
8370 ITypeInfo2_fnGetCustData,
8371 ITypeInfo2_fnGetFuncCustData,
8372 ITypeInfo2_fnGetParamCustData,
8373 ITypeInfo2_fnGetVarCustData,
8374 ITypeInfo2_fnGetImplTypeCustData,
8375 ITypeInfo2_fnGetDocumentation2,
8376 ITypeInfo2_fnGetAllCustData,
8377 ITypeInfo2_fnGetAllFuncCustData,
8378 ITypeInfo2_fnGetAllParamCustData,
8379 ITypeInfo2_fnGetAllVarCustData,
8380 ITypeInfo2_fnGetAllImplTypeCustData,
8383 /******************************************************************************
8384 * CreateDispTypeInfo [OLEAUT32.31]
8386 * Build type information for an object so it can be called through an
8387 * IDispatch interface.
8389 * RETURNS
8390 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8391 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8393 * NOTES
8394 * This call allows an objects methods to be accessed through IDispatch, by
8395 * building an ITypeInfo object that IDispatch can use to call through.
8397 HRESULT WINAPI CreateDispTypeInfo(
8398 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8399 LCID lcid, /* [I] Locale Id */
8400 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8402 ITypeInfoImpl *pTIClass, *pTIIface;
8403 ITypeLibImpl *pTypeLibImpl;
8404 unsigned int param, func;
8405 TLBFuncDesc *pFuncDesc;
8406 TLBRefType *ref;
8408 TRACE("\n");
8409 pTypeLibImpl = TypeLibImpl_Constructor();
8410 if (!pTypeLibImpl) return E_FAIL;
8412 pTypeLibImpl->TypeInfoCount = 2;
8413 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8415 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8416 pTIIface->pTypeLib = pTypeLibImpl;
8417 pTIIface->index = 0;
8418 pTIIface->Name = NULL;
8419 pTIIface->dwHelpContext = -1;
8420 pTIIface->guid = NULL;
8421 pTIIface->lcid = lcid;
8422 pTIIface->typekind = TKIND_INTERFACE;
8423 pTIIface->wMajorVerNum = 0;
8424 pTIIface->wMinorVerNum = 0;
8425 pTIIface->cbAlignment = 2;
8426 pTIIface->cbSizeInstance = -1;
8427 pTIIface->cbSizeVft = -1;
8428 pTIIface->cFuncs = 0;
8429 pTIIface->cImplTypes = 0;
8430 pTIIface->cVars = 0;
8431 pTIIface->wTypeFlags = 0;
8432 pTIIface->hreftype = 0;
8434 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8435 pFuncDesc = pTIIface->funcdescs;
8436 for(func = 0; func < pidata->cMembers; func++) {
8437 METHODDATA *md = pidata->pmethdata + func;
8438 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8439 pFuncDesc->funcdesc.memid = md->dispid;
8440 pFuncDesc->funcdesc.lprgscode = NULL;
8441 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8442 pFuncDesc->funcdesc.invkind = md->wFlags;
8443 pFuncDesc->funcdesc.callconv = md->cc;
8444 pFuncDesc->funcdesc.cParams = md->cArgs;
8445 pFuncDesc->funcdesc.cParamsOpt = 0;
8446 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8447 pFuncDesc->funcdesc.cScodes = 0;
8448 pFuncDesc->funcdesc.wFuncFlags = 0;
8449 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8450 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8451 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8452 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8453 md->cArgs * sizeof(ELEMDESC));
8454 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8455 for(param = 0; param < md->cArgs; param++) {
8456 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8457 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8459 pFuncDesc->helpcontext = 0;
8460 pFuncDesc->HelpStringContext = 0;
8461 pFuncDesc->HelpString = NULL;
8462 pFuncDesc->Entry = NULL;
8463 list_init(&pFuncDesc->custdata_list);
8464 pTIIface->cFuncs++;
8465 ++pFuncDesc;
8468 dump_TypeInfo(pTIIface);
8470 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8471 pTIClass->pTypeLib = pTypeLibImpl;
8472 pTIClass->index = 1;
8473 pTIClass->Name = NULL;
8474 pTIClass->dwHelpContext = -1;
8475 pTIClass->guid = NULL;
8476 pTIClass->lcid = lcid;
8477 pTIClass->typekind = TKIND_COCLASS;
8478 pTIClass->wMajorVerNum = 0;
8479 pTIClass->wMinorVerNum = 0;
8480 pTIClass->cbAlignment = 2;
8481 pTIClass->cbSizeInstance = -1;
8482 pTIClass->cbSizeVft = -1;
8483 pTIClass->cFuncs = 0;
8484 pTIClass->cImplTypes = 1;
8485 pTIClass->cVars = 0;
8486 pTIClass->wTypeFlags = 0;
8487 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8489 pTIClass->impltypes = TLBImplType_Alloc(1);
8491 ref = heap_alloc_zero(sizeof(*ref));
8492 ref->pImpTLInfo = TLB_REF_INTERNAL;
8493 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8495 dump_TypeInfo(pTIClass);
8497 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8499 ITypeInfo_AddRef(*pptinfo);
8500 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8502 return S_OK;
8506 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8508 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8510 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8513 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8515 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8517 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8520 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8522 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8524 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8527 static HRESULT WINAPI ITypeComp_fnBind(
8528 ITypeComp * iface,
8529 OLECHAR * szName,
8530 ULONG lHash,
8531 WORD wFlags,
8532 ITypeInfo ** ppTInfo,
8533 DESCKIND * pDescKind,
8534 BINDPTR * pBindPtr)
8536 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8537 const TLBFuncDesc *pFDesc;
8538 const TLBVarDesc *pVDesc;
8539 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8540 UINT fdc;
8542 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8544 *pDescKind = DESCKIND_NONE;
8545 pBindPtr->lpfuncdesc = NULL;
8546 *ppTInfo = NULL;
8548 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8549 pFDesc = &This->funcdescs[fdc];
8550 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8551 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8552 break;
8553 else
8554 /* name found, but wrong flags */
8555 hr = TYPE_E_TYPEMISMATCH;
8559 if (fdc < This->cFuncs)
8561 HRESULT hr = TLB_AllocAndInitFuncDesc(
8562 &pFDesc->funcdesc,
8563 &pBindPtr->lpfuncdesc,
8564 This->typekind == TKIND_DISPATCH);
8565 if (FAILED(hr))
8566 return hr;
8567 *pDescKind = DESCKIND_FUNCDESC;
8568 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8569 ITypeInfo_AddRef(*ppTInfo);
8570 return S_OK;
8571 } else {
8572 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8573 if(pVDesc){
8574 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8575 if (FAILED(hr))
8576 return hr;
8577 *pDescKind = DESCKIND_VARDESC;
8578 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8579 ITypeInfo_AddRef(*ppTInfo);
8580 return S_OK;
8584 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8585 /* recursive search */
8586 ITypeInfo *pTInfo;
8587 ITypeComp *pTComp;
8588 HRESULT hr;
8589 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8590 if (SUCCEEDED(hr))
8592 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8593 ITypeInfo_Release(pTInfo);
8595 if (SUCCEEDED(hr))
8597 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8598 ITypeComp_Release(pTComp);
8599 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8600 This->typekind == TKIND_DISPATCH)
8602 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8603 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8604 SysFreeString((BSTR)tmp);
8606 return hr;
8608 WARN("Could not search inherited interface!\n");
8610 if (hr == DISP_E_MEMBERNOTFOUND)
8611 hr = S_OK;
8612 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8613 return hr;
8616 static HRESULT WINAPI ITypeComp_fnBindType(
8617 ITypeComp * iface,
8618 OLECHAR * szName,
8619 ULONG lHash,
8620 ITypeInfo ** ppTInfo,
8621 ITypeComp ** ppTComp)
8623 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8625 /* strange behaviour (does nothing) but like the
8626 * original */
8628 if (!ppTInfo || !ppTComp)
8629 return E_POINTER;
8631 *ppTInfo = NULL;
8632 *ppTComp = NULL;
8634 return S_OK;
8637 static const ITypeCompVtbl tcompvt =
8640 ITypeComp_fnQueryInterface,
8641 ITypeComp_fnAddRef,
8642 ITypeComp_fnRelease,
8644 ITypeComp_fnBind,
8645 ITypeComp_fnBindType
8648 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8649 ICreateTypeLib2** ppctlib)
8651 ITypeLibImpl *This;
8652 HRESULT hres;
8654 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8656 if (!szFile) return E_INVALIDARG;
8658 This = TypeLibImpl_Constructor();
8659 if (!This)
8660 return E_OUTOFMEMORY;
8662 This->lcid = GetSystemDefaultLCID();
8663 This->syskind = syskind;
8664 This->ptr_size = get_ptr_size(syskind);
8666 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8667 if (!This->path) {
8668 ITypeLib2_Release(&This->ITypeLib2_iface);
8669 return E_OUTOFMEMORY;
8671 lstrcpyW(This->path, szFile);
8673 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8674 ITypeLib2_Release(&This->ITypeLib2_iface);
8675 return hres;
8678 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8679 REFIID riid, void **object)
8681 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8683 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8686 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8688 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8690 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8693 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8695 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8697 return ITypeLib2_Release(&This->ITypeLib2_iface);
8700 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8701 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8703 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8704 ITypeInfoImpl *info;
8705 HRESULT hres;
8707 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8709 if (!ctinfo || !name)
8710 return E_INVALIDARG;
8712 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8713 if (info)
8714 return TYPE_E_NAMECONFLICT;
8716 if (This->typeinfos)
8717 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8718 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8719 else
8720 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8722 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8724 info->pTypeLib = This;
8725 info->Name = TLB_append_str(&This->name_list, name);
8726 info->index = This->TypeInfoCount;
8727 info->typekind = kind;
8728 info->cbAlignment = 4;
8730 switch(info->typekind) {
8731 case TKIND_ENUM:
8732 case TKIND_INTERFACE:
8733 case TKIND_DISPATCH:
8734 case TKIND_COCLASS:
8735 info->cbSizeInstance = This->ptr_size;
8736 break;
8737 case TKIND_RECORD:
8738 case TKIND_UNION:
8739 info->cbSizeInstance = 0;
8740 break;
8741 case TKIND_MODULE:
8742 info->cbSizeInstance = 2;
8743 break;
8744 case TKIND_ALIAS:
8745 info->cbSizeInstance = -0x75;
8746 break;
8747 default:
8748 FIXME("unrecognized typekind %d\n", info->typekind);
8749 info->cbSizeInstance = 0xdeadbeef;
8750 break;
8753 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8754 &IID_ICreateTypeInfo, (void **)ctinfo);
8755 if (FAILED(hres)) {
8756 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8757 return hres;
8760 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8762 ++This->TypeInfoCount;
8764 return S_OK;
8767 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8768 LPOLESTR name)
8770 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8772 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8774 if (!name)
8775 return E_INVALIDARG;
8777 This->Name = TLB_append_str(&This->name_list, name);
8779 return S_OK;
8782 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8783 WORD majorVerNum, WORD minorVerNum)
8785 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8787 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8789 This->ver_major = majorVerNum;
8790 This->ver_minor = minorVerNum;
8792 return S_OK;
8795 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8796 REFGUID guid)
8798 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8800 TRACE("%p %s\n", This, debugstr_guid(guid));
8802 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8804 return S_OK;
8807 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8808 LPOLESTR doc)
8810 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8812 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8814 if (!doc)
8815 return E_INVALIDARG;
8817 This->DocString = TLB_append_str(&This->string_list, doc);
8819 return S_OK;
8822 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8823 LPOLESTR helpFileName)
8825 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8827 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8829 if (!helpFileName)
8830 return E_INVALIDARG;
8832 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8834 return S_OK;
8837 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8838 DWORD helpContext)
8840 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8842 TRACE("%p %d\n", This, helpContext);
8844 This->dwHelpContext = helpContext;
8846 return S_OK;
8849 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8850 LCID lcid)
8852 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8854 TRACE("%p %x\n", This, lcid);
8856 This->set_lcid = lcid;
8858 return S_OK;
8861 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8862 UINT libFlags)
8864 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8866 TRACE("%p %x\n", This, libFlags);
8868 This->libflags = libFlags;
8870 return S_OK;
8873 typedef struct tagWMSFT_SegContents {
8874 DWORD len;
8875 void *data;
8876 } WMSFT_SegContents;
8878 typedef struct tagWMSFT_TLBFile {
8879 MSFT_Header header;
8880 WMSFT_SegContents typeinfo_seg;
8881 WMSFT_SegContents impfile_seg;
8882 WMSFT_SegContents impinfo_seg;
8883 WMSFT_SegContents ref_seg;
8884 WMSFT_SegContents guidhash_seg;
8885 WMSFT_SegContents guid_seg;
8886 WMSFT_SegContents namehash_seg;
8887 WMSFT_SegContents name_seg;
8888 WMSFT_SegContents string_seg;
8889 WMSFT_SegContents typdesc_seg;
8890 WMSFT_SegContents arraydesc_seg;
8891 WMSFT_SegContents custdata_seg;
8892 WMSFT_SegContents cdguids_seg;
8893 MSFT_SegDir segdir;
8894 WMSFT_SegContents aux_seg;
8895 } WMSFT_TLBFile;
8897 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8898 WMSFT_TLBFile *file)
8900 TLBString *str;
8901 UINT last_offs;
8902 char *data;
8904 file->string_seg.len = 0;
8905 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8906 int size;
8908 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8909 if (size == 0)
8910 return E_UNEXPECTED;
8912 size += sizeof(INT16);
8913 if (size % 4)
8914 size = (size + 4) & ~0x3;
8915 if (size < 8)
8916 size = 8;
8918 file->string_seg.len += size;
8920 /* temporarily use str->offset to store the length of the aligned,
8921 * converted string */
8922 str->offset = size;
8925 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8927 last_offs = 0;
8928 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8929 int size;
8931 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8932 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8933 if (size == 0) {
8934 heap_free(file->string_seg.data);
8935 return E_UNEXPECTED;
8938 *((INT16*)data) = size;
8940 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8942 size = str->offset;
8943 data += size;
8944 str->offset = last_offs;
8945 last_offs += size;
8948 return S_OK;
8951 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8952 WMSFT_TLBFile *file)
8954 TLBString *str;
8955 UINT last_offs;
8956 char *data;
8957 MSFT_NameIntro *last_intro = NULL;
8959 file->header.nametablecount = 0;
8960 file->header.nametablechars = 0;
8962 file->name_seg.len = 0;
8963 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8964 int size;
8966 size = strlenW(str->str);
8967 file->header.nametablechars += size;
8968 file->header.nametablecount++;
8970 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8971 if (size == 0)
8972 return E_UNEXPECTED;
8974 size += sizeof(MSFT_NameIntro);
8975 if (size % 4)
8976 size = (size + 4) & ~0x3;
8977 if (size < 8)
8978 size = 8;
8980 file->name_seg.len += size;
8982 /* temporarily use str->offset to store the length of the aligned,
8983 * converted string */
8984 str->offset = size;
8987 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8988 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8990 last_offs = 0;
8991 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8992 int size, hash;
8993 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8995 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8996 data + sizeof(MSFT_NameIntro),
8997 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8998 if (size == 0) {
8999 heap_free(file->name_seg.data);
9000 return E_UNEXPECTED;
9002 data[sizeof(MSFT_NameIntro) + size] = '\0';
9004 intro->hreftype = -1; /* TODO? */
9005 intro->namelen = size & 0xFF;
9006 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9007 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9008 intro->namelen |= hash << 16;
9009 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9010 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9012 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9013 str->offset - size - sizeof(MSFT_NameIntro));
9015 /* update str->offset to actual value to use in other
9016 * compilation functions that require positions within
9017 * the string table */
9018 last_intro = intro;
9019 size = str->offset;
9020 data += size;
9021 str->offset = last_offs;
9022 last_offs += size;
9025 if(last_intro)
9026 last_intro->hreftype = 0; /* last one is 0? */
9028 return S_OK;
9031 static inline int hash_guid(GUID *guid)
9033 int i, hash = 0;
9035 for (i = 0; i < 8; i ++)
9036 hash ^= ((const short *)guid)[i];
9038 return hash & 0x1f;
9041 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9043 TLBGuid *guid;
9044 MSFT_GuidEntry *entry;
9045 DWORD offs;
9046 int hash_key, *guidhashtab;
9048 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9049 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9051 entry = file->guid_seg.data;
9052 offs = 0;
9053 guidhashtab = file->guidhash_seg.data;
9054 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9055 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9056 entry->hreftype = guid->hreftype;
9058 hash_key = hash_guid(&guid->guid);
9059 entry->next_hash = guidhashtab[hash_key];
9060 guidhashtab[hash_key] = offs;
9062 guid->offset = offs;
9063 offs += sizeof(MSFT_GuidEntry);
9064 ++entry;
9067 return S_OK;
9070 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9072 VARIANT v = *value;
9073 VARTYPE arg_type = V_VT(value);
9074 int mask = 0;
9075 HRESULT hres;
9076 DWORD ret = file->custdata_seg.len;
9078 if(arg_type == VT_INT)
9079 arg_type = VT_I4;
9080 if(arg_type == VT_UINT)
9081 arg_type = VT_UI4;
9083 v = *value;
9084 if(V_VT(value) != arg_type) {
9085 hres = VariantChangeType(&v, value, 0, arg_type);
9086 if(FAILED(hres)){
9087 ERR("VariantChangeType failed: %08x\n", hres);
9088 return -1;
9092 /* Check if default value can be stored in-place */
9093 switch(arg_type){
9094 case VT_I4:
9095 case VT_UI4:
9096 mask = 0x3ffffff;
9097 if(V_UI4(&v) > 0x3ffffff)
9098 break;
9099 /* fall through */
9100 case VT_I1:
9101 case VT_UI1:
9102 case VT_BOOL:
9103 if(!mask)
9104 mask = 0xff;
9105 /* fall through */
9106 case VT_I2:
9107 case VT_UI2:
9108 if(!mask)
9109 mask = 0xffff;
9110 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9113 /* have to allocate space in custdata_seg */
9114 switch(arg_type) {
9115 case VT_I4:
9116 case VT_R4:
9117 case VT_UI4:
9118 case VT_INT:
9119 case VT_UINT:
9120 case VT_HRESULT:
9121 case VT_PTR: {
9122 /* Construct the data to be allocated */
9123 int *data;
9125 if(file->custdata_seg.data){
9126 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9127 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9128 file->custdata_seg.len += sizeof(int) * 2;
9129 }else{
9130 file->custdata_seg.len = sizeof(int) * 2;
9131 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9134 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9135 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9137 /* TODO: Check if the encoded data is already present in custdata_seg */
9139 return ret;
9142 case VT_BSTR: {
9143 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9144 char *data;
9146 if(file->custdata_seg.data){
9147 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9148 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9149 file->custdata_seg.len += len;
9150 }else{
9151 file->custdata_seg.len = len;
9152 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9155 *((unsigned short *)data) = V_VT(value);
9156 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9157 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9158 if(V_BSTR(&v)[i] <= 0x7f)
9159 data[i+6] = V_BSTR(&v)[i];
9160 else
9161 data[i+6] = '?';
9163 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9164 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9165 data[i] = 0x57;
9167 /* TODO: Check if the encoded data is already present in custdata_seg */
9169 return ret;
9171 default:
9172 FIXME("Argument type not yet handled\n");
9173 return -1;
9177 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9179 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9181 DWORD offs = file->arraydesc_seg.len;
9182 DWORD *encoded;
9183 USHORT i;
9185 /* TODO: we should check for duplicates, but that's harder because each
9186 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9187 * at the library-level) */
9189 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9190 if(!file->arraydesc_seg.data)
9191 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9192 else
9193 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9194 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9196 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9197 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9198 for(i = 0; i < desc->cDims; ++i){
9199 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9200 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9203 return offs;
9206 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9208 DWORD junk;
9209 INT16 junk2;
9210 DWORD offs = 0;
9211 DWORD encoded[2];
9212 VARTYPE vt, subtype;
9213 char *data;
9215 if(!desc)
9216 return -1;
9218 if(!out_mix)
9219 out_mix = &junk;
9220 if(!out_size)
9221 out_size = &junk2;
9223 vt = desc->vt & VT_TYPEMASK;
9225 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9226 DWORD mix;
9227 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9228 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9229 *out_mix = 0x7FFF;
9230 *out_size += 2 * sizeof(DWORD);
9231 }else if(vt == VT_CARRAY){
9232 encoded[0] = desc->vt | (0x7FFE << 16);
9233 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9234 *out_mix = 0x7FFE;
9235 }else if(vt == VT_USERDEFINED){
9236 encoded[0] = desc->vt | (0x7FFF << 16);
9237 encoded[1] = desc->u.hreftype;
9238 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9239 }else{
9240 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9242 switch(vt){
9243 case VT_INT:
9244 subtype = VT_I4;
9245 break;
9246 case VT_UINT:
9247 subtype = VT_UI4;
9248 break;
9249 case VT_VOID:
9250 subtype = VT_EMPTY;
9251 break;
9252 default:
9253 subtype = vt;
9254 break;
9257 *out_mix = subtype;
9258 return 0x80000000 | (subtype << 16) | desc->vt;
9261 data = file->typdesc_seg.data;
9262 while(offs < file->typdesc_seg.len){
9263 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9264 return offs;
9265 offs += sizeof(encoded);
9268 file->typdesc_seg.len += sizeof(encoded);
9269 if(!file->typdesc_seg.data)
9270 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9271 else
9272 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9274 memcpy(&data[offs], encoded, sizeof(encoded));
9276 return offs;
9279 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9281 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9282 DWORD ret = cdguids_seg->len, offs;
9283 MSFT_CDGuid *cdguid;
9284 TLBCustData *cd;
9286 if(list_empty(custdata_list))
9287 return -1;
9289 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9290 if(!cdguids_seg->data){
9291 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9292 }else {
9293 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9294 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9297 offs = ret + sizeof(MSFT_CDGuid);
9298 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9299 cdguid->GuidOffset = cd->guid->offset;
9300 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9301 cdguid->next = offs;
9302 offs += sizeof(MSFT_CDGuid);
9303 ++cdguid;
9306 --cdguid;
9307 cdguid->next = -1;
9309 return ret;
9312 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9313 WMSFT_TLBFile *file)
9315 WMSFT_SegContents *aux_seg = &file->aux_seg;
9316 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9317 MSFT_VarRecord *varrecord;
9318 MSFT_FuncRecord *funcrecord;
9319 MEMBERID *memid;
9320 DWORD *name, *offsets, offs;
9322 for(i = 0; i < info->cFuncs; ++i){
9323 TLBFuncDesc *desc = &info->funcdescs[i];
9325 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9327 /* optional fields */
9328 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9329 if(!list_empty(&desc->custdata_list))
9330 recorded_size += 7 * sizeof(INT);
9331 else if(desc->HelpStringContext != 0)
9332 recorded_size += 6 * sizeof(INT);
9333 /* res9? resA? */
9334 else if(desc->Entry)
9335 recorded_size += 3 * sizeof(INT);
9336 else if(desc->HelpString)
9337 recorded_size += 2 * sizeof(INT);
9338 else if(desc->helpcontext)
9339 recorded_size += sizeof(INT);
9341 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9343 for(j = 0; j < desc->funcdesc.cParams; ++j){
9344 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9345 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9346 break;
9350 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9353 for(i = 0; i < info->cVars; ++i){
9354 TLBVarDesc *desc = &info->vardescs[i];
9356 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9358 /* optional fields */
9359 if(desc->HelpStringContext != 0)
9360 recorded_size += 5 * sizeof(INT);
9361 else if(!list_empty(&desc->custdata_list))
9362 recorded_size += 4 * sizeof(INT);
9363 /* res9? */
9364 else if(desc->HelpString)
9365 recorded_size += 2 * sizeof(INT);
9366 else if(desc->HelpContext != 0)
9367 recorded_size += sizeof(INT);
9369 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9372 if(!recorded_size && !extra_size)
9373 return ret;
9375 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9377 aux_seg->len += recorded_size + extra_size;
9379 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9381 if(aux_seg->data)
9382 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9383 else
9384 aux_seg->data = heap_alloc(aux_seg->len);
9386 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9388 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9389 offs = 0;
9391 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9392 for(i = 0; i < info->cFuncs; ++i){
9393 TLBFuncDesc *desc = &info->funcdescs[i];
9394 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9396 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9397 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9398 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9399 funcrecord->VtableOffset = desc->funcdesc.oVft;
9401 /* FKCCIC:
9402 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9403 * ^^^funckind
9404 * ^^^ ^invkind
9405 * ^has_cust_data
9406 * ^^^^callconv
9407 * ^has_param_defaults
9408 * ^oEntry_is_intresource
9410 funcrecord->FKCCIC =
9411 desc->funcdesc.funckind |
9412 (desc->funcdesc.invkind << 3) |
9413 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9414 (desc->funcdesc.callconv << 8);
9416 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9417 funcrecord->FKCCIC |= 0x2000;
9419 for(j = 0; j < desc->funcdesc.cParams; ++j){
9420 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9421 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9422 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9425 if(paramdefault_size > 0)
9426 funcrecord->FKCCIC |= 0x1000;
9428 funcrecord->nrargs = desc->funcdesc.cParams;
9429 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9431 /* optional fields */
9432 /* res9? resA? */
9433 if(!list_empty(&desc->custdata_list)){
9434 size += 7 * sizeof(INT);
9435 funcrecord->HelpContext = desc->helpcontext;
9436 if(desc->HelpString)
9437 funcrecord->oHelpString = desc->HelpString->offset;
9438 else
9439 funcrecord->oHelpString = -1;
9440 if(!desc->Entry)
9441 funcrecord->oEntry = -1;
9442 else if(IS_INTRESOURCE(desc->Entry))
9443 funcrecord->oEntry = LOWORD(desc->Entry);
9444 else
9445 funcrecord->oEntry = desc->Entry->offset;
9446 funcrecord->res9 = -1;
9447 funcrecord->resA = -1;
9448 funcrecord->HelpStringContext = desc->HelpStringContext;
9449 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9450 }else if(desc->HelpStringContext != 0){
9451 size += 6 * sizeof(INT);
9452 funcrecord->HelpContext = desc->helpcontext;
9453 if(desc->HelpString)
9454 funcrecord->oHelpString = desc->HelpString->offset;
9455 else
9456 funcrecord->oHelpString = -1;
9457 if(!desc->Entry)
9458 funcrecord->oEntry = -1;
9459 else if(IS_INTRESOURCE(desc->Entry))
9460 funcrecord->oEntry = LOWORD(desc->Entry);
9461 else
9462 funcrecord->oEntry = desc->Entry->offset;
9463 funcrecord->res9 = -1;
9464 funcrecord->resA = -1;
9465 funcrecord->HelpStringContext = desc->HelpStringContext;
9466 }else if(desc->Entry){
9467 size += 3 * sizeof(INT);
9468 funcrecord->HelpContext = desc->helpcontext;
9469 if(desc->HelpString)
9470 funcrecord->oHelpString = desc->HelpString->offset;
9471 else
9472 funcrecord->oHelpString = -1;
9473 if(!desc->Entry)
9474 funcrecord->oEntry = -1;
9475 else if(IS_INTRESOURCE(desc->Entry))
9476 funcrecord->oEntry = LOWORD(desc->Entry);
9477 else
9478 funcrecord->oEntry = desc->Entry->offset;
9479 }else if(desc->HelpString){
9480 size += 2 * sizeof(INT);
9481 funcrecord->HelpContext = desc->helpcontext;
9482 funcrecord->oHelpString = desc->HelpString->offset;
9483 }else if(desc->helpcontext){
9484 size += sizeof(INT);
9485 funcrecord->HelpContext = desc->helpcontext;
9488 paramdefault = (DWORD*)((char *)funcrecord + size);
9489 size += paramdefault_size;
9491 for(j = 0; j < desc->funcdesc.cParams; ++j){
9492 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9494 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9495 if(desc->pParamDesc[j].Name)
9496 info->oName = desc->pParamDesc[j].Name->offset;
9497 else
9498 info->oName = -1;
9499 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9501 if(paramdefault_size){
9502 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9503 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9504 else if(paramdefault_size)
9505 *paramdefault = -1;
9506 ++paramdefault;
9509 size += sizeof(MSFT_ParameterInfo);
9512 funcrecord->Info = size | (i << 16); /* is it just the index? */
9514 *offsets = offs;
9515 offs += size;
9516 ++offsets;
9518 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9521 varrecord = (MSFT_VarRecord*)funcrecord;
9522 for(i = 0; i < info->cVars; ++i){
9523 TLBVarDesc *desc = &info->vardescs[i];
9524 DWORD size = 5 * sizeof(INT);
9526 varrecord->vardescsize = sizeof(desc->vardesc);
9527 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9528 varrecord->Flags = desc->vardesc.wVarFlags;
9529 varrecord->VarKind = desc->vardesc.varkind;
9531 if(desc->vardesc.varkind == VAR_CONST){
9532 varrecord->vardescsize += sizeof(VARIANT);
9533 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9534 }else
9535 varrecord->OffsValue = desc->vardesc.u.oInst;
9537 /* res9? */
9538 if(desc->HelpStringContext != 0){
9539 size += 5 * sizeof(INT);
9540 varrecord->HelpContext = desc->HelpContext;
9541 if(desc->HelpString)
9542 varrecord->HelpString = desc->HelpString->offset;
9543 else
9544 varrecord->HelpString = -1;
9545 varrecord->res9 = -1;
9546 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9547 varrecord->HelpStringContext = desc->HelpStringContext;
9548 }else if(!list_empty(&desc->custdata_list)){
9549 size += 4 * sizeof(INT);
9550 varrecord->HelpContext = desc->HelpContext;
9551 if(desc->HelpString)
9552 varrecord->HelpString = desc->HelpString->offset;
9553 else
9554 varrecord->HelpString = -1;
9555 varrecord->res9 = -1;
9556 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9557 }else if(desc->HelpString){
9558 size += 2 * sizeof(INT);
9559 varrecord->HelpContext = desc->HelpContext;
9560 if(desc->HelpString)
9561 varrecord->HelpString = desc->HelpString->offset;
9562 else
9563 varrecord->HelpString = -1;
9564 }else if(desc->HelpContext != 0){
9565 size += sizeof(INT);
9566 varrecord->HelpContext = desc->HelpContext;
9569 varrecord->Info = size | (i << 16);
9571 *offsets = offs;
9572 offs += size;
9573 ++offsets;
9575 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9578 memid = (MEMBERID*)varrecord;
9579 for(i = 0; i < info->cFuncs; ++i){
9580 TLBFuncDesc *desc = &info->funcdescs[i];
9581 *memid = desc->funcdesc.memid;
9582 ++memid;
9584 for(i = 0; i < info->cVars; ++i){
9585 TLBVarDesc *desc = &info->vardescs[i];
9586 *memid = desc->vardesc.memid;
9587 ++memid;
9590 name = (UINT*)memid;
9591 for(i = 0; i < info->cFuncs; ++i){
9592 TLBFuncDesc *desc = &info->funcdescs[i];
9593 if(desc->Name)
9594 *name = desc->Name->offset;
9595 else
9596 *name = -1;
9597 ++name;
9599 for(i = 0; i < info->cVars; ++i){
9600 TLBVarDesc *desc = &info->vardescs[i];
9601 if(desc->Name)
9602 *name = desc->Name->offset;
9603 else
9604 *name = -1;
9605 ++name;
9608 return ret;
9611 typedef struct tagWMSFT_RefChunk {
9612 DWORD href;
9613 DWORD res04;
9614 DWORD res08;
9615 DWORD next;
9616 } WMSFT_RefChunk;
9618 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9620 DWORD offs = file->ref_seg.len, i;
9621 WMSFT_RefChunk *chunk;
9623 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9624 if(!file->ref_seg.data)
9625 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9626 else
9627 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9629 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9631 for(i = 0; i < info->cImplTypes; ++i){
9632 chunk->href = info->impltypes[i].hRef;
9633 chunk->res04 = info->impltypes[i].implflags;
9634 chunk->res08 = -1;
9635 if(i < info->cImplTypes - 1)
9636 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9637 else
9638 chunk->next = -1;
9639 ++chunk;
9642 return offs;
9645 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9647 DWORD size;
9649 size = sizeof(MSFT_TypeInfoBase);
9651 if(data){
9652 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9653 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9654 base->typekind = TKIND_DISPATCH;
9655 else
9656 base->typekind = info->typekind;
9657 base->typekind |= index << 16; /* TODO: There are some other flags here */
9658 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9659 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9660 base->res2 = 0;
9661 base->res3 = 0;
9662 base->res4 = 3;
9663 base->res5 = 0;
9664 base->cElement = (info->cVars << 16) | info->cFuncs;
9665 base->res7 = 0;
9666 base->res8 = 0;
9667 base->res9 = 0;
9668 base->resA = 0;
9669 if(info->guid)
9670 base->posguid = info->guid->offset;
9671 else
9672 base->posguid = -1;
9673 base->flags = info->wTypeFlags;
9674 if(info->Name) {
9675 base->NameOffset = info->Name->offset;
9677 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9678 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9679 }else {
9680 base->NameOffset = -1;
9682 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9683 if(info->DocString)
9684 base->docstringoffs = info->DocString->offset;
9685 else
9686 base->docstringoffs = -1;
9687 base->helpstringcontext = info->dwHelpStringContext;
9688 base->helpcontext = info->dwHelpContext;
9689 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9690 base->cImplTypes = info->cImplTypes;
9691 base->cbSizeVft = info->cbSizeVft;
9692 base->size = info->cbSizeInstance;
9693 if(info->typekind == TKIND_COCLASS){
9694 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9695 }else if(info->typekind == TKIND_ALIAS){
9696 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9697 }else if(info->typekind == TKIND_MODULE){
9698 if(info->DllName)
9699 base->datatype1 = info->DllName->offset;
9700 else
9701 base->datatype1 = -1;
9702 }else{
9703 if(info->cImplTypes > 0)
9704 base->datatype1 = info->impltypes[0].hRef;
9705 else
9706 base->datatype1 = -1;
9708 base->datatype2 = index; /* FIXME: i think there's more here */
9709 base->res18 = 0;
9710 base->res19 = -1;
9713 return size;
9716 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9718 UINT i;
9720 file->typeinfo_seg.len = 0;
9721 for(i = 0; i < This->TypeInfoCount; ++i){
9722 ITypeInfoImpl *info = This->typeinfos[i];
9723 *junk = file->typeinfo_seg.len;
9724 ++junk;
9725 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9728 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9729 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9731 file->aux_seg.len = 0;
9732 file->aux_seg.data = NULL;
9734 file->typeinfo_seg.len = 0;
9735 for(i = 0; i < This->TypeInfoCount; ++i){
9736 ITypeInfoImpl *info = This->typeinfos[i];
9737 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9738 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9742 typedef struct tagWMSFT_ImpFile {
9743 INT guid_offs;
9744 LCID lcid;
9745 DWORD version;
9746 } WMSFT_ImpFile;
9748 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9750 TLBImpLib *implib;
9751 WMSFT_ImpFile *impfile;
9752 char *data;
9753 DWORD last_offs = 0;
9755 file->impfile_seg.len = 0;
9756 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9757 int size = 0;
9759 if(implib->name){
9760 WCHAR *path = strrchrW(implib->name, '\\');
9761 if(path)
9762 ++path;
9763 else
9764 path = implib->name;
9765 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9766 if (size == 0)
9767 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9770 size += sizeof(INT16);
9771 if (size % 4)
9772 size = (size + 4) & ~0x3;
9773 if (size < 8)
9774 size = 8;
9776 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9779 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9781 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9782 int strlen = 0, size;
9784 impfile = (WMSFT_ImpFile*)data;
9785 impfile->guid_offs = implib->guid->offset;
9786 impfile->lcid = implib->lcid;
9787 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9789 data += sizeof(WMSFT_ImpFile);
9791 if(implib->name){
9792 WCHAR *path= strrchrW(implib->name, '\\');
9793 if(path)
9794 ++path;
9795 else
9796 path = implib->name;
9797 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9798 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9799 if (strlen == 0)
9800 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9803 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9805 size = strlen + sizeof(INT16);
9806 if (size % 4)
9807 size = (size + 4) & ~0x3;
9808 if (size < 8)
9809 size = 8;
9810 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9812 data += size;
9813 implib->offset = last_offs;
9814 last_offs += size + sizeof(WMSFT_ImpFile);
9818 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9820 MSFT_ImpInfo *info;
9821 TLBRefType *ref_type;
9822 UINT i = 0;
9824 WMSFT_compile_impfile(This, file);
9826 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9827 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9829 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9830 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9831 if(ref_type->index == TLB_REF_USE_GUID){
9832 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9833 info->oGuid = ref_type->guid->offset;
9834 }else
9835 info->oGuid = ref_type->index;
9836 info->oImpFile = ref_type->pImpTLInfo->offset;
9837 ++i;
9838 ++info;
9842 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9844 file->guidhash_seg.len = 0x80;
9845 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9846 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9849 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9851 file->namehash_seg.len = 0x200;
9852 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9853 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9856 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9858 if(contents && contents->len){
9859 segdir->offset = *running_offset;
9860 segdir->length = contents->len;
9861 *running_offset += segdir->length;
9862 }else{
9863 segdir->offset = -1;
9864 segdir->length = 0;
9867 /* TODO: do these ever change? */
9868 segdir->res08 = -1;
9869 segdir->res0c = 0xf;
9872 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9874 DWORD written;
9875 if(segment)
9876 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9879 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9880 DWORD file_len)
9882 DWORD i;
9883 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9885 for(i = 0; i < This->TypeInfoCount; ++i){
9886 base->memoffset += file_len;
9887 ++base;
9890 return S_OK;
9893 static void WMSFT_free_file(WMSFT_TLBFile *file)
9895 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9896 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9897 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9898 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9899 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9900 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9901 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9902 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9903 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9904 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9905 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9906 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9907 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9908 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9911 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9913 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9914 WMSFT_TLBFile file;
9915 DWORD written, junk_size, junk_offs, running_offset;
9916 BOOL br;
9917 HANDLE outfile;
9918 HRESULT hres;
9919 DWORD *junk;
9920 UINT i;
9922 TRACE("%p\n", This);
9924 for(i = 0; i < This->TypeInfoCount; ++i)
9925 if(This->typeinfos[i]->needs_layout)
9926 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9928 memset(&file, 0, sizeof(file));
9930 file.header.magic1 = 0x5446534D;
9931 file.header.magic2 = 0x00010002;
9932 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9933 file.header.lcid2 = This->set_lcid;
9934 file.header.varflags = 0x40 | This->syskind;
9935 if (This->HelpFile)
9936 file.header.varflags |= 0x10;
9937 if (This->HelpStringDll)
9938 file.header.varflags |= HELPDLLFLAG;
9939 file.header.version = (This->ver_minor << 16) | This->ver_major;
9940 file.header.flags = This->libflags;
9941 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9942 file.header.helpcontext = This->dwHelpContext;
9943 file.header.res44 = 0x20;
9944 file.header.res48 = 0x80;
9945 file.header.dispatchpos = This->dispatch_href;
9947 WMSFT_compile_namehash(This, &file);
9948 /* do name and string compilation to get offsets for other compilations */
9949 hres = WMSFT_compile_names(This, &file);
9950 if (FAILED(hres)){
9951 WMSFT_free_file(&file);
9952 return hres;
9955 hres = WMSFT_compile_strings(This, &file);
9956 if (FAILED(hres)){
9957 WMSFT_free_file(&file);
9958 return hres;
9961 WMSFT_compile_guidhash(This, &file);
9962 hres = WMSFT_compile_guids(This, &file);
9963 if (FAILED(hres)){
9964 WMSFT_free_file(&file);
9965 return hres;
9968 if(This->HelpFile)
9969 file.header.helpfile = This->HelpFile->offset;
9970 else
9971 file.header.helpfile = -1;
9973 if(This->DocString)
9974 file.header.helpstring = This->DocString->offset;
9975 else
9976 file.header.helpstring = -1;
9978 /* do some more segment compilation */
9979 file.header.nimpinfos = list_count(&This->ref_list);
9980 file.header.nrtypeinfos = This->TypeInfoCount;
9982 if(This->Name)
9983 file.header.NameOffset = This->Name->offset;
9984 else
9985 file.header.NameOffset = -1;
9987 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
9989 if(This->guid)
9990 file.header.posguid = This->guid->offset;
9991 else
9992 file.header.posguid = -1;
9994 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9995 if(file.header.varflags & HELPDLLFLAG)
9996 junk_size += sizeof(DWORD);
9997 if(junk_size){
9998 junk = heap_alloc_zero(junk_size);
9999 if(file.header.varflags & HELPDLLFLAG){
10000 *junk = This->HelpStringDll->offset;
10001 junk_offs = 1;
10002 }else
10003 junk_offs = 0;
10004 }else{
10005 junk = NULL;
10006 junk_offs = 0;
10009 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10010 WMSFT_compile_impinfo(This, &file);
10012 running_offset = 0;
10014 TRACE("header at: 0x%x\n", running_offset);
10015 running_offset += sizeof(file.header);
10017 TRACE("junk at: 0x%x\n", running_offset);
10018 running_offset += junk_size;
10020 TRACE("segdir at: 0x%x\n", running_offset);
10021 running_offset += sizeof(file.segdir);
10023 TRACE("typeinfo at: 0x%x\n", running_offset);
10024 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10026 TRACE("guidhashtab at: 0x%x\n", running_offset);
10027 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10029 TRACE("guidtab at: 0x%x\n", running_offset);
10030 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10032 TRACE("reftab at: 0x%x\n", running_offset);
10033 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10035 TRACE("impinfo at: 0x%x\n", running_offset);
10036 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10038 TRACE("impfiles at: 0x%x\n", running_offset);
10039 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10041 TRACE("namehashtab at: 0x%x\n", running_offset);
10042 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10044 TRACE("nametab at: 0x%x\n", running_offset);
10045 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10047 TRACE("stringtab at: 0x%x\n", running_offset);
10048 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10050 TRACE("typdesc at: 0x%x\n", running_offset);
10051 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10053 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10054 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10056 TRACE("custdata at: 0x%x\n", running_offset);
10057 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10059 TRACE("cdguids at: 0x%x\n", running_offset);
10060 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10062 TRACE("res0e at: 0x%x\n", running_offset);
10063 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10065 TRACE("res0f at: 0x%x\n", running_offset);
10066 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10068 TRACE("aux_seg at: 0x%x\n", running_offset);
10070 WMSFT_fixup_typeinfos(This, &file, running_offset);
10072 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10073 FILE_ATTRIBUTE_NORMAL, 0);
10074 if (outfile == INVALID_HANDLE_VALUE){
10075 WMSFT_free_file(&file);
10076 heap_free(junk);
10077 return TYPE_E_IOERROR;
10080 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10081 if (!br) {
10082 WMSFT_free_file(&file);
10083 CloseHandle(outfile);
10084 heap_free(junk);
10085 return TYPE_E_IOERROR;
10088 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10089 heap_free(junk);
10090 if (!br) {
10091 WMSFT_free_file(&file);
10092 CloseHandle(outfile);
10093 return TYPE_E_IOERROR;
10096 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10097 if (!br) {
10098 WMSFT_free_file(&file);
10099 CloseHandle(outfile);
10100 return TYPE_E_IOERROR;
10103 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10104 WMSFT_write_segment(outfile, &file.guidhash_seg);
10105 WMSFT_write_segment(outfile, &file.guid_seg);
10106 WMSFT_write_segment(outfile, &file.ref_seg);
10107 WMSFT_write_segment(outfile, &file.impinfo_seg);
10108 WMSFT_write_segment(outfile, &file.impfile_seg);
10109 WMSFT_write_segment(outfile, &file.namehash_seg);
10110 WMSFT_write_segment(outfile, &file.name_seg);
10111 WMSFT_write_segment(outfile, &file.string_seg);
10112 WMSFT_write_segment(outfile, &file.typdesc_seg);
10113 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10114 WMSFT_write_segment(outfile, &file.custdata_seg);
10115 WMSFT_write_segment(outfile, &file.cdguids_seg);
10116 WMSFT_write_segment(outfile, &file.aux_seg);
10118 WMSFT_free_file(&file);
10120 CloseHandle(outfile);
10122 return S_OK;
10125 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10126 LPOLESTR name)
10128 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10129 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10130 return E_NOTIMPL;
10133 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10134 REFGUID guid, VARIANT *varVal)
10136 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10137 TLBGuid *tlbguid;
10139 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10141 if (!guid || !varVal)
10142 return E_INVALIDARG;
10144 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10146 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10149 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10150 ULONG helpStringContext)
10152 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10153 FIXME("%p %u - stub\n", This, helpStringContext);
10154 return E_NOTIMPL;
10157 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10158 LPOLESTR filename)
10160 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10161 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10163 if (!filename)
10164 return E_INVALIDARG;
10166 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10168 return S_OK;
10171 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10172 ICreateTypeLib2_fnQueryInterface,
10173 ICreateTypeLib2_fnAddRef,
10174 ICreateTypeLib2_fnRelease,
10175 ICreateTypeLib2_fnCreateTypeInfo,
10176 ICreateTypeLib2_fnSetName,
10177 ICreateTypeLib2_fnSetVersion,
10178 ICreateTypeLib2_fnSetGuid,
10179 ICreateTypeLib2_fnSetDocString,
10180 ICreateTypeLib2_fnSetHelpFileName,
10181 ICreateTypeLib2_fnSetHelpContext,
10182 ICreateTypeLib2_fnSetLcid,
10183 ICreateTypeLib2_fnSetLibFlags,
10184 ICreateTypeLib2_fnSaveAllChanges,
10185 ICreateTypeLib2_fnDeleteTypeInfo,
10186 ICreateTypeLib2_fnSetCustData,
10187 ICreateTypeLib2_fnSetHelpStringContext,
10188 ICreateTypeLib2_fnSetHelpStringDll
10191 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10192 REFIID riid, void **object)
10194 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10196 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10199 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10201 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10203 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10206 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10208 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10210 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10213 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10214 REFGUID guid)
10216 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10218 TRACE("%p %s\n", This, debugstr_guid(guid));
10220 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10222 return S_OK;
10225 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10226 UINT typeFlags)
10228 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10229 WORD old_flags;
10230 HRESULT hres;
10232 TRACE("%p %x\n", This, typeFlags);
10234 if (typeFlags & TYPEFLAG_FDUAL) {
10235 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10236 ITypeLib *stdole;
10237 ITypeInfo *dispatch;
10238 HREFTYPE hreftype;
10239 HRESULT hres;
10241 hres = LoadTypeLib(stdole2tlb, &stdole);
10242 if(FAILED(hres))
10243 return hres;
10245 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10246 ITypeLib_Release(stdole);
10247 if(FAILED(hres))
10248 return hres;
10250 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10251 ITypeInfo_Release(dispatch);
10252 if(FAILED(hres))
10253 return hres;
10256 old_flags = This->wTypeFlags;
10257 This->wTypeFlags = typeFlags;
10259 hres = ICreateTypeInfo2_LayOut(iface);
10260 if (FAILED(hres)) {
10261 This->wTypeFlags = old_flags;
10262 return hres;
10265 return S_OK;
10268 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10269 LPOLESTR doc)
10271 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10273 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10275 if (!doc)
10276 return E_INVALIDARG;
10278 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10280 return S_OK;
10283 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10284 DWORD helpContext)
10286 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10288 TRACE("%p %d\n", This, helpContext);
10290 This->dwHelpContext = helpContext;
10292 return S_OK;
10295 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10296 WORD majorVerNum, WORD minorVerNum)
10298 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10300 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10302 This->wMajorVerNum = majorVerNum;
10303 This->wMinorVerNum = minorVerNum;
10305 return S_OK;
10308 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10309 ITypeInfo *typeInfo, HREFTYPE *refType)
10311 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10312 UINT index;
10313 ITypeLib *container;
10314 TLBRefType *ref_type;
10315 TLBImpLib *implib;
10316 TYPEATTR *typeattr;
10317 TLIBATTR *libattr;
10318 HRESULT hres;
10320 TRACE("%p %p %p\n", This, typeInfo, refType);
10322 if (!typeInfo || !refType)
10323 return E_INVALIDARG;
10325 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10326 if (FAILED(hres))
10327 return hres;
10329 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10330 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10332 ITypeLib_Release(container);
10334 *refType = target->hreftype;
10336 return S_OK;
10339 hres = ITypeLib_GetLibAttr(container, &libattr);
10340 if (FAILED(hres)) {
10341 ITypeLib_Release(container);
10342 return hres;
10345 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10346 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10347 implib->lcid == libattr->lcid &&
10348 implib->wVersionMajor == libattr->wMajorVerNum &&
10349 implib->wVersionMinor == libattr->wMinorVerNum)
10350 break;
10353 if(&implib->entry == &This->pTypeLib->implib_list){
10354 implib = heap_alloc_zero(sizeof(TLBImpLib));
10356 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10357 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10358 implib->name = SysAllocString(our_container->path);
10359 }else{
10360 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10361 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10362 if(FAILED(hres)){
10363 implib->name = NULL;
10364 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10368 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10369 implib->lcid = libattr->lcid;
10370 implib->wVersionMajor = libattr->wMajorVerNum;
10371 implib->wVersionMinor = libattr->wMinorVerNum;
10373 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10376 ITypeLib_ReleaseTLibAttr(container, libattr);
10377 ITypeLib_Release(container);
10379 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10380 if (FAILED(hres))
10381 return hres;
10383 index = 0;
10384 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10385 if(ref_type->index == TLB_REF_USE_GUID &&
10386 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10387 ref_type->tkind == typeattr->typekind)
10388 break;
10389 ++index;
10392 if(&ref_type->entry == &This->pTypeLib->ref_list){
10393 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10395 ref_type->tkind = typeattr->typekind;
10396 ref_type->pImpTLInfo = implib;
10397 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10399 ref_type->index = TLB_REF_USE_GUID;
10401 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10403 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10406 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10408 *refType = ref_type->reference | 0x1;
10410 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10411 This->pTypeLib->dispatch_href = *refType;
10413 return S_OK;
10416 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10417 UINT index, FUNCDESC *funcDesc)
10419 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10420 TLBFuncDesc tmp_func_desc, *func_desc;
10421 int buf_size, i;
10422 char *buffer;
10423 HRESULT hres;
10425 TRACE("%p %u %p\n", This, index, funcDesc);
10427 if (!funcDesc || funcDesc->oVft & 3)
10428 return E_INVALIDARG;
10430 switch (This->typekind) {
10431 case TKIND_MODULE:
10432 if (funcDesc->funckind != FUNC_STATIC)
10433 return TYPE_E_BADMODULEKIND;
10434 break;
10435 case TKIND_DISPATCH:
10436 if (funcDesc->funckind != FUNC_DISPATCH)
10437 return TYPE_E_BADMODULEKIND;
10438 break;
10439 default:
10440 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10441 return TYPE_E_BADMODULEKIND;
10444 if (index > This->cFuncs)
10445 return TYPE_E_ELEMENTNOTFOUND;
10447 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10448 !funcDesc->cParams)
10449 return TYPE_E_INCONSISTENTPROPFUNCS;
10451 #ifdef _WIN64
10452 if(This->pTypeLib->syskind == SYS_WIN64 &&
10453 funcDesc->oVft % 8 != 0)
10454 return E_INVALIDARG;
10455 #endif
10457 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10458 TLBFuncDesc_Constructor(&tmp_func_desc);
10460 tmp_func_desc.funcdesc = *funcDesc;
10462 if (tmp_func_desc.funcdesc.oVft != 0)
10463 tmp_func_desc.funcdesc.oVft |= 1;
10465 if (funcDesc->cScodes) {
10466 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10467 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10468 } else
10469 tmp_func_desc.funcdesc.lprgscode = NULL;
10471 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10472 for (i = 0; i < funcDesc->cParams; ++i) {
10473 buf_size += sizeof(ELEMDESC);
10474 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10476 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10477 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10479 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10480 if (FAILED(hres)) {
10481 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10482 heap_free(tmp_func_desc.funcdesc.lprgscode);
10483 return hres;
10486 for (i = 0; i < funcDesc->cParams; ++i) {
10487 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10488 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10489 if (FAILED(hres)) {
10490 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10491 heap_free(tmp_func_desc.funcdesc.lprgscode);
10492 return hres;
10494 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10495 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10496 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10497 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10498 if (FAILED(hres)) {
10499 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10500 heap_free(tmp_func_desc.funcdesc.lprgscode);
10501 return hres;
10506 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10508 if (This->funcdescs) {
10509 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10510 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10512 if (index < This->cFuncs) {
10513 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10514 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10515 func_desc = This->funcdescs + index;
10516 } else
10517 func_desc = This->funcdescs + This->cFuncs;
10519 /* move custdata lists to the new memory location */
10520 for(i = 0; i < This->cFuncs + 1; ++i){
10521 if(index != i){
10522 TLBFuncDesc *fd = &This->funcdescs[i];
10523 if(fd->custdata_list.prev == fd->custdata_list.next)
10524 list_init(&fd->custdata_list);
10525 else{
10526 fd->custdata_list.prev->next = &fd->custdata_list;
10527 fd->custdata_list.next->prev = &fd->custdata_list;
10531 } else
10532 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10534 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10535 list_init(&func_desc->custdata_list);
10537 ++This->cFuncs;
10539 This->needs_layout = TRUE;
10541 return S_OK;
10544 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10545 UINT index, HREFTYPE refType)
10547 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10548 TLBImplType *impl_type;
10549 HRESULT hres;
10551 TRACE("%p %u %d\n", This, index, refType);
10553 switch(This->typekind){
10554 case TKIND_COCLASS: {
10555 if (index == -1) {
10556 FIXME("Unhandled index: -1\n");
10557 return E_NOTIMPL;
10560 if(index != This->cImplTypes)
10561 return TYPE_E_ELEMENTNOTFOUND;
10563 break;
10565 case TKIND_INTERFACE:
10566 case TKIND_DISPATCH:
10567 if (index != 0 || This->cImplTypes)
10568 return TYPE_E_ELEMENTNOTFOUND;
10569 break;
10570 default:
10571 FIXME("Unimplemented typekind: %d\n", This->typekind);
10572 return E_NOTIMPL;
10575 if (This->impltypes){
10576 UINT i;
10578 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10579 sizeof(TLBImplType) * (This->cImplTypes + 1));
10581 if (index < This->cImplTypes) {
10582 memmove(This->impltypes + index + 1, This->impltypes + index,
10583 (This->cImplTypes - index) * sizeof(TLBImplType));
10584 impl_type = This->impltypes + index;
10585 } else
10586 impl_type = This->impltypes + This->cImplTypes;
10588 /* move custdata lists to the new memory location */
10589 for(i = 0; i < This->cImplTypes + 1; ++i){
10590 if(index != i){
10591 TLBImplType *it = &This->impltypes[i];
10592 if(it->custdata_list.prev == it->custdata_list.next)
10593 list_init(&it->custdata_list);
10594 else{
10595 it->custdata_list.prev->next = &it->custdata_list;
10596 it->custdata_list.next->prev = &it->custdata_list;
10600 } else
10601 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10603 memset(impl_type, 0, sizeof(TLBImplType));
10604 TLBImplType_Constructor(impl_type);
10605 impl_type->hRef = refType;
10607 ++This->cImplTypes;
10609 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10610 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10612 hres = ICreateTypeInfo2_LayOut(iface);
10613 if (FAILED(hres))
10614 return hres;
10616 return S_OK;
10619 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10620 UINT index, INT implTypeFlags)
10622 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10623 TLBImplType *impl_type = &This->impltypes[index];
10625 TRACE("%p %u %x\n", This, index, implTypeFlags);
10627 if (This->typekind != TKIND_COCLASS)
10628 return TYPE_E_BADMODULEKIND;
10630 if (index >= This->cImplTypes)
10631 return TYPE_E_ELEMENTNOTFOUND;
10633 impl_type->implflags = implTypeFlags;
10635 return S_OK;
10638 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10639 WORD alignment)
10641 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10643 TRACE("%p %d\n", This, alignment);
10645 This->cbAlignment = alignment;
10647 return S_OK;
10650 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10651 LPOLESTR schema)
10653 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10655 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10657 if (!schema)
10658 return E_INVALIDARG;
10660 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10662 This->lpstrSchema = This->Schema->str;
10664 return S_OK;
10667 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10668 UINT index, VARDESC *varDesc)
10670 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10671 TLBVarDesc *var_desc;
10673 TRACE("%p %u %p\n", This, index, varDesc);
10675 if (This->vardescs){
10676 UINT i;
10678 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10679 sizeof(TLBVarDesc) * (This->cVars + 1));
10681 if (index < This->cVars) {
10682 memmove(This->vardescs + index + 1, This->vardescs + index,
10683 (This->cVars - index) * sizeof(TLBVarDesc));
10684 var_desc = This->vardescs + index;
10685 } else
10686 var_desc = This->vardescs + This->cVars;
10688 /* move custdata lists to the new memory location */
10689 for(i = 0; i < This->cVars + 1; ++i){
10690 if(index != i){
10691 TLBVarDesc *var = &This->vardescs[i];
10692 if(var->custdata_list.prev == var->custdata_list.next)
10693 list_init(&var->custdata_list);
10694 else{
10695 var->custdata_list.prev->next = &var->custdata_list;
10696 var->custdata_list.next->prev = &var->custdata_list;
10700 } else
10701 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10703 TLBVarDesc_Constructor(var_desc);
10704 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10705 var_desc->vardesc = *var_desc->vardesc_create;
10707 ++This->cVars;
10709 This->needs_layout = TRUE;
10711 return S_OK;
10714 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10715 UINT index, LPOLESTR *names, UINT numNames)
10717 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10718 TLBFuncDesc *func_desc = &This->funcdescs[index];
10719 int i;
10721 TRACE("%p %u %p %u\n", This, index, names, numNames);
10723 if (!names)
10724 return E_INVALIDARG;
10726 if (index >= This->cFuncs || numNames == 0)
10727 return TYPE_E_ELEMENTNOTFOUND;
10729 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10730 if(numNames > func_desc->funcdesc.cParams)
10731 return TYPE_E_ELEMENTNOTFOUND;
10732 } else
10733 if(numNames > func_desc->funcdesc.cParams + 1)
10734 return TYPE_E_ELEMENTNOTFOUND;
10736 for(i = 0; i < This->cFuncs; ++i) {
10737 TLBFuncDesc *iter = &This->funcdescs[i];
10738 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10739 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10740 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10741 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10742 continue;
10743 return TYPE_E_AMBIGUOUSNAME;
10747 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10749 for (i = 1; i < numNames; ++i) {
10750 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10751 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10754 return S_OK;
10757 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10758 UINT index, LPOLESTR name)
10760 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10762 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10764 if(!name)
10765 return E_INVALIDARG;
10767 if(index >= This->cVars)
10768 return TYPE_E_ELEMENTNOTFOUND;
10770 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10771 return S_OK;
10774 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10775 TYPEDESC *tdescAlias)
10777 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10778 HRESULT hr;
10780 TRACE("%p %p\n", This, tdescAlias);
10782 if(!tdescAlias)
10783 return E_INVALIDARG;
10785 if(This->typekind != TKIND_ALIAS)
10786 return TYPE_E_BADMODULEKIND;
10788 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->cbSizeInstance, &This->cbAlignment);
10789 if(FAILED(hr))
10790 return hr;
10792 heap_free(This->tdescAlias);
10793 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10794 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10796 return S_OK;
10799 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10800 UINT index, LPOLESTR dllName, LPOLESTR procName)
10802 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10803 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10804 return E_NOTIMPL;
10807 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10808 UINT index, LPOLESTR docString)
10810 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10811 TLBFuncDesc *func_desc = &This->funcdescs[index];
10813 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10815 if(!docString)
10816 return E_INVALIDARG;
10818 if(index >= This->cFuncs)
10819 return TYPE_E_ELEMENTNOTFOUND;
10821 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10823 return S_OK;
10826 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10827 UINT index, LPOLESTR docString)
10829 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10830 TLBVarDesc *var_desc = &This->vardescs[index];
10832 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10834 if(!docString)
10835 return E_INVALIDARG;
10837 if(index >= This->cVars)
10838 return TYPE_E_ELEMENTNOTFOUND;
10840 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10842 return S_OK;
10845 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10846 UINT index, DWORD helpContext)
10848 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10849 TLBFuncDesc *func_desc = &This->funcdescs[index];
10851 TRACE("%p %u %d\n", This, index, helpContext);
10853 if(index >= This->cFuncs)
10854 return TYPE_E_ELEMENTNOTFOUND;
10856 func_desc->helpcontext = helpContext;
10858 return S_OK;
10861 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10862 UINT index, DWORD helpContext)
10864 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10865 TLBVarDesc *var_desc = &This->vardescs[index];
10867 TRACE("%p %u %d\n", This, index, helpContext);
10869 if(index >= This->cVars)
10870 return TYPE_E_ELEMENTNOTFOUND;
10872 var_desc->HelpContext = helpContext;
10874 return S_OK;
10877 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10878 UINT index, BSTR bstrMops)
10880 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10881 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10882 return E_NOTIMPL;
10885 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10886 IDLDESC *idlDesc)
10888 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10890 TRACE("%p %p\n", This, idlDesc);
10892 if (!idlDesc)
10893 return E_INVALIDARG;
10895 This->idldescType.dwReserved = idlDesc->dwReserved;
10896 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10898 return S_OK;
10901 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10903 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10904 ITypeInfo *tinfo;
10905 TLBFuncDesc *func_desc;
10906 UINT user_vft = 0, i, depth = 0;
10907 HRESULT hres = S_OK;
10909 TRACE("%p\n", This);
10911 This->needs_layout = FALSE;
10913 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10914 if (FAILED(hres))
10915 return hres;
10917 if (This->typekind == TKIND_INTERFACE) {
10918 ITypeInfo *inh;
10919 TYPEATTR *attr;
10920 HREFTYPE inh_href;
10922 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10924 if (SUCCEEDED(hres)) {
10925 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10927 if (SUCCEEDED(hres)) {
10928 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10929 if (FAILED(hres)) {
10930 ITypeInfo_Release(inh);
10931 ITypeInfo_Release(tinfo);
10932 return hres;
10934 This->cbSizeVft = attr->cbSizeVft;
10935 ITypeInfo_ReleaseTypeAttr(inh, attr);
10938 ++depth;
10939 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10940 if(SUCCEEDED(hres)){
10941 ITypeInfo *next;
10942 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10943 if(SUCCEEDED(hres)){
10944 ITypeInfo_Release(inh);
10945 inh = next;
10948 }while(SUCCEEDED(hres));
10949 hres = S_OK;
10951 ITypeInfo_Release(inh);
10952 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10953 This->cbSizeVft = 0;
10954 hres = S_OK;
10955 } else {
10956 ITypeInfo_Release(tinfo);
10957 return hres;
10959 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10960 This->cbSizeVft = 0;
10961 hres = S_OK;
10962 } else {
10963 ITypeInfo_Release(tinfo);
10964 return hres;
10966 } else if (This->typekind == TKIND_DISPATCH)
10967 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10968 else
10969 This->cbSizeVft = 0;
10971 func_desc = This->funcdescs;
10972 i = 0;
10973 while (i < This->cFuncs) {
10974 if (!(func_desc->funcdesc.oVft & 0x1))
10975 func_desc->funcdesc.oVft = This->cbSizeVft;
10977 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10978 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10980 This->cbSizeVft += This->pTypeLib->ptr_size;
10982 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10983 TLBFuncDesc *iter;
10984 UINT j = 0;
10985 BOOL reset = FALSE;
10987 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10989 iter = This->funcdescs;
10990 while (j < This->cFuncs) {
10991 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10992 if (!reset) {
10993 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10994 reset = TRUE;
10995 } else
10996 ++func_desc->funcdesc.memid;
10997 iter = This->funcdescs;
10998 j = 0;
10999 } else {
11000 ++iter;
11001 ++j;
11006 ++func_desc;
11007 ++i;
11010 if (user_vft > This->cbSizeVft)
11011 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11013 for(i = 0; i < This->cVars; ++i){
11014 TLBVarDesc *var_desc = &This->vardescs[i];
11015 if(var_desc->vardesc.memid == MEMBERID_NIL){
11016 UINT j = 0;
11017 BOOL reset = FALSE;
11018 TLBVarDesc *iter;
11020 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11022 iter = This->vardescs;
11023 while (j < This->cVars) {
11024 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11025 if (!reset) {
11026 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->cVars;
11027 reset = TRUE;
11028 } else
11029 ++var_desc->vardesc.memid;
11030 iter = This->vardescs;
11031 j = 0;
11032 } else {
11033 ++iter;
11034 ++j;
11040 ITypeInfo_Release(tinfo);
11041 return hres;
11044 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11045 UINT index)
11047 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11048 FIXME("%p %u - stub\n", This, index);
11049 return E_NOTIMPL;
11052 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11053 MEMBERID memid, INVOKEKIND invKind)
11055 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11056 FIXME("%p %x %d - stub\n", This, memid, invKind);
11057 return E_NOTIMPL;
11060 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11061 UINT index)
11063 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11064 FIXME("%p %u - stub\n", This, index);
11065 return E_NOTIMPL;
11068 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11069 MEMBERID memid)
11071 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11072 FIXME("%p %x - stub\n", This, memid);
11073 return E_NOTIMPL;
11076 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11077 UINT index)
11079 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11080 FIXME("%p %u - stub\n", This, index);
11081 return E_NOTIMPL;
11084 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11085 REFGUID guid, VARIANT *varVal)
11087 TLBGuid *tlbguid;
11089 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11091 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11093 if (!guid || !varVal)
11094 return E_INVALIDARG;
11096 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11098 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11101 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11102 UINT index, REFGUID guid, VARIANT *varVal)
11104 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11105 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11106 return E_NOTIMPL;
11109 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11110 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11112 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11113 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11114 return E_NOTIMPL;
11117 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11118 UINT index, REFGUID guid, VARIANT *varVal)
11120 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11121 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11122 return E_NOTIMPL;
11125 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11126 UINT index, REFGUID guid, VARIANT *varVal)
11128 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11129 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11130 return E_NOTIMPL;
11133 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11134 ULONG helpStringContext)
11136 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11138 TRACE("%p %u\n", This, helpStringContext);
11140 This->dwHelpStringContext = helpStringContext;
11142 return S_OK;
11145 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11146 UINT index, ULONG helpStringContext)
11148 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11149 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11150 return E_NOTIMPL;
11153 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11154 UINT index, ULONG helpStringContext)
11156 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11157 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11158 return E_NOTIMPL;
11161 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11163 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11164 FIXME("%p - stub\n", This);
11165 return E_NOTIMPL;
11168 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11169 LPOLESTR name)
11171 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11173 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11175 if (!name)
11176 return E_INVALIDARG;
11178 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11180 return S_OK;
11183 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11184 ICreateTypeInfo2_fnQueryInterface,
11185 ICreateTypeInfo2_fnAddRef,
11186 ICreateTypeInfo2_fnRelease,
11187 ICreateTypeInfo2_fnSetGuid,
11188 ICreateTypeInfo2_fnSetTypeFlags,
11189 ICreateTypeInfo2_fnSetDocString,
11190 ICreateTypeInfo2_fnSetHelpContext,
11191 ICreateTypeInfo2_fnSetVersion,
11192 ICreateTypeInfo2_fnAddRefTypeInfo,
11193 ICreateTypeInfo2_fnAddFuncDesc,
11194 ICreateTypeInfo2_fnAddImplType,
11195 ICreateTypeInfo2_fnSetImplTypeFlags,
11196 ICreateTypeInfo2_fnSetAlignment,
11197 ICreateTypeInfo2_fnSetSchema,
11198 ICreateTypeInfo2_fnAddVarDesc,
11199 ICreateTypeInfo2_fnSetFuncAndParamNames,
11200 ICreateTypeInfo2_fnSetVarName,
11201 ICreateTypeInfo2_fnSetTypeDescAlias,
11202 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11203 ICreateTypeInfo2_fnSetFuncDocString,
11204 ICreateTypeInfo2_fnSetVarDocString,
11205 ICreateTypeInfo2_fnSetFuncHelpContext,
11206 ICreateTypeInfo2_fnSetVarHelpContext,
11207 ICreateTypeInfo2_fnSetMops,
11208 ICreateTypeInfo2_fnSetTypeIdldesc,
11209 ICreateTypeInfo2_fnLayOut,
11210 ICreateTypeInfo2_fnDeleteFuncDesc,
11211 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11212 ICreateTypeInfo2_fnDeleteVarDesc,
11213 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11214 ICreateTypeInfo2_fnDeleteImplType,
11215 ICreateTypeInfo2_fnSetCustData,
11216 ICreateTypeInfo2_fnSetFuncCustData,
11217 ICreateTypeInfo2_fnSetParamCustData,
11218 ICreateTypeInfo2_fnSetVarCustData,
11219 ICreateTypeInfo2_fnSetImplTypeCustData,
11220 ICreateTypeInfo2_fnSetHelpStringContext,
11221 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11222 ICreateTypeInfo2_fnSetVarHelpStringContext,
11223 ICreateTypeInfo2_fnInvalidate,
11224 ICreateTypeInfo2_fnSetName
11227 /******************************************************************************
11228 * ClearCustData (OLEAUT32.171)
11230 * Clear a custom data type's data.
11232 * PARAMS
11233 * lpCust [I] The custom data type instance
11235 * RETURNS
11236 * Nothing.
11238 void WINAPI ClearCustData(CUSTDATA *lpCust)
11240 if (lpCust && lpCust->cCustData)
11242 if (lpCust->prgCustData)
11244 DWORD i;
11246 for (i = 0; i < lpCust->cCustData; i++)
11247 VariantClear(&lpCust->prgCustData[i].varValue);
11249 CoTaskMemFree(lpCust->prgCustData);
11250 lpCust->prgCustData = NULL;
11252 lpCust->cCustData = 0;