server: Allow cancelling async I/O for all object types.
[wine.git] / dlls / oleaut32 / typelib.c
blobb8325c0e02c11870c014a69e9ef13747400cbb96
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 (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 (*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, i = 0;
4490 pBlkEntry[order].next != 0;
4491 order = pBlkEntry[order].next - 1, i++) {
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 %rcx,%xmm0\n\t"
6460 "movq %rdx,%xmm1\n\t"
6461 "movq %r8,%xmm2\n\t"
6462 "movq %r9,%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) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
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 V_ARRAY(&rgvarg[i]) = a;
7111 V_VT(&rgvarg[i]) = rgvt[i];
7113 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7115 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7116 if (wParamFlags & PARAMFLAG_FIN)
7117 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7118 else
7119 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7120 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7121 V_VT(&rgvarg[i]) = rgvt[i];
7123 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7125 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7126 V_VT(&rgvarg[i]) = rgvt[i];
7128 else
7130 /* FIXME: this doesn't work for VT_BYREF arguments if
7131 * they are not the same type as in the paramdesc */
7132 V_VT(&rgvarg[i]) = V_VT(src_arg);
7133 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7134 V_VT(&rgvarg[i]) = rgvt[i];
7137 if (FAILED(hres))
7139 ERR("failed to convert param %d to %s from %s\n", i,
7140 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7141 break;
7143 prgpvarg[i] = &rgvarg[i];
7145 else
7147 prgpvarg[i] = src_arg;
7150 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7151 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7152 && V_UNKNOWN(prgpvarg[i])) {
7153 IUnknown *userdefined_iface;
7154 GUID guid;
7156 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7157 if(FAILED(hres))
7158 break;
7160 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7161 if(FAILED(hres)) {
7162 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7163 break;
7166 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7167 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7170 else if (wParamFlags & PARAMFLAG_FOPT)
7172 VARIANTARG *arg;
7173 arg = prgpvarg[i] = &rgvarg[i];
7174 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7176 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7177 if (FAILED(hres))
7178 break;
7180 else
7182 VARIANTARG *missing_arg;
7183 /* if the function wants a pointer to a variant then
7184 * set that up, otherwise just pass the VT_ERROR in
7185 * the argument by value */
7186 if (rgvt[i] & VT_BYREF)
7188 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7189 V_VT(arg) = VT_VARIANT | VT_BYREF;
7190 V_VARIANTREF(arg) = missing_arg;
7192 else
7193 missing_arg = arg;
7194 V_VT(missing_arg) = VT_ERROR;
7195 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7198 else
7200 hres = DISP_E_BADPARAMCOUNT;
7201 break;
7204 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7206 /* VT_VOID is a special case for return types, so it is not
7207 * handled in the general function */
7208 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7209 V_VT(&varresult) = VT_EMPTY;
7210 else
7212 V_VT(&varresult) = 0;
7213 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7214 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7217 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7218 V_VT(&varresult), func_desc->cParams, rgvt,
7219 prgpvarg, &varresult);
7221 vargs_converted = 0;
7223 for (i = 0; i < func_desc->cParams; i++)
7225 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7226 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7228 if (wParamFlags & PARAMFLAG_FLCID)
7229 continue;
7230 else if (wParamFlags & PARAMFLAG_FRETVAL)
7232 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7234 if (pVarResult)
7236 VariantInit(pVarResult);
7237 /* deref return value */
7238 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7241 VARIANT_ClearInd(prgpvarg[i]);
7243 else if (vargs_converted < pDispParams->cArgs)
7245 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7246 if (wParamFlags & PARAMFLAG_FOUT)
7248 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7250 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7252 if (FAILED(hres))
7254 ERR("failed to convert param %d to vt %d\n", i,
7255 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7256 break;
7260 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7261 func_desc->cParamsOpt < 0 &&
7262 i == func_desc->cParams-1)
7264 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7265 LONG j, ubound;
7266 VARIANT *v;
7267 hres = SafeArrayGetUBound(a, 1, &ubound);
7268 if (hres != S_OK)
7270 ERR("SafeArrayGetUBound failed with %x\n", hres);
7271 break;
7273 hres = SafeArrayAccessData(a, (LPVOID)&v);
7274 if (hres != S_OK)
7276 ERR("SafeArrayAccessData failed with %x\n", hres);
7277 break;
7279 for (j = 0; j <= ubound; j++)
7280 VariantClear(&v[j]);
7281 hres = SafeArrayUnaccessData(a);
7282 if (hres != S_OK)
7284 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7285 break;
7288 VariantClear(&rgvarg[i]);
7289 vargs_converted++;
7291 else if (wParamFlags & PARAMFLAG_FOPT)
7293 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7294 VariantClear(&rgvarg[i]);
7297 VariantClear(&missing_arg[i]);
7300 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7302 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7303 hres = DISP_E_EXCEPTION;
7304 if (pExcepInfo)
7306 IErrorInfo *pErrorInfo;
7307 pExcepInfo->scode = V_ERROR(&varresult);
7308 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7310 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7311 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7312 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7313 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7315 IErrorInfo_Release(pErrorInfo);
7319 if (V_VT(&varresult) != VT_ERROR)
7321 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7323 if (pVarResult)
7325 VariantClear(pVarResult);
7326 *pVarResult = varresult;
7328 else
7329 VariantClear(&varresult);
7332 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7333 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7334 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7335 (pDispParams->cArgs != 0))
7337 if (V_VT(pVarResult) == VT_DISPATCH)
7339 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7340 /* Note: not VariantClear; we still need the dispatch
7341 * pointer to be valid */
7342 VariantInit(pVarResult);
7343 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7344 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7345 pDispParams, pVarResult, pExcepInfo, pArgErr);
7346 IDispatch_Release(pDispatch);
7348 else
7350 VariantClear(pVarResult);
7351 hres = DISP_E_NOTACOLLECTION;
7355 func_fail:
7356 heap_free(buffer);
7357 break;
7359 case FUNC_DISPATCH: {
7360 IDispatch *disp;
7362 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7363 if (SUCCEEDED(hres)) {
7364 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7365 hres = IDispatch_Invoke(
7366 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7367 pVarResult,pExcepInfo,pArgErr
7369 if (FAILED(hres))
7370 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7371 IDispatch_Release(disp);
7372 } else
7373 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7374 break;
7376 default:
7377 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7378 hres = E_FAIL;
7379 break;
7382 TRACE("-- 0x%08x\n", hres);
7383 return hres;
7385 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7386 VARDESC *var_desc;
7388 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7389 if(FAILED(hres)) return hres;
7391 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7392 dump_VARDESC(var_desc);
7393 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7394 return E_NOTIMPL;
7397 /* not found, look for it in inherited interfaces */
7398 ITypeInfo2_GetTypeKind(iface, &type_kind);
7399 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7400 if(This->impltypes) {
7401 /* recursive search */
7402 ITypeInfo *pTInfo;
7403 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7404 if(SUCCEEDED(hres)){
7405 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7406 ITypeInfo_Release(pTInfo);
7407 return hres;
7409 WARN("Could not search inherited interface!\n");
7412 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7413 return DISP_E_MEMBERNOTFOUND;
7416 /* ITypeInfo::GetDocumentation
7418 * Retrieves the documentation string, the complete Help file name and path,
7419 * and the context ID for the Help topic for a specified type description.
7421 * (Can be tested by the Visual Basic Editor in Word for instance.)
7423 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7424 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7425 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7427 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7428 const TLBFuncDesc *pFDesc;
7429 const TLBVarDesc *pVDesc;
7430 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7431 " HelpContext(%p) HelpFile(%p)\n",
7432 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7433 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7434 if(pBstrName)
7435 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7436 if(pBstrDocString)
7437 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7438 if(pdwHelpContext)
7439 *pdwHelpContext=This->dwHelpContext;
7440 if(pBstrHelpFile)
7441 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7442 return S_OK;
7443 }else {/* for a member */
7444 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7445 if(pFDesc){
7446 if(pBstrName)
7447 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7448 if(pBstrDocString)
7449 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7450 if(pdwHelpContext)
7451 *pdwHelpContext=pFDesc->helpcontext;
7452 if(pBstrHelpFile)
7453 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7454 return S_OK;
7456 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7457 if(pVDesc){
7458 if(pBstrName)
7459 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7460 if(pBstrDocString)
7461 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7462 if(pdwHelpContext)
7463 *pdwHelpContext=pVDesc->HelpContext;
7464 if(pBstrHelpFile)
7465 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7466 return S_OK;
7470 if(This->impltypes &&
7471 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7472 /* recursive search */
7473 ITypeInfo *pTInfo;
7474 HRESULT result;
7475 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7476 if(SUCCEEDED(result)) {
7477 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7478 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7479 ITypeInfo_Release(pTInfo);
7480 return result;
7482 WARN("Could not search inherited interface!\n");
7485 WARN("member %d not found\n", memid);
7486 return TYPE_E_ELEMENTNOTFOUND;
7489 /* ITypeInfo::GetDllEntry
7491 * Retrieves a description or specification of an entry point for a function
7492 * in a DLL.
7494 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7495 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7496 WORD *pwOrdinal)
7498 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7499 const TLBFuncDesc *pFDesc;
7501 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7503 if (pBstrDllName) *pBstrDllName = NULL;
7504 if (pBstrName) *pBstrName = NULL;
7505 if (pwOrdinal) *pwOrdinal = 0;
7507 if (This->typekind != TKIND_MODULE)
7508 return TYPE_E_BADMODULEKIND;
7510 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7511 if(pFDesc){
7512 dump_TypeInfo(This);
7513 if (TRACE_ON(ole))
7514 dump_TLBFuncDescOne(pFDesc);
7516 if (pBstrDllName)
7517 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7519 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7520 if (pBstrName)
7521 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7522 if (pwOrdinal)
7523 *pwOrdinal = -1;
7524 return S_OK;
7526 if (pBstrName)
7527 *pBstrName = NULL;
7528 if (pwOrdinal)
7529 *pwOrdinal = LOWORD(pFDesc->Entry);
7530 return S_OK;
7532 return TYPE_E_ELEMENTNOTFOUND;
7535 /* internal function to make the inherited interfaces' methods appear
7536 * part of the interface */
7537 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7538 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7540 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7541 HRESULT hr;
7543 TRACE("%p, 0x%x\n", iface, *hRefType);
7545 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7547 ITypeInfo *pSubTypeInfo;
7549 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7550 if (FAILED(hr))
7551 return hr;
7553 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7554 hRefType, ppTInfo);
7555 ITypeInfo_Release(pSubTypeInfo);
7556 if (SUCCEEDED(hr))
7557 return hr;
7559 *hRefType -= DISPATCH_HREF_OFFSET;
7561 if (!(*hRefType & DISPATCH_HREF_MASK))
7562 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7563 else
7564 return E_FAIL;
7567 struct search_res_tlb_params
7569 const GUID *guid;
7570 ITypeLib *pTLib;
7573 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7575 struct search_res_tlb_params *params = (LPVOID)lParam;
7576 static const WCHAR formatW[] = {'\\','%','d',0};
7577 WCHAR szPath[MAX_PATH+1];
7578 ITypeLib *pTLib = NULL;
7579 HRESULT ret;
7580 DWORD len;
7582 if (IS_INTRESOURCE(lpszName) == FALSE)
7583 return TRUE;
7585 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7586 return TRUE;
7588 if (snprintfW(szPath + len, sizeof(szPath)/sizeof(WCHAR) - len, formatW, LOWORD(lpszName)) < 0)
7589 return TRUE;
7591 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7592 if (SUCCEEDED(ret))
7594 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7595 if (IsEqualGUID(params->guid, impl->guid))
7597 params->pTLib = pTLib;
7598 return FALSE; /* stop enumeration */
7600 ITypeLib_Release(pTLib);
7603 return TRUE;
7606 /* ITypeInfo::GetRefTypeInfo
7608 * If a type description references other type descriptions, it retrieves
7609 * the referenced type descriptions.
7611 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7612 ITypeInfo2 *iface,
7613 HREFTYPE hRefType,
7614 ITypeInfo **ppTInfo)
7616 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7617 HRESULT result = E_FAIL;
7619 if(!ppTInfo)
7620 return E_INVALIDARG;
7622 if ((INT)hRefType < 0) {
7623 ITypeInfoImpl *pTypeInfoImpl;
7625 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7626 !(This->typekind == TKIND_INTERFACE ||
7627 This->typekind == TKIND_DISPATCH))
7628 return TYPE_E_ELEMENTNOTFOUND;
7630 /* when we meet a DUAL typeinfo, we must create the alternate
7631 * version of it.
7633 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7635 *pTypeInfoImpl = *This;
7636 pTypeInfoImpl->ref = 0;
7637 list_init(&pTypeInfoImpl->custdata_list);
7639 if (This->typekind == TKIND_INTERFACE)
7640 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7641 else
7642 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7644 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7645 /* the AddRef implicitly adds a reference to the parent typelib, which
7646 * stops the copied data from being destroyed until the new typeinfo's
7647 * refcount goes to zero, but we need to signal to the new instance to
7648 * not free its data structures when it is destroyed */
7649 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7651 ITypeInfo_AddRef(*ppTInfo);
7653 result = S_OK;
7654 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7655 (This->typekind == TKIND_DISPATCH))
7657 HREFTYPE href_dispatch = hRefType;
7658 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7659 } else {
7660 TLBRefType *ref_type;
7661 ITypeLib *pTLib = NULL;
7662 UINT i;
7664 if(!(hRefType & 0x1)){
7665 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7667 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7669 result = S_OK;
7670 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7671 ITypeInfo_AddRef(*ppTInfo);
7672 goto end;
7677 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7679 if(ref_type->reference == (hRefType & (~0x3)))
7680 break;
7682 if(&ref_type->entry == &This->pTypeLib->ref_list)
7684 FIXME("Can't find pRefType for ref %x\n", hRefType);
7685 goto end;
7688 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7689 UINT Index;
7690 TRACE("internal reference\n");
7691 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7692 } else {
7693 if(ref_type->pImpTLInfo->pImpTypeLib) {
7694 TRACE("typeinfo in imported typelib that is already loaded\n");
7695 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7696 ITypeLib_AddRef(pTLib);
7697 result = S_OK;
7698 } else {
7699 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
7700 struct search_res_tlb_params params;
7701 BSTR libnam;
7703 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7705 /* Search in resource table */
7706 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
7707 params.pTLib = NULL;
7708 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
7709 pTLib = params.pTLib;
7710 result = S_OK;
7712 if (!pTLib)
7714 /* Search on disk */
7715 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7716 ref_type->pImpTLInfo->wVersionMajor,
7717 ref_type->pImpTLInfo->wVersionMinor,
7718 This->pTypeLib->syskind,
7719 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7720 if (FAILED(result))
7721 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7723 result = LoadTypeLib(libnam, &pTLib);
7724 SysFreeString(libnam);
7727 if(SUCCEEDED(result)) {
7728 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7729 ITypeLib_AddRef(pTLib);
7733 if(SUCCEEDED(result)) {
7734 if(ref_type->index == TLB_REF_USE_GUID)
7735 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7736 else
7737 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7739 if (pTLib != NULL)
7740 ITypeLib_Release(pTLib);
7743 end:
7744 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7745 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7746 return result;
7749 /* ITypeInfo::AddressOfMember
7751 * Retrieves the addresses of static functions or variables, such as those
7752 * defined in a DLL.
7754 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7755 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7757 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7758 HRESULT hr;
7759 BSTR dll, entry;
7760 WORD ordinal;
7761 HMODULE module;
7763 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7765 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7766 if (FAILED(hr))
7767 return hr;
7769 module = LoadLibraryW(dll);
7770 if (!module)
7772 ERR("couldn't load %s\n", debugstr_w(dll));
7773 SysFreeString(dll);
7774 SysFreeString(entry);
7775 return STG_E_FILENOTFOUND;
7777 /* FIXME: store library somewhere where we can free it */
7779 if (entry)
7781 LPSTR entryA;
7782 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7783 entryA = heap_alloc(len);
7784 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7786 *ppv = GetProcAddress(module, entryA);
7787 if (!*ppv)
7788 ERR("function not found %s\n", debugstr_a(entryA));
7790 heap_free(entryA);
7792 else
7794 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7795 if (!*ppv)
7796 ERR("function not found %d\n", ordinal);
7799 SysFreeString(dll);
7800 SysFreeString(entry);
7802 if (!*ppv)
7803 return TYPE_E_DLLFUNCTIONNOTFOUND;
7805 return S_OK;
7808 /* ITypeInfo::CreateInstance
7810 * Creates a new instance of a type that describes a component object class
7811 * (coclass).
7813 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7814 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7816 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7817 HRESULT hr;
7818 TYPEATTR *pTA;
7820 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7822 *ppvObj = NULL;
7824 if(pOuterUnk)
7826 WARN("Not able to aggregate\n");
7827 return CLASS_E_NOAGGREGATION;
7830 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7831 if(FAILED(hr)) return hr;
7833 if(pTA->typekind != TKIND_COCLASS)
7835 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7836 hr = E_INVALIDARG;
7837 goto end;
7840 hr = S_FALSE;
7841 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7843 IUnknown *pUnk;
7844 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7845 TRACE("GetActiveObject rets %08x\n", hr);
7846 if(hr == S_OK)
7848 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7849 IUnknown_Release(pUnk);
7853 if(hr != S_OK)
7854 hr = CoCreateInstance(&pTA->guid, NULL,
7855 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7856 riid, ppvObj);
7858 end:
7859 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7860 return hr;
7863 /* ITypeInfo::GetMops
7865 * Retrieves marshalling information.
7867 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7868 BSTR *pBstrMops)
7870 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7871 FIXME("(%p %d) stub!\n", This, memid);
7872 *pBstrMops = NULL;
7873 return S_OK;
7876 /* ITypeInfo::GetContainingTypeLib
7878 * Retrieves the containing type library and the index of the type description
7879 * within that type library.
7881 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7882 ITypeLib * *ppTLib, UINT *pIndex)
7884 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7886 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7887 if (pIndex) {
7888 *pIndex=This->index;
7889 TRACE("returning pIndex=%d\n", *pIndex);
7892 if (ppTLib) {
7893 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7894 ITypeLib_AddRef(*ppTLib);
7895 TRACE("returning ppTLib=%p\n", *ppTLib);
7898 return S_OK;
7901 /* ITypeInfo::ReleaseTypeAttr
7903 * Releases a TYPEATTR previously returned by Get
7906 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7907 TYPEATTR* pTypeAttr)
7909 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7910 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7911 heap_free(pTypeAttr);
7914 /* ITypeInfo::ReleaseFuncDesc
7916 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7918 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7919 ITypeInfo2 *iface,
7920 FUNCDESC *pFuncDesc)
7922 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7923 SHORT i;
7925 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7927 for (i = 0; i < pFuncDesc->cParams; i++)
7928 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7929 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7931 SysFreeString((BSTR)pFuncDesc);
7934 /* ITypeInfo::ReleaseVarDesc
7936 * Releases a VARDESC previously returned by GetVarDesc.
7938 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7939 VARDESC *pVarDesc)
7941 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7942 TRACE("(%p)->(%p)\n", This, pVarDesc);
7944 TLB_FreeVarDesc(pVarDesc);
7947 /* ITypeInfo2::GetTypeKind
7949 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7952 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7953 TYPEKIND *pTypeKind)
7955 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7956 *pTypeKind=This->typekind;
7957 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7958 return S_OK;
7961 /* ITypeInfo2::GetTypeFlags
7963 * Returns the type flags without any allocations. This returns a DWORD type
7964 * flag, which expands the type flags without growing the TYPEATTR (type
7965 * attribute).
7968 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7970 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7971 *pTypeFlags=This->wTypeFlags;
7972 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7973 return S_OK;
7976 /* ITypeInfo2::GetFuncIndexOfMemId
7977 * Binds to a specific member based on a known DISPID, where the member name
7978 * is not known (for example, when binding to a default member).
7981 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7982 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7984 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7985 UINT fdc;
7986 HRESULT result;
7988 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7989 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7990 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7991 break;
7993 if(fdc < This->cFuncs) {
7994 *pFuncIndex = fdc;
7995 result = S_OK;
7996 } else
7997 result = TYPE_E_ELEMENTNOTFOUND;
7999 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8000 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8001 return result;
8004 /* TypeInfo2::GetVarIndexOfMemId
8006 * Binds to a specific member based on a known DISPID, where the member name
8007 * is not known (for example, when binding to a default member).
8010 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8011 MEMBERID memid, UINT *pVarIndex)
8013 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8014 TLBVarDesc *pVarInfo;
8016 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8018 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8019 if(!pVarInfo)
8020 return TYPE_E_ELEMENTNOTFOUND;
8022 *pVarIndex = (pVarInfo - This->vardescs);
8024 return S_OK;
8027 /* ITypeInfo2::GetCustData
8029 * Gets the custom data
8031 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8032 ITypeInfo2 * iface,
8033 REFGUID guid,
8034 VARIANT *pVarVal)
8036 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8037 TLBCustData *pCData;
8039 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8041 if(!guid || !pVarVal)
8042 return E_INVALIDARG;
8044 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8046 VariantInit( pVarVal);
8047 if (pCData)
8048 VariantCopy( pVarVal, &pCData->data);
8049 else
8050 VariantClear( pVarVal );
8051 return S_OK;
8054 /* ITypeInfo2::GetFuncCustData
8056 * Gets the custom data
8058 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8059 ITypeInfo2 * iface,
8060 UINT index,
8061 REFGUID guid,
8062 VARIANT *pVarVal)
8064 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8065 TLBCustData *pCData;
8066 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8068 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8070 if(index >= This->cFuncs)
8071 return TYPE_E_ELEMENTNOTFOUND;
8073 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8074 if(!pCData)
8075 return TYPE_E_ELEMENTNOTFOUND;
8077 VariantInit(pVarVal);
8078 VariantCopy(pVarVal, &pCData->data);
8080 return S_OK;
8083 /* ITypeInfo2::GetParamCustData
8085 * Gets the custom data
8087 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8088 ITypeInfo2 * iface,
8089 UINT indexFunc,
8090 UINT indexParam,
8091 REFGUID guid,
8092 VARIANT *pVarVal)
8094 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8095 TLBCustData *pCData;
8096 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8098 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8099 debugstr_guid(guid), pVarVal);
8101 if(indexFunc >= This->cFuncs)
8102 return TYPE_E_ELEMENTNOTFOUND;
8104 if(indexParam >= pFDesc->funcdesc.cParams)
8105 return TYPE_E_ELEMENTNOTFOUND;
8107 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8108 if(!pCData)
8109 return TYPE_E_ELEMENTNOTFOUND;
8111 VariantInit(pVarVal);
8112 VariantCopy(pVarVal, &pCData->data);
8114 return S_OK;
8117 /* ITypeInfo2::GetVarCustData
8119 * Gets the custom data
8121 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8122 ITypeInfo2 * iface,
8123 UINT index,
8124 REFGUID guid,
8125 VARIANT *pVarVal)
8127 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8128 TLBCustData *pCData;
8129 TLBVarDesc *pVDesc = &This->vardescs[index];
8131 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8133 if(index >= This->cVars)
8134 return TYPE_E_ELEMENTNOTFOUND;
8136 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8137 if(!pCData)
8138 return TYPE_E_ELEMENTNOTFOUND;
8140 VariantInit(pVarVal);
8141 VariantCopy(pVarVal, &pCData->data);
8143 return S_OK;
8146 /* ITypeInfo2::GetImplCustData
8148 * Gets the custom data
8150 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8151 ITypeInfo2 * iface,
8152 UINT index,
8153 REFGUID guid,
8154 VARIANT *pVarVal)
8156 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8157 TLBCustData *pCData;
8158 TLBImplType *pRDesc = &This->impltypes[index];
8160 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8162 if(index >= This->cImplTypes)
8163 return TYPE_E_ELEMENTNOTFOUND;
8165 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8166 if(!pCData)
8167 return TYPE_E_ELEMENTNOTFOUND;
8169 VariantInit(pVarVal);
8170 VariantCopy(pVarVal, &pCData->data);
8172 return S_OK;
8175 /* ITypeInfo2::GetDocumentation2
8177 * Retrieves the documentation string, the complete Help file name and path,
8178 * the localization context to use, and the context ID for the library Help
8179 * topic in the Help file.
8182 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8183 ITypeInfo2 * iface,
8184 MEMBERID memid,
8185 LCID lcid,
8186 BSTR *pbstrHelpString,
8187 DWORD *pdwHelpStringContext,
8188 BSTR *pbstrHelpStringDll)
8190 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8191 const TLBFuncDesc *pFDesc;
8192 const TLBVarDesc *pVDesc;
8193 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8194 "HelpStringContext(%p) HelpStringDll(%p)\n",
8195 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8196 pbstrHelpStringDll );
8197 /* the help string should be obtained from the helpstringdll,
8198 * using the _DLLGetDocumentation function, based on the supplied
8199 * lcid. Nice to do sometime...
8201 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8202 if(pbstrHelpString)
8203 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8204 if(pdwHelpStringContext)
8205 *pdwHelpStringContext=This->dwHelpStringContext;
8206 if(pbstrHelpStringDll)
8207 *pbstrHelpStringDll=
8208 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8209 return S_OK;
8210 }else {/* for a member */
8211 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
8212 if(pFDesc){
8213 if(pbstrHelpString)
8214 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8215 if(pdwHelpStringContext)
8216 *pdwHelpStringContext=pFDesc->HelpStringContext;
8217 if(pbstrHelpStringDll)
8218 *pbstrHelpStringDll=
8219 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8220 return S_OK;
8222 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8223 if(pVDesc){
8224 if(pbstrHelpString)
8225 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8226 if(pdwHelpStringContext)
8227 *pdwHelpStringContext=pVDesc->HelpStringContext;
8228 if(pbstrHelpStringDll)
8229 *pbstrHelpStringDll=
8230 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8231 return S_OK;
8234 return TYPE_E_ELEMENTNOTFOUND;
8237 /* ITypeInfo2::GetAllCustData
8239 * Gets all custom data items for the Type info.
8242 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8243 ITypeInfo2 * iface,
8244 CUSTDATA *pCustData)
8246 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8248 TRACE("%p %p\n", This, pCustData);
8250 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8253 /* ITypeInfo2::GetAllFuncCustData
8255 * Gets all custom data items for the specified Function
8258 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8259 ITypeInfo2 * iface,
8260 UINT index,
8261 CUSTDATA *pCustData)
8263 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8264 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8266 TRACE("%p %u %p\n", This, index, pCustData);
8268 if(index >= This->cFuncs)
8269 return TYPE_E_ELEMENTNOTFOUND;
8271 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8274 /* ITypeInfo2::GetAllParamCustData
8276 * Gets all custom data items for the Functions
8279 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8280 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8282 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8283 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8285 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8287 if(indexFunc >= This->cFuncs)
8288 return TYPE_E_ELEMENTNOTFOUND;
8290 if(indexParam >= pFDesc->funcdesc.cParams)
8291 return TYPE_E_ELEMENTNOTFOUND;
8293 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8296 /* ITypeInfo2::GetAllVarCustData
8298 * Gets all custom data items for the specified Variable
8301 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8302 UINT index, CUSTDATA *pCustData)
8304 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8305 TLBVarDesc * pVDesc = &This->vardescs[index];
8307 TRACE("%p %u %p\n", This, index, pCustData);
8309 if(index >= This->cVars)
8310 return TYPE_E_ELEMENTNOTFOUND;
8312 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8315 /* ITypeInfo2::GetAllImplCustData
8317 * Gets all custom data items for the specified implementation type
8320 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8321 ITypeInfo2 * iface,
8322 UINT index,
8323 CUSTDATA *pCustData)
8325 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8326 TLBImplType *pRDesc = &This->impltypes[index];
8328 TRACE("%p %u %p\n", This, index, pCustData);
8330 if(index >= This->cImplTypes)
8331 return TYPE_E_ELEMENTNOTFOUND;
8333 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8336 static const ITypeInfo2Vtbl tinfvt =
8339 ITypeInfo_fnQueryInterface,
8340 ITypeInfo_fnAddRef,
8341 ITypeInfo_fnRelease,
8343 ITypeInfo_fnGetTypeAttr,
8344 ITypeInfo_fnGetTypeComp,
8345 ITypeInfo_fnGetFuncDesc,
8346 ITypeInfo_fnGetVarDesc,
8347 ITypeInfo_fnGetNames,
8348 ITypeInfo_fnGetRefTypeOfImplType,
8349 ITypeInfo_fnGetImplTypeFlags,
8350 ITypeInfo_fnGetIDsOfNames,
8351 ITypeInfo_fnInvoke,
8352 ITypeInfo_fnGetDocumentation,
8353 ITypeInfo_fnGetDllEntry,
8354 ITypeInfo_fnGetRefTypeInfo,
8355 ITypeInfo_fnAddressOfMember,
8356 ITypeInfo_fnCreateInstance,
8357 ITypeInfo_fnGetMops,
8358 ITypeInfo_fnGetContainingTypeLib,
8359 ITypeInfo_fnReleaseTypeAttr,
8360 ITypeInfo_fnReleaseFuncDesc,
8361 ITypeInfo_fnReleaseVarDesc,
8363 ITypeInfo2_fnGetTypeKind,
8364 ITypeInfo2_fnGetTypeFlags,
8365 ITypeInfo2_fnGetFuncIndexOfMemId,
8366 ITypeInfo2_fnGetVarIndexOfMemId,
8367 ITypeInfo2_fnGetCustData,
8368 ITypeInfo2_fnGetFuncCustData,
8369 ITypeInfo2_fnGetParamCustData,
8370 ITypeInfo2_fnGetVarCustData,
8371 ITypeInfo2_fnGetImplTypeCustData,
8372 ITypeInfo2_fnGetDocumentation2,
8373 ITypeInfo2_fnGetAllCustData,
8374 ITypeInfo2_fnGetAllFuncCustData,
8375 ITypeInfo2_fnGetAllParamCustData,
8376 ITypeInfo2_fnGetAllVarCustData,
8377 ITypeInfo2_fnGetAllImplTypeCustData,
8380 /******************************************************************************
8381 * CreateDispTypeInfo [OLEAUT32.31]
8383 * Build type information for an object so it can be called through an
8384 * IDispatch interface.
8386 * RETURNS
8387 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8388 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8390 * NOTES
8391 * This call allows an objects methods to be accessed through IDispatch, by
8392 * building an ITypeInfo object that IDispatch can use to call through.
8394 HRESULT WINAPI CreateDispTypeInfo(
8395 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8396 LCID lcid, /* [I] Locale Id */
8397 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8399 ITypeInfoImpl *pTIClass, *pTIIface;
8400 ITypeLibImpl *pTypeLibImpl;
8401 unsigned int param, func;
8402 TLBFuncDesc *pFuncDesc;
8403 TLBRefType *ref;
8405 TRACE("\n");
8406 pTypeLibImpl = TypeLibImpl_Constructor();
8407 if (!pTypeLibImpl) return E_FAIL;
8409 pTypeLibImpl->TypeInfoCount = 2;
8410 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8412 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8413 pTIIface->pTypeLib = pTypeLibImpl;
8414 pTIIface->index = 0;
8415 pTIIface->Name = NULL;
8416 pTIIface->dwHelpContext = -1;
8417 pTIIface->guid = NULL;
8418 pTIIface->lcid = lcid;
8419 pTIIface->typekind = TKIND_INTERFACE;
8420 pTIIface->wMajorVerNum = 0;
8421 pTIIface->wMinorVerNum = 0;
8422 pTIIface->cbAlignment = 2;
8423 pTIIface->cbSizeInstance = -1;
8424 pTIIface->cbSizeVft = -1;
8425 pTIIface->cFuncs = 0;
8426 pTIIface->cImplTypes = 0;
8427 pTIIface->cVars = 0;
8428 pTIIface->wTypeFlags = 0;
8429 pTIIface->hreftype = 0;
8431 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8432 pFuncDesc = pTIIface->funcdescs;
8433 for(func = 0; func < pidata->cMembers; func++) {
8434 METHODDATA *md = pidata->pmethdata + func;
8435 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8436 pFuncDesc->funcdesc.memid = md->dispid;
8437 pFuncDesc->funcdesc.lprgscode = NULL;
8438 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8439 pFuncDesc->funcdesc.invkind = md->wFlags;
8440 pFuncDesc->funcdesc.callconv = md->cc;
8441 pFuncDesc->funcdesc.cParams = md->cArgs;
8442 pFuncDesc->funcdesc.cParamsOpt = 0;
8443 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8444 pFuncDesc->funcdesc.cScodes = 0;
8445 pFuncDesc->funcdesc.wFuncFlags = 0;
8446 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8447 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8448 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8449 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8450 md->cArgs * sizeof(ELEMDESC));
8451 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8452 for(param = 0; param < md->cArgs; param++) {
8453 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8454 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8456 pFuncDesc->helpcontext = 0;
8457 pFuncDesc->HelpStringContext = 0;
8458 pFuncDesc->HelpString = NULL;
8459 pFuncDesc->Entry = NULL;
8460 list_init(&pFuncDesc->custdata_list);
8461 pTIIface->cFuncs++;
8462 ++pFuncDesc;
8465 dump_TypeInfo(pTIIface);
8467 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8468 pTIClass->pTypeLib = pTypeLibImpl;
8469 pTIClass->index = 1;
8470 pTIClass->Name = NULL;
8471 pTIClass->dwHelpContext = -1;
8472 pTIClass->guid = NULL;
8473 pTIClass->lcid = lcid;
8474 pTIClass->typekind = TKIND_COCLASS;
8475 pTIClass->wMajorVerNum = 0;
8476 pTIClass->wMinorVerNum = 0;
8477 pTIClass->cbAlignment = 2;
8478 pTIClass->cbSizeInstance = -1;
8479 pTIClass->cbSizeVft = -1;
8480 pTIClass->cFuncs = 0;
8481 pTIClass->cImplTypes = 1;
8482 pTIClass->cVars = 0;
8483 pTIClass->wTypeFlags = 0;
8484 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8486 pTIClass->impltypes = TLBImplType_Alloc(1);
8488 ref = heap_alloc_zero(sizeof(*ref));
8489 ref->pImpTLInfo = TLB_REF_INTERNAL;
8490 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8492 dump_TypeInfo(pTIClass);
8494 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8496 ITypeInfo_AddRef(*pptinfo);
8497 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8499 return S_OK;
8503 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8505 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8507 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8510 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8512 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8514 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8517 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8519 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8521 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8524 static HRESULT WINAPI ITypeComp_fnBind(
8525 ITypeComp * iface,
8526 OLECHAR * szName,
8527 ULONG lHash,
8528 WORD wFlags,
8529 ITypeInfo ** ppTInfo,
8530 DESCKIND * pDescKind,
8531 BINDPTR * pBindPtr)
8533 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8534 const TLBFuncDesc *pFDesc;
8535 const TLBVarDesc *pVDesc;
8536 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8537 UINT fdc;
8539 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8541 *pDescKind = DESCKIND_NONE;
8542 pBindPtr->lpfuncdesc = NULL;
8543 *ppTInfo = NULL;
8545 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8546 pFDesc = &This->funcdescs[fdc];
8547 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8548 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8549 break;
8550 else
8551 /* name found, but wrong flags */
8552 hr = TYPE_E_TYPEMISMATCH;
8556 if (fdc < This->cFuncs)
8558 HRESULT hr = TLB_AllocAndInitFuncDesc(
8559 &pFDesc->funcdesc,
8560 &pBindPtr->lpfuncdesc,
8561 This->typekind == TKIND_DISPATCH);
8562 if (FAILED(hr))
8563 return hr;
8564 *pDescKind = DESCKIND_FUNCDESC;
8565 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8566 ITypeInfo_AddRef(*ppTInfo);
8567 return S_OK;
8568 } else {
8569 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8570 if(pVDesc){
8571 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8572 if (FAILED(hr))
8573 return hr;
8574 *pDescKind = DESCKIND_VARDESC;
8575 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8576 ITypeInfo_AddRef(*ppTInfo);
8577 return S_OK;
8581 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8582 /* recursive search */
8583 ITypeInfo *pTInfo;
8584 ITypeComp *pTComp;
8585 HRESULT hr;
8586 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8587 if (SUCCEEDED(hr))
8589 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8590 ITypeInfo_Release(pTInfo);
8592 if (SUCCEEDED(hr))
8594 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8595 ITypeComp_Release(pTComp);
8596 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8597 This->typekind == TKIND_DISPATCH)
8599 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8600 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8601 SysFreeString((BSTR)tmp);
8603 return hr;
8605 WARN("Could not search inherited interface!\n");
8607 if (hr == DISP_E_MEMBERNOTFOUND)
8608 hr = S_OK;
8609 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8610 return hr;
8613 static HRESULT WINAPI ITypeComp_fnBindType(
8614 ITypeComp * iface,
8615 OLECHAR * szName,
8616 ULONG lHash,
8617 ITypeInfo ** ppTInfo,
8618 ITypeComp ** ppTComp)
8620 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8622 /* strange behaviour (does nothing) but like the
8623 * original */
8625 if (!ppTInfo || !ppTComp)
8626 return E_POINTER;
8628 *ppTInfo = NULL;
8629 *ppTComp = NULL;
8631 return S_OK;
8634 static const ITypeCompVtbl tcompvt =
8637 ITypeComp_fnQueryInterface,
8638 ITypeComp_fnAddRef,
8639 ITypeComp_fnRelease,
8641 ITypeComp_fnBind,
8642 ITypeComp_fnBindType
8645 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8646 ICreateTypeLib2** ppctlib)
8648 ITypeLibImpl *This;
8649 HRESULT hres;
8651 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8653 if (!szFile) return E_INVALIDARG;
8655 This = TypeLibImpl_Constructor();
8656 if (!This)
8657 return E_OUTOFMEMORY;
8659 This->lcid = GetSystemDefaultLCID();
8660 This->syskind = syskind;
8661 This->ptr_size = get_ptr_size(syskind);
8663 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8664 if (!This->path) {
8665 ITypeLib2_Release(&This->ITypeLib2_iface);
8666 return E_OUTOFMEMORY;
8668 lstrcpyW(This->path, szFile);
8670 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8671 ITypeLib2_Release(&This->ITypeLib2_iface);
8672 return hres;
8675 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8676 REFIID riid, void **object)
8678 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8680 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8683 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8685 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8687 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8690 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8692 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8694 return ITypeLib2_Release(&This->ITypeLib2_iface);
8697 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8698 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8700 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8701 ITypeInfoImpl *info;
8702 HRESULT hres;
8704 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8706 if (!ctinfo || !name)
8707 return E_INVALIDARG;
8709 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8710 if (info)
8711 return TYPE_E_NAMECONFLICT;
8713 if (This->typeinfos)
8714 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8715 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8716 else
8717 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8719 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8721 info->pTypeLib = This;
8722 info->Name = TLB_append_str(&This->name_list, name);
8723 info->index = This->TypeInfoCount;
8724 info->typekind = kind;
8725 info->cbAlignment = 4;
8727 switch(info->typekind) {
8728 case TKIND_ENUM:
8729 case TKIND_INTERFACE:
8730 case TKIND_DISPATCH:
8731 case TKIND_COCLASS:
8732 info->cbSizeInstance = This->ptr_size;
8733 break;
8734 case TKIND_RECORD:
8735 case TKIND_UNION:
8736 info->cbSizeInstance = 0;
8737 break;
8738 case TKIND_MODULE:
8739 info->cbSizeInstance = 2;
8740 break;
8741 case TKIND_ALIAS:
8742 info->cbSizeInstance = -0x75;
8743 break;
8744 default:
8745 FIXME("unrecognized typekind %d\n", info->typekind);
8746 info->cbSizeInstance = 0xdeadbeef;
8747 break;
8750 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8751 &IID_ICreateTypeInfo, (void **)ctinfo);
8752 if (FAILED(hres)) {
8753 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8754 return hres;
8757 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8759 ++This->TypeInfoCount;
8761 return S_OK;
8764 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8765 LPOLESTR name)
8767 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8769 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8771 if (!name)
8772 return E_INVALIDARG;
8774 This->Name = TLB_append_str(&This->name_list, name);
8776 return S_OK;
8779 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8780 WORD majorVerNum, WORD minorVerNum)
8782 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8784 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8786 This->ver_major = majorVerNum;
8787 This->ver_minor = minorVerNum;
8789 return S_OK;
8792 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8793 REFGUID guid)
8795 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8797 TRACE("%p %s\n", This, debugstr_guid(guid));
8799 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8801 return S_OK;
8804 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8805 LPOLESTR doc)
8807 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8809 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8811 if (!doc)
8812 return E_INVALIDARG;
8814 This->DocString = TLB_append_str(&This->string_list, doc);
8816 return S_OK;
8819 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8820 LPOLESTR helpFileName)
8822 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8824 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8826 if (!helpFileName)
8827 return E_INVALIDARG;
8829 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8831 return S_OK;
8834 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8835 DWORD helpContext)
8837 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8839 TRACE("%p %d\n", This, helpContext);
8841 This->dwHelpContext = helpContext;
8843 return S_OK;
8846 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8847 LCID lcid)
8849 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8851 TRACE("%p %x\n", This, lcid);
8853 This->set_lcid = lcid;
8855 return S_OK;
8858 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8859 UINT libFlags)
8861 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8863 TRACE("%p %x\n", This, libFlags);
8865 This->libflags = libFlags;
8867 return S_OK;
8870 typedef struct tagWMSFT_SegContents {
8871 DWORD len;
8872 void *data;
8873 } WMSFT_SegContents;
8875 typedef struct tagWMSFT_TLBFile {
8876 MSFT_Header header;
8877 WMSFT_SegContents typeinfo_seg;
8878 WMSFT_SegContents impfile_seg;
8879 WMSFT_SegContents impinfo_seg;
8880 WMSFT_SegContents ref_seg;
8881 WMSFT_SegContents guidhash_seg;
8882 WMSFT_SegContents guid_seg;
8883 WMSFT_SegContents namehash_seg;
8884 WMSFT_SegContents name_seg;
8885 WMSFT_SegContents string_seg;
8886 WMSFT_SegContents typdesc_seg;
8887 WMSFT_SegContents arraydesc_seg;
8888 WMSFT_SegContents custdata_seg;
8889 WMSFT_SegContents cdguids_seg;
8890 MSFT_SegDir segdir;
8891 WMSFT_SegContents aux_seg;
8892 } WMSFT_TLBFile;
8894 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8895 WMSFT_TLBFile *file)
8897 TLBString *str;
8898 UINT last_offs;
8899 char *data;
8901 file->string_seg.len = 0;
8902 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8903 int size;
8905 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8906 if (size == 0)
8907 return E_UNEXPECTED;
8909 size += sizeof(INT16);
8910 if (size % 4)
8911 size = (size + 4) & ~0x3;
8912 if (size < 8)
8913 size = 8;
8915 file->string_seg.len += size;
8917 /* temporarily use str->offset to store the length of the aligned,
8918 * converted string */
8919 str->offset = size;
8922 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8924 last_offs = 0;
8925 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8926 int size;
8928 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8929 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8930 if (size == 0) {
8931 heap_free(file->string_seg.data);
8932 return E_UNEXPECTED;
8935 *((INT16*)data) = size;
8937 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8939 size = str->offset;
8940 data += size;
8941 str->offset = last_offs;
8942 last_offs += size;
8945 return S_OK;
8948 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8949 WMSFT_TLBFile *file)
8951 TLBString *str;
8952 UINT last_offs;
8953 char *data;
8954 MSFT_NameIntro *last_intro = NULL;
8956 file->header.nametablecount = 0;
8957 file->header.nametablechars = 0;
8959 file->name_seg.len = 0;
8960 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8961 int size;
8963 size = strlenW(str->str);
8964 file->header.nametablechars += size;
8965 file->header.nametablecount++;
8967 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8968 if (size == 0)
8969 return E_UNEXPECTED;
8971 size += sizeof(MSFT_NameIntro);
8972 if (size % 4)
8973 size = (size + 4) & ~0x3;
8974 if (size < 8)
8975 size = 8;
8977 file->name_seg.len += size;
8979 /* temporarily use str->offset to store the length of the aligned,
8980 * converted string */
8981 str->offset = size;
8984 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8985 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8987 last_offs = 0;
8988 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8989 int size, hash;
8990 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8992 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8993 data + sizeof(MSFT_NameIntro),
8994 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8995 if (size == 0) {
8996 heap_free(file->name_seg.data);
8997 return E_UNEXPECTED;
8999 data[sizeof(MSFT_NameIntro) + size] = '\0';
9001 intro->hreftype = -1; /* TODO? */
9002 intro->namelen = size & 0xFF;
9003 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9004 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9005 intro->namelen |= hash << 16;
9006 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9007 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9009 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9010 str->offset - size - sizeof(MSFT_NameIntro));
9012 /* update str->offset to actual value to use in other
9013 * compilation functions that require positions within
9014 * the string table */
9015 last_intro = intro;
9016 size = str->offset;
9017 data += size;
9018 str->offset = last_offs;
9019 last_offs += size;
9022 if(last_intro)
9023 last_intro->hreftype = 0; /* last one is 0? */
9025 return S_OK;
9028 static inline int hash_guid(GUID *guid)
9030 int i, hash = 0;
9032 for (i = 0; i < 8; i ++)
9033 hash ^= ((const short *)guid)[i];
9035 return hash & 0x1f;
9038 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9040 TLBGuid *guid;
9041 MSFT_GuidEntry *entry;
9042 DWORD offs;
9043 int hash_key, *guidhashtab;
9045 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9046 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9048 entry = file->guid_seg.data;
9049 offs = 0;
9050 guidhashtab = file->guidhash_seg.data;
9051 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9052 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9053 entry->hreftype = guid->hreftype;
9055 hash_key = hash_guid(&guid->guid);
9056 entry->next_hash = guidhashtab[hash_key];
9057 guidhashtab[hash_key] = offs;
9059 guid->offset = offs;
9060 offs += sizeof(MSFT_GuidEntry);
9061 ++entry;
9064 return S_OK;
9067 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9069 VARIANT v = *value;
9070 VARTYPE arg_type = V_VT(value);
9071 int mask = 0;
9072 HRESULT hres;
9073 DWORD ret = file->custdata_seg.len;
9075 if(arg_type == VT_INT)
9076 arg_type = VT_I4;
9077 if(arg_type == VT_UINT)
9078 arg_type = VT_UI4;
9080 v = *value;
9081 if(V_VT(value) != arg_type) {
9082 hres = VariantChangeType(&v, value, 0, arg_type);
9083 if(FAILED(hres)){
9084 ERR("VariantChangeType failed: %08x\n", hres);
9085 return -1;
9089 /* Check if default value can be stored in-place */
9090 switch(arg_type){
9091 case VT_I4:
9092 case VT_UI4:
9093 mask = 0x3ffffff;
9094 if(V_UI4(&v) > 0x3ffffff)
9095 break;
9096 /* fall through */
9097 case VT_I1:
9098 case VT_UI1:
9099 case VT_BOOL:
9100 if(!mask)
9101 mask = 0xff;
9102 /* fall through */
9103 case VT_I2:
9104 case VT_UI2:
9105 if(!mask)
9106 mask = 0xffff;
9107 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9110 /* have to allocate space in custdata_seg */
9111 switch(arg_type) {
9112 case VT_I4:
9113 case VT_R4:
9114 case VT_UI4:
9115 case VT_INT:
9116 case VT_UINT:
9117 case VT_HRESULT:
9118 case VT_PTR: {
9119 /* Construct the data to be allocated */
9120 int *data;
9122 if(file->custdata_seg.data){
9123 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9124 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9125 file->custdata_seg.len += sizeof(int) * 2;
9126 }else{
9127 file->custdata_seg.len = sizeof(int) * 2;
9128 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9131 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9132 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9134 /* TODO: Check if the encoded data is already present in custdata_seg */
9136 return ret;
9139 case VT_BSTR: {
9140 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9141 char *data;
9143 if(file->custdata_seg.data){
9144 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9145 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9146 file->custdata_seg.len += len;
9147 }else{
9148 file->custdata_seg.len = len;
9149 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9152 *((unsigned short *)data) = V_VT(value);
9153 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9154 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9155 if(V_BSTR(&v)[i] <= 0x7f)
9156 data[i+6] = V_BSTR(&v)[i];
9157 else
9158 data[i+6] = '?';
9160 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9161 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9162 data[i] = 0x57;
9164 /* TODO: Check if the encoded data is already present in custdata_seg */
9166 return ret;
9168 default:
9169 FIXME("Argument type not yet handled\n");
9170 return -1;
9174 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9176 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9178 DWORD offs = file->arraydesc_seg.len;
9179 DWORD *encoded;
9180 USHORT i;
9182 /* TODO: we should check for duplicates, but that's harder because each
9183 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9184 * at the library-level) */
9186 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9187 if(!file->arraydesc_seg.data)
9188 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9189 else
9190 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9191 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9193 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9194 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9195 for(i = 0; i < desc->cDims; ++i){
9196 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9197 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9200 return offs;
9203 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9205 DWORD junk;
9206 INT16 junk2;
9207 DWORD offs = 0;
9208 DWORD encoded[2];
9209 VARTYPE vt, subtype;
9210 char *data;
9212 if(!desc)
9213 return -1;
9215 if(!out_mix)
9216 out_mix = &junk;
9217 if(!out_size)
9218 out_size = &junk2;
9220 vt = desc->vt & VT_TYPEMASK;
9222 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9223 DWORD mix;
9224 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9225 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9226 *out_mix = 0x7FFF;
9227 *out_size += 2 * sizeof(DWORD);
9228 }else if(vt == VT_CARRAY){
9229 encoded[0] = desc->vt | (0x7FFE << 16);
9230 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9231 *out_mix = 0x7FFE;
9232 }else if(vt == VT_USERDEFINED){
9233 encoded[0] = desc->vt | (0x7FFF << 16);
9234 encoded[1] = desc->u.hreftype;
9235 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9236 }else{
9237 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9239 switch(vt){
9240 case VT_INT:
9241 subtype = VT_I4;
9242 break;
9243 case VT_UINT:
9244 subtype = VT_UI4;
9245 break;
9246 case VT_VOID:
9247 subtype = VT_EMPTY;
9248 break;
9249 default:
9250 subtype = vt;
9251 break;
9254 *out_mix = subtype;
9255 return 0x80000000 | (subtype << 16) | desc->vt;
9258 data = file->typdesc_seg.data;
9259 while(offs < file->typdesc_seg.len){
9260 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9261 return offs;
9262 offs += sizeof(encoded);
9265 file->typdesc_seg.len += sizeof(encoded);
9266 if(!file->typdesc_seg.data)
9267 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9268 else
9269 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9271 memcpy(&data[offs], encoded, sizeof(encoded));
9273 return offs;
9276 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9278 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9279 DWORD ret = cdguids_seg->len, offs;
9280 MSFT_CDGuid *cdguid = cdguids_seg->data;
9281 TLBCustData *cd;
9283 if(list_empty(custdata_list))
9284 return -1;
9286 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9287 if(!cdguids_seg->data){
9288 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9289 }else
9290 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9292 offs = ret + sizeof(MSFT_CDGuid);
9293 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9294 cdguid->GuidOffset = cd->guid->offset;
9295 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9296 cdguid->next = offs;
9297 offs += sizeof(MSFT_CDGuid);
9298 ++cdguid;
9301 --cdguid;
9302 cdguid->next = -1;
9304 return ret;
9307 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9308 WMSFT_TLBFile *file)
9310 WMSFT_SegContents *aux_seg = &file->aux_seg;
9311 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9312 MSFT_VarRecord *varrecord;
9313 MSFT_FuncRecord *funcrecord;
9314 MEMBERID *memid;
9315 DWORD *name, *offsets, offs;
9317 for(i = 0; i < info->cFuncs; ++i){
9318 TLBFuncDesc *desc = &info->funcdescs[i];
9320 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9322 /* optional fields */
9323 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9324 if(!list_empty(&desc->custdata_list))
9325 recorded_size += 7 * sizeof(INT);
9326 else if(desc->HelpStringContext != 0)
9327 recorded_size += 6 * sizeof(INT);
9328 /* res9? resA? */
9329 else if(desc->Entry)
9330 recorded_size += 3 * sizeof(INT);
9331 else if(desc->HelpString)
9332 recorded_size += 2 * sizeof(INT);
9333 else if(desc->helpcontext)
9334 recorded_size += sizeof(INT);
9336 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9338 for(j = 0; j < desc->funcdesc.cParams; ++j){
9339 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9340 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9341 break;
9345 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9348 for(i = 0; i < info->cVars; ++i){
9349 TLBVarDesc *desc = &info->vardescs[i];
9351 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9353 /* optional fields */
9354 if(desc->HelpStringContext != 0)
9355 recorded_size += 5 * sizeof(INT);
9356 else if(!list_empty(&desc->custdata_list))
9357 recorded_size += 4 * sizeof(INT);
9358 /* res9? */
9359 else if(desc->HelpString)
9360 recorded_size += 2 * sizeof(INT);
9361 else if(desc->HelpContext != 0)
9362 recorded_size += sizeof(INT);
9364 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9367 if(!recorded_size && !extra_size)
9368 return ret;
9370 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9372 aux_seg->len += recorded_size + extra_size;
9374 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9376 if(aux_seg->data)
9377 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9378 else
9379 aux_seg->data = heap_alloc(aux_seg->len);
9381 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9383 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9384 offs = 0;
9386 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9387 for(i = 0; i < info->cFuncs; ++i){
9388 TLBFuncDesc *desc = &info->funcdescs[i];
9389 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9391 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9392 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9393 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9394 funcrecord->VtableOffset = desc->funcdesc.oVft;
9396 /* FKCCIC:
9397 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9398 * ^^^funckind
9399 * ^^^ ^invkind
9400 * ^has_cust_data
9401 * ^^^^callconv
9402 * ^has_param_defaults
9403 * ^oEntry_is_intresource
9405 funcrecord->FKCCIC =
9406 desc->funcdesc.funckind |
9407 (desc->funcdesc.invkind << 3) |
9408 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9409 (desc->funcdesc.callconv << 8);
9411 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9412 funcrecord->FKCCIC |= 0x2000;
9414 for(j = 0; j < desc->funcdesc.cParams; ++j){
9415 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9416 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9417 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9420 if(paramdefault_size > 0)
9421 funcrecord->FKCCIC |= 0x1000;
9423 funcrecord->nrargs = desc->funcdesc.cParams;
9424 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9426 /* optional fields */
9427 /* res9? resA? */
9428 if(!list_empty(&desc->custdata_list)){
9429 size += 7 * sizeof(INT);
9430 funcrecord->HelpContext = desc->helpcontext;
9431 if(desc->HelpString)
9432 funcrecord->oHelpString = desc->HelpString->offset;
9433 else
9434 funcrecord->oHelpString = -1;
9435 if(!desc->Entry)
9436 funcrecord->oEntry = -1;
9437 else if(IS_INTRESOURCE(desc->Entry))
9438 funcrecord->oEntry = LOWORD(desc->Entry);
9439 else
9440 funcrecord->oEntry = desc->Entry->offset;
9441 funcrecord->res9 = -1;
9442 funcrecord->resA = -1;
9443 funcrecord->HelpStringContext = desc->HelpStringContext;
9444 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9445 }else if(desc->HelpStringContext != 0){
9446 size += 6 * sizeof(INT);
9447 funcrecord->HelpContext = desc->helpcontext;
9448 if(desc->HelpString)
9449 funcrecord->oHelpString = desc->HelpString->offset;
9450 else
9451 funcrecord->oHelpString = -1;
9452 if(!desc->Entry)
9453 funcrecord->oEntry = -1;
9454 else if(IS_INTRESOURCE(desc->Entry))
9455 funcrecord->oEntry = LOWORD(desc->Entry);
9456 else
9457 funcrecord->oEntry = desc->Entry->offset;
9458 funcrecord->res9 = -1;
9459 funcrecord->resA = -1;
9460 funcrecord->HelpStringContext = desc->HelpStringContext;
9461 }else if(desc->Entry){
9462 size += 3 * sizeof(INT);
9463 funcrecord->HelpContext = desc->helpcontext;
9464 if(desc->HelpString)
9465 funcrecord->oHelpString = desc->HelpString->offset;
9466 else
9467 funcrecord->oHelpString = -1;
9468 if(!desc->Entry)
9469 funcrecord->oEntry = -1;
9470 else if(IS_INTRESOURCE(desc->Entry))
9471 funcrecord->oEntry = LOWORD(desc->Entry);
9472 else
9473 funcrecord->oEntry = desc->Entry->offset;
9474 }else if(desc->HelpString){
9475 size += 2 * sizeof(INT);
9476 funcrecord->HelpContext = desc->helpcontext;
9477 funcrecord->oHelpString = desc->HelpString->offset;
9478 }else if(desc->helpcontext){
9479 size += sizeof(INT);
9480 funcrecord->HelpContext = desc->helpcontext;
9483 paramdefault = (DWORD*)((char *)funcrecord + size);
9484 size += paramdefault_size;
9486 for(j = 0; j < desc->funcdesc.cParams; ++j){
9487 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9489 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9490 if(desc->pParamDesc[j].Name)
9491 info->oName = desc->pParamDesc[j].Name->offset;
9492 else
9493 info->oName = -1;
9494 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9496 if(paramdefault_size){
9497 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9498 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9499 else if(paramdefault_size)
9500 *paramdefault = -1;
9501 ++paramdefault;
9504 size += sizeof(MSFT_ParameterInfo);
9507 funcrecord->Info = size | (i << 16); /* is it just the index? */
9509 *offsets = offs;
9510 offs += size;
9511 ++offsets;
9513 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9516 varrecord = (MSFT_VarRecord*)funcrecord;
9517 for(i = 0; i < info->cVars; ++i){
9518 TLBVarDesc *desc = &info->vardescs[i];
9519 DWORD size = 5 * sizeof(INT);
9521 varrecord->vardescsize = sizeof(desc->vardesc);
9522 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9523 varrecord->Flags = desc->vardesc.wVarFlags;
9524 varrecord->VarKind = desc->vardesc.varkind;
9526 if(desc->vardesc.varkind == VAR_CONST){
9527 varrecord->vardescsize += sizeof(VARIANT);
9528 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9529 }else
9530 varrecord->OffsValue = desc->vardesc.u.oInst;
9532 /* res9? */
9533 if(desc->HelpStringContext != 0){
9534 size += 5 * sizeof(INT);
9535 varrecord->HelpContext = desc->HelpContext;
9536 if(desc->HelpString)
9537 varrecord->HelpString = desc->HelpString->offset;
9538 else
9539 varrecord->HelpString = -1;
9540 varrecord->res9 = -1;
9541 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9542 varrecord->HelpStringContext = desc->HelpStringContext;
9543 }else if(!list_empty(&desc->custdata_list)){
9544 size += 4 * sizeof(INT);
9545 varrecord->HelpContext = desc->HelpContext;
9546 if(desc->HelpString)
9547 varrecord->HelpString = desc->HelpString->offset;
9548 else
9549 varrecord->HelpString = -1;
9550 varrecord->res9 = -1;
9551 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9552 }else if(desc->HelpString){
9553 size += 2 * sizeof(INT);
9554 varrecord->HelpContext = desc->HelpContext;
9555 if(desc->HelpString)
9556 varrecord->HelpString = desc->HelpString->offset;
9557 else
9558 varrecord->HelpString = -1;
9559 }else if(desc->HelpContext != 0){
9560 size += sizeof(INT);
9561 varrecord->HelpContext = desc->HelpContext;
9564 varrecord->Info = size | (i << 16);
9566 *offsets = offs;
9567 offs += size;
9568 ++offsets;
9570 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9573 memid = (MEMBERID*)varrecord;
9574 for(i = 0; i < info->cFuncs; ++i){
9575 TLBFuncDesc *desc = &info->funcdescs[i];
9576 *memid = desc->funcdesc.memid;
9577 ++memid;
9579 for(i = 0; i < info->cVars; ++i){
9580 TLBVarDesc *desc = &info->vardescs[i];
9581 *memid = desc->vardesc.memid;
9582 ++memid;
9585 name = (UINT*)memid;
9586 for(i = 0; i < info->cFuncs; ++i){
9587 TLBFuncDesc *desc = &info->funcdescs[i];
9588 if(desc->Name)
9589 *name = desc->Name->offset;
9590 else
9591 *name = -1;
9592 ++name;
9594 for(i = 0; i < info->cVars; ++i){
9595 TLBVarDesc *desc = &info->vardescs[i];
9596 if(desc->Name)
9597 *name = desc->Name->offset;
9598 else
9599 *name = -1;
9600 ++name;
9603 return ret;
9606 typedef struct tagWMSFT_RefChunk {
9607 DWORD href;
9608 DWORD res04;
9609 DWORD res08;
9610 DWORD next;
9611 } WMSFT_RefChunk;
9613 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9615 DWORD offs = file->ref_seg.len, i;
9616 WMSFT_RefChunk *chunk;
9618 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9619 if(!file->ref_seg.data)
9620 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9621 else
9622 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9624 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9626 for(i = 0; i < info->cImplTypes; ++i){
9627 chunk->href = info->impltypes[i].hRef;
9628 chunk->res04 = info->impltypes[i].implflags;
9629 chunk->res08 = -1;
9630 if(i < info->cImplTypes - 1)
9631 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9632 else
9633 chunk->next = -1;
9634 ++chunk;
9637 return offs;
9640 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9642 DWORD size;
9644 size = sizeof(MSFT_TypeInfoBase);
9646 if(data){
9647 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9648 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9649 base->typekind = TKIND_DISPATCH;
9650 else
9651 base->typekind = info->typekind;
9652 base->typekind |= index << 16; /* TODO: There are some other flags here */
9653 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9654 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9655 base->res2 = 0;
9656 base->res3 = 0;
9657 base->res4 = 3;
9658 base->res5 = 0;
9659 base->cElement = (info->cVars << 16) | info->cFuncs;
9660 base->res7 = 0;
9661 base->res8 = 0;
9662 base->res9 = 0;
9663 base->resA = 0;
9664 if(info->guid)
9665 base->posguid = info->guid->offset;
9666 else
9667 base->posguid = -1;
9668 base->flags = info->wTypeFlags;
9669 if(info->Name) {
9670 base->NameOffset = info->Name->offset;
9672 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9673 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9674 }else {
9675 base->NameOffset = -1;
9677 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9678 if(info->DocString)
9679 base->docstringoffs = info->DocString->offset;
9680 else
9681 base->docstringoffs = -1;
9682 base->helpstringcontext = info->dwHelpStringContext;
9683 base->helpcontext = info->dwHelpContext;
9684 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9685 base->cImplTypes = info->cImplTypes;
9686 base->cbSizeVft = info->cbSizeVft;
9687 base->size = info->cbSizeInstance;
9688 if(info->typekind == TKIND_COCLASS){
9689 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9690 }else if(info->typekind == TKIND_ALIAS){
9691 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9692 }else if(info->typekind == TKIND_MODULE){
9693 if(info->DllName)
9694 base->datatype1 = info->DllName->offset;
9695 else
9696 base->datatype1 = -1;
9697 }else{
9698 if(info->cImplTypes > 0)
9699 base->datatype1 = info->impltypes[0].hRef;
9700 else
9701 base->datatype1 = -1;
9703 base->datatype2 = index; /* FIXME: i think there's more here */
9704 base->res18 = 0;
9705 base->res19 = -1;
9708 return size;
9711 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9713 UINT i;
9715 file->typeinfo_seg.len = 0;
9716 for(i = 0; i < This->TypeInfoCount; ++i){
9717 ITypeInfoImpl *info = This->typeinfos[i];
9718 *junk = file->typeinfo_seg.len;
9719 ++junk;
9720 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9723 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9724 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9726 file->aux_seg.len = 0;
9727 file->aux_seg.data = NULL;
9729 file->typeinfo_seg.len = 0;
9730 for(i = 0; i < This->TypeInfoCount; ++i){
9731 ITypeInfoImpl *info = This->typeinfos[i];
9732 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9733 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9737 typedef struct tagWMSFT_ImpFile {
9738 INT guid_offs;
9739 LCID lcid;
9740 DWORD version;
9741 } WMSFT_ImpFile;
9743 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9745 TLBImpLib *implib;
9746 WMSFT_ImpFile *impfile;
9747 char *data;
9748 DWORD last_offs = 0;
9750 file->impfile_seg.len = 0;
9751 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9752 int size = 0;
9754 if(implib->name){
9755 WCHAR *path = strrchrW(implib->name, '\\');
9756 if(path)
9757 ++path;
9758 else
9759 path = implib->name;
9760 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9761 if (size == 0)
9762 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9765 size += sizeof(INT16);
9766 if (size % 4)
9767 size = (size + 4) & ~0x3;
9768 if (size < 8)
9769 size = 8;
9771 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9774 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9776 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9777 int strlen = 0, size;
9779 impfile = (WMSFT_ImpFile*)data;
9780 impfile->guid_offs = implib->guid->offset;
9781 impfile->lcid = implib->lcid;
9782 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9784 data += sizeof(WMSFT_ImpFile);
9786 if(implib->name){
9787 WCHAR *path= strrchrW(implib->name, '\\');
9788 if(path)
9789 ++path;
9790 else
9791 path = implib->name;
9792 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9793 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9794 if (strlen == 0)
9795 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9798 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9800 size = strlen + sizeof(INT16);
9801 if (size % 4)
9802 size = (size + 4) & ~0x3;
9803 if (size < 8)
9804 size = 8;
9805 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9807 data += size;
9808 implib->offset = last_offs;
9809 last_offs += size + sizeof(WMSFT_ImpFile);
9813 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9815 MSFT_ImpInfo *info;
9816 TLBRefType *ref_type;
9817 UINT i = 0;
9819 WMSFT_compile_impfile(This, file);
9821 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9822 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9824 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9825 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9826 if(ref_type->index == TLB_REF_USE_GUID){
9827 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9828 info->oGuid = ref_type->guid->offset;
9829 }else
9830 info->oGuid = ref_type->index;
9831 info->oImpFile = ref_type->pImpTLInfo->offset;
9832 ++i;
9833 ++info;
9837 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9839 file->guidhash_seg.len = 0x80;
9840 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9841 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9844 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9846 file->namehash_seg.len = 0x200;
9847 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9848 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9851 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9853 if(contents && contents->len){
9854 segdir->offset = *running_offset;
9855 segdir->length = contents->len;
9856 *running_offset += segdir->length;
9857 }else{
9858 segdir->offset = -1;
9859 segdir->length = 0;
9862 /* TODO: do these ever change? */
9863 segdir->res08 = -1;
9864 segdir->res0c = 0xf;
9867 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9869 DWORD written;
9870 if(segment)
9871 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9874 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9875 DWORD file_len)
9877 DWORD i;
9878 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9880 for(i = 0; i < This->TypeInfoCount; ++i){
9881 base->memoffset += file_len;
9882 ++base;
9885 return S_OK;
9888 static void WMSFT_free_file(WMSFT_TLBFile *file)
9890 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9891 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9892 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9893 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9894 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9895 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9896 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9897 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9898 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9899 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9900 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9901 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9902 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9903 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9906 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9908 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9909 WMSFT_TLBFile file;
9910 DWORD written, junk_size, junk_offs, running_offset;
9911 BOOL br;
9912 HANDLE outfile;
9913 HRESULT hres;
9914 DWORD *junk;
9915 UINT i;
9917 TRACE("%p\n", This);
9919 for(i = 0; i < This->TypeInfoCount; ++i)
9920 if(This->typeinfos[i]->needs_layout)
9921 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9923 memset(&file, 0, sizeof(file));
9925 file.header.magic1 = 0x5446534D;
9926 file.header.magic2 = 0x00010002;
9927 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9928 file.header.lcid2 = This->set_lcid;
9929 file.header.varflags = 0x40 | This->syskind;
9930 if (This->HelpFile)
9931 file.header.varflags |= 0x10;
9932 if (This->HelpStringDll)
9933 file.header.varflags |= HELPDLLFLAG;
9934 file.header.version = (This->ver_minor << 16) | This->ver_major;
9935 file.header.flags = This->libflags;
9936 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9937 file.header.helpcontext = This->dwHelpContext;
9938 file.header.res44 = 0x20;
9939 file.header.res48 = 0x80;
9940 file.header.dispatchpos = This->dispatch_href;
9942 WMSFT_compile_namehash(This, &file);
9943 /* do name and string compilation to get offsets for other compilations */
9944 hres = WMSFT_compile_names(This, &file);
9945 if (FAILED(hres)){
9946 WMSFT_free_file(&file);
9947 return hres;
9950 hres = WMSFT_compile_strings(This, &file);
9951 if (FAILED(hres)){
9952 WMSFT_free_file(&file);
9953 return hres;
9956 WMSFT_compile_guidhash(This, &file);
9957 hres = WMSFT_compile_guids(This, &file);
9958 if (FAILED(hres)){
9959 WMSFT_free_file(&file);
9960 return hres;
9963 if(This->HelpFile)
9964 file.header.helpfile = This->HelpFile->offset;
9965 else
9966 file.header.helpfile = -1;
9968 if(This->DocString)
9969 file.header.helpstring = This->DocString->offset;
9970 else
9971 file.header.helpstring = -1;
9973 /* do some more segment compilation */
9974 file.header.nimpinfos = list_count(&This->ref_list);
9975 file.header.nrtypeinfos = This->TypeInfoCount;
9977 if(This->Name)
9978 file.header.NameOffset = This->Name->offset;
9979 else
9980 file.header.NameOffset = -1;
9982 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9984 if(This->guid)
9985 file.header.posguid = This->guid->offset;
9986 else
9987 file.header.posguid = -1;
9989 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9990 if(file.header.varflags & HELPDLLFLAG)
9991 junk_size += sizeof(DWORD);
9992 if(junk_size){
9993 junk = heap_alloc_zero(junk_size);
9994 if(file.header.varflags & HELPDLLFLAG){
9995 *junk = This->HelpStringDll->offset;
9996 junk_offs = 1;
9997 }else
9998 junk_offs = 0;
9999 }else{
10000 junk = NULL;
10001 junk_offs = 0;
10004 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10005 WMSFT_compile_impinfo(This, &file);
10007 running_offset = 0;
10009 TRACE("header at: 0x%x\n", running_offset);
10010 running_offset += sizeof(file.header);
10012 TRACE("junk at: 0x%x\n", running_offset);
10013 running_offset += junk_size;
10015 TRACE("segdir at: 0x%x\n", running_offset);
10016 running_offset += sizeof(file.segdir);
10018 TRACE("typeinfo at: 0x%x\n", running_offset);
10019 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10021 TRACE("guidhashtab at: 0x%x\n", running_offset);
10022 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10024 TRACE("guidtab at: 0x%x\n", running_offset);
10025 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10027 TRACE("reftab at: 0x%x\n", running_offset);
10028 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10030 TRACE("impinfo at: 0x%x\n", running_offset);
10031 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10033 TRACE("impfiles at: 0x%x\n", running_offset);
10034 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10036 TRACE("namehashtab at: 0x%x\n", running_offset);
10037 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10039 TRACE("nametab at: 0x%x\n", running_offset);
10040 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10042 TRACE("stringtab at: 0x%x\n", running_offset);
10043 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10045 TRACE("typdesc at: 0x%x\n", running_offset);
10046 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10048 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10049 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10051 TRACE("custdata at: 0x%x\n", running_offset);
10052 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10054 TRACE("cdguids at: 0x%x\n", running_offset);
10055 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10057 TRACE("res0e at: 0x%x\n", running_offset);
10058 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10060 TRACE("res0f at: 0x%x\n", running_offset);
10061 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10063 TRACE("aux_seg at: 0x%x\n", running_offset);
10065 WMSFT_fixup_typeinfos(This, &file, running_offset);
10067 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10068 FILE_ATTRIBUTE_NORMAL, 0);
10069 if (outfile == INVALID_HANDLE_VALUE){
10070 WMSFT_free_file(&file);
10071 heap_free(junk);
10072 return TYPE_E_IOERROR;
10075 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10076 if (!br) {
10077 WMSFT_free_file(&file);
10078 CloseHandle(outfile);
10079 heap_free(junk);
10080 return TYPE_E_IOERROR;
10083 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10084 heap_free(junk);
10085 if (!br) {
10086 WMSFT_free_file(&file);
10087 CloseHandle(outfile);
10088 return TYPE_E_IOERROR;
10091 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10092 if (!br) {
10093 WMSFT_free_file(&file);
10094 CloseHandle(outfile);
10095 return TYPE_E_IOERROR;
10098 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10099 WMSFT_write_segment(outfile, &file.guidhash_seg);
10100 WMSFT_write_segment(outfile, &file.guid_seg);
10101 WMSFT_write_segment(outfile, &file.ref_seg);
10102 WMSFT_write_segment(outfile, &file.impinfo_seg);
10103 WMSFT_write_segment(outfile, &file.impfile_seg);
10104 WMSFT_write_segment(outfile, &file.namehash_seg);
10105 WMSFT_write_segment(outfile, &file.name_seg);
10106 WMSFT_write_segment(outfile, &file.string_seg);
10107 WMSFT_write_segment(outfile, &file.typdesc_seg);
10108 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10109 WMSFT_write_segment(outfile, &file.custdata_seg);
10110 WMSFT_write_segment(outfile, &file.cdguids_seg);
10111 WMSFT_write_segment(outfile, &file.aux_seg);
10113 WMSFT_free_file(&file);
10115 CloseHandle(outfile);
10117 return S_OK;
10120 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10121 LPOLESTR name)
10123 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10124 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10125 return E_NOTIMPL;
10128 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10129 REFGUID guid, VARIANT *varVal)
10131 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10132 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
10133 return E_NOTIMPL;
10136 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10137 ULONG helpStringContext)
10139 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10140 FIXME("%p %u - stub\n", This, helpStringContext);
10141 return E_NOTIMPL;
10144 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10145 LPOLESTR filename)
10147 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10148 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10150 if (!filename)
10151 return E_INVALIDARG;
10153 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10155 return S_OK;
10158 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10159 ICreateTypeLib2_fnQueryInterface,
10160 ICreateTypeLib2_fnAddRef,
10161 ICreateTypeLib2_fnRelease,
10162 ICreateTypeLib2_fnCreateTypeInfo,
10163 ICreateTypeLib2_fnSetName,
10164 ICreateTypeLib2_fnSetVersion,
10165 ICreateTypeLib2_fnSetGuid,
10166 ICreateTypeLib2_fnSetDocString,
10167 ICreateTypeLib2_fnSetHelpFileName,
10168 ICreateTypeLib2_fnSetHelpContext,
10169 ICreateTypeLib2_fnSetLcid,
10170 ICreateTypeLib2_fnSetLibFlags,
10171 ICreateTypeLib2_fnSaveAllChanges,
10172 ICreateTypeLib2_fnDeleteTypeInfo,
10173 ICreateTypeLib2_fnSetCustData,
10174 ICreateTypeLib2_fnSetHelpStringContext,
10175 ICreateTypeLib2_fnSetHelpStringDll
10178 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10179 REFIID riid, void **object)
10181 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10183 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10186 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10188 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10190 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10193 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10195 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10197 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10200 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10201 REFGUID guid)
10203 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10205 TRACE("%p %s\n", This, debugstr_guid(guid));
10207 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10209 return S_OK;
10212 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10213 UINT typeFlags)
10215 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10216 WORD old_flags;
10217 HRESULT hres;
10219 TRACE("%p %x\n", This, typeFlags);
10221 if (typeFlags & TYPEFLAG_FDUAL) {
10222 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10223 ITypeLib *stdole;
10224 ITypeInfo *dispatch;
10225 HREFTYPE hreftype;
10226 HRESULT hres;
10228 hres = LoadTypeLib(stdole2tlb, &stdole);
10229 if(FAILED(hres))
10230 return hres;
10232 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10233 ITypeLib_Release(stdole);
10234 if(FAILED(hres))
10235 return hres;
10237 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10238 ITypeInfo_Release(dispatch);
10239 if(FAILED(hres))
10240 return hres;
10243 old_flags = This->wTypeFlags;
10244 This->wTypeFlags = typeFlags;
10246 hres = ICreateTypeInfo2_LayOut(iface);
10247 if (FAILED(hres)) {
10248 This->wTypeFlags = old_flags;
10249 return hres;
10252 return S_OK;
10255 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10256 LPOLESTR doc)
10258 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10260 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10262 if (!doc)
10263 return E_INVALIDARG;
10265 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10267 return S_OK;
10270 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10271 DWORD helpContext)
10273 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10275 TRACE("%p %d\n", This, helpContext);
10277 This->dwHelpContext = helpContext;
10279 return S_OK;
10282 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10283 WORD majorVerNum, WORD minorVerNum)
10285 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10287 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10289 This->wMajorVerNum = majorVerNum;
10290 This->wMinorVerNum = minorVerNum;
10292 return S_OK;
10295 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10296 ITypeInfo *typeInfo, HREFTYPE *refType)
10298 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10299 UINT index;
10300 ITypeLib *container;
10301 TLBRefType *ref_type;
10302 TLBImpLib *implib;
10303 TYPEATTR *typeattr;
10304 TLIBATTR *libattr;
10305 HRESULT hres;
10307 TRACE("%p %p %p\n", This, typeInfo, refType);
10309 if (!typeInfo || !refType)
10310 return E_INVALIDARG;
10312 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10313 if (FAILED(hres))
10314 return hres;
10316 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10317 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10319 ITypeLib_Release(container);
10321 *refType = target->hreftype;
10323 return S_OK;
10326 hres = ITypeLib_GetLibAttr(container, &libattr);
10327 if (FAILED(hres)) {
10328 ITypeLib_Release(container);
10329 return hres;
10332 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10333 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10334 implib->lcid == libattr->lcid &&
10335 implib->wVersionMajor == libattr->wMajorVerNum &&
10336 implib->wVersionMinor == libattr->wMinorVerNum)
10337 break;
10340 if(&implib->entry == &This->pTypeLib->implib_list){
10341 implib = heap_alloc_zero(sizeof(TLBImpLib));
10343 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10344 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10345 implib->name = SysAllocString(our_container->path);
10346 }else{
10347 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10348 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10349 if(FAILED(hres)){
10350 implib->name = NULL;
10351 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10355 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10356 implib->lcid = libattr->lcid;
10357 implib->wVersionMajor = libattr->wMajorVerNum;
10358 implib->wVersionMinor = libattr->wMinorVerNum;
10360 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10363 ITypeLib_ReleaseTLibAttr(container, libattr);
10364 ITypeLib_Release(container);
10366 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10367 if (FAILED(hres))
10368 return hres;
10370 index = 0;
10371 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10372 if(ref_type->index == TLB_REF_USE_GUID &&
10373 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10374 ref_type->tkind == typeattr->typekind)
10375 break;
10376 ++index;
10379 if(&ref_type->entry == &This->pTypeLib->ref_list){
10380 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10382 ref_type->tkind = typeattr->typekind;
10383 ref_type->pImpTLInfo = implib;
10384 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10386 ref_type->index = TLB_REF_USE_GUID;
10388 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10390 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10393 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10395 *refType = ref_type->reference | 0x1;
10397 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10398 This->pTypeLib->dispatch_href = *refType;
10400 return S_OK;
10403 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10404 UINT index, FUNCDESC *funcDesc)
10406 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10407 TLBFuncDesc tmp_func_desc, *func_desc;
10408 int buf_size, i;
10409 char *buffer;
10410 HRESULT hres;
10412 TRACE("%p %u %p\n", This, index, funcDesc);
10414 if (!funcDesc || funcDesc->oVft & 3)
10415 return E_INVALIDARG;
10417 switch (This->typekind) {
10418 case TKIND_MODULE:
10419 if (funcDesc->funckind != FUNC_STATIC)
10420 return TYPE_E_BADMODULEKIND;
10421 break;
10422 case TKIND_DISPATCH:
10423 if (funcDesc->funckind != FUNC_DISPATCH)
10424 return TYPE_E_BADMODULEKIND;
10425 break;
10426 default:
10427 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10428 return TYPE_E_BADMODULEKIND;
10431 if (index > This->cFuncs)
10432 return TYPE_E_ELEMENTNOTFOUND;
10434 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10435 !funcDesc->cParams)
10436 return TYPE_E_INCONSISTENTPROPFUNCS;
10438 #ifdef _WIN64
10439 if(This->pTypeLib->syskind == SYS_WIN64 &&
10440 funcDesc->oVft % 8 != 0)
10441 return E_INVALIDARG;
10442 #endif
10444 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10445 TLBFuncDesc_Constructor(&tmp_func_desc);
10447 tmp_func_desc.funcdesc = *funcDesc;
10449 if (tmp_func_desc.funcdesc.oVft != 0)
10450 tmp_func_desc.funcdesc.oVft |= 1;
10452 if (funcDesc->cScodes) {
10453 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10454 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10455 } else
10456 tmp_func_desc.funcdesc.lprgscode = NULL;
10458 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10459 for (i = 0; i < funcDesc->cParams; ++i) {
10460 buf_size += sizeof(ELEMDESC);
10461 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10463 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10464 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10466 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10467 if (FAILED(hres)) {
10468 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10469 heap_free(tmp_func_desc.funcdesc.lprgscode);
10470 return hres;
10473 for (i = 0; i < funcDesc->cParams; ++i) {
10474 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10475 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10476 if (FAILED(hres)) {
10477 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10478 heap_free(tmp_func_desc.funcdesc.lprgscode);
10479 return hres;
10481 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10482 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10483 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10484 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10485 if (FAILED(hres)) {
10486 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10487 heap_free(tmp_func_desc.funcdesc.lprgscode);
10488 return hres;
10493 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10495 if (This->funcdescs) {
10496 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10497 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10499 if (index < This->cFuncs) {
10500 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10501 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10502 func_desc = This->funcdescs + index;
10503 } else
10504 func_desc = This->funcdescs + This->cFuncs;
10506 /* move custdata lists to the new memory location */
10507 for(i = 0; i < This->cFuncs + 1; ++i){
10508 if(index != i){
10509 TLBFuncDesc *fd = &This->funcdescs[i];
10510 if(fd->custdata_list.prev == fd->custdata_list.next)
10511 list_init(&fd->custdata_list);
10512 else{
10513 fd->custdata_list.prev->next = &fd->custdata_list;
10514 fd->custdata_list.next->prev = &fd->custdata_list;
10518 } else
10519 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10521 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10522 list_init(&func_desc->custdata_list);
10524 ++This->cFuncs;
10526 This->needs_layout = TRUE;
10528 return S_OK;
10531 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10532 UINT index, HREFTYPE refType)
10534 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10535 TLBImplType *impl_type;
10536 HRESULT hres;
10538 TRACE("%p %u %d\n", This, index, refType);
10540 switch(This->typekind){
10541 case TKIND_COCLASS: {
10542 if (index == -1) {
10543 FIXME("Unhandled index: -1\n");
10544 return E_NOTIMPL;
10547 if(index != This->cImplTypes)
10548 return TYPE_E_ELEMENTNOTFOUND;
10550 break;
10552 case TKIND_INTERFACE:
10553 case TKIND_DISPATCH:
10554 if (index != 0 || This->cImplTypes)
10555 return TYPE_E_ELEMENTNOTFOUND;
10556 break;
10557 default:
10558 FIXME("Unimplemented typekind: %d\n", This->typekind);
10559 return E_NOTIMPL;
10562 if (This->impltypes){
10563 UINT i;
10565 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10566 sizeof(TLBImplType) * (This->cImplTypes + 1));
10568 if (index < This->cImplTypes) {
10569 memmove(This->impltypes + index + 1, This->impltypes + index,
10570 (This->cImplTypes - index) * sizeof(TLBImplType));
10571 impl_type = This->impltypes + index;
10572 } else
10573 impl_type = This->impltypes + This->cImplTypes;
10575 /* move custdata lists to the new memory location */
10576 for(i = 0; i < This->cImplTypes + 1; ++i){
10577 if(index != i){
10578 TLBImplType *it = &This->impltypes[i];
10579 if(it->custdata_list.prev == it->custdata_list.next)
10580 list_init(&it->custdata_list);
10581 else{
10582 it->custdata_list.prev->next = &it->custdata_list;
10583 it->custdata_list.next->prev = &it->custdata_list;
10587 } else
10588 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10590 memset(impl_type, 0, sizeof(TLBImplType));
10591 TLBImplType_Constructor(impl_type);
10592 impl_type->hRef = refType;
10594 ++This->cImplTypes;
10596 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10597 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10599 hres = ICreateTypeInfo2_LayOut(iface);
10600 if (FAILED(hres))
10601 return hres;
10603 return S_OK;
10606 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10607 UINT index, INT implTypeFlags)
10609 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10610 TLBImplType *impl_type = &This->impltypes[index];
10612 TRACE("%p %u %x\n", This, index, implTypeFlags);
10614 if (This->typekind != TKIND_COCLASS)
10615 return TYPE_E_BADMODULEKIND;
10617 if (index >= This->cImplTypes)
10618 return TYPE_E_ELEMENTNOTFOUND;
10620 impl_type->implflags = implTypeFlags;
10622 return S_OK;
10625 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10626 WORD alignment)
10628 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10630 TRACE("%p %d\n", This, alignment);
10632 This->cbAlignment = alignment;
10634 return S_OK;
10637 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10638 LPOLESTR schema)
10640 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10642 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10644 if (!schema)
10645 return E_INVALIDARG;
10647 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10649 This->lpstrSchema = This->Schema->str;
10651 return S_OK;
10654 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10655 UINT index, VARDESC *varDesc)
10657 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10658 TLBVarDesc *var_desc;
10660 TRACE("%p %u %p\n", This, index, varDesc);
10662 if (This->vardescs){
10663 UINT i;
10665 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10666 sizeof(TLBVarDesc) * (This->cVars + 1));
10668 if (index < This->cVars) {
10669 memmove(This->vardescs + index + 1, This->vardescs + index,
10670 (This->cVars - index) * sizeof(TLBVarDesc));
10671 var_desc = This->vardescs + index;
10672 } else
10673 var_desc = This->vardescs + This->cVars;
10675 /* move custdata lists to the new memory location */
10676 for(i = 0; i < This->cVars + 1; ++i){
10677 if(index != i){
10678 TLBVarDesc *var = &This->vardescs[i];
10679 if(var->custdata_list.prev == var->custdata_list.next)
10680 list_init(&var->custdata_list);
10681 else{
10682 var->custdata_list.prev->next = &var->custdata_list;
10683 var->custdata_list.next->prev = &var->custdata_list;
10687 } else
10688 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10690 TLBVarDesc_Constructor(var_desc);
10691 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10692 var_desc->vardesc = *var_desc->vardesc_create;
10694 ++This->cVars;
10696 This->needs_layout = TRUE;
10698 return S_OK;
10701 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10702 UINT index, LPOLESTR *names, UINT numNames)
10704 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10705 TLBFuncDesc *func_desc = &This->funcdescs[index];
10706 int i;
10708 TRACE("%p %u %p %u\n", This, index, names, numNames);
10710 if (!names)
10711 return E_INVALIDARG;
10713 if (index >= This->cFuncs || numNames == 0)
10714 return TYPE_E_ELEMENTNOTFOUND;
10716 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10717 if(numNames > func_desc->funcdesc.cParams)
10718 return TYPE_E_ELEMENTNOTFOUND;
10719 } else
10720 if(numNames > func_desc->funcdesc.cParams + 1)
10721 return TYPE_E_ELEMENTNOTFOUND;
10723 for(i = 0; i < This->cFuncs; ++i) {
10724 TLBFuncDesc *iter = &This->funcdescs[i];
10725 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10726 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10727 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10728 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10729 continue;
10730 return TYPE_E_AMBIGUOUSNAME;
10734 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10736 for (i = 1; i < numNames; ++i) {
10737 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10738 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10741 return S_OK;
10744 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10745 UINT index, LPOLESTR name)
10747 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10749 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10751 if(!name)
10752 return E_INVALIDARG;
10754 if(index >= This->cVars)
10755 return TYPE_E_ELEMENTNOTFOUND;
10757 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10758 return S_OK;
10761 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10762 TYPEDESC *tdescAlias)
10764 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10765 HRESULT hr;
10767 TRACE("%p %p\n", This, tdescAlias);
10769 if(!tdescAlias)
10770 return E_INVALIDARG;
10772 if(This->typekind != TKIND_ALIAS)
10773 return TYPE_E_BADMODULEKIND;
10775 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->cbSizeInstance, &This->cbAlignment);
10776 if(FAILED(hr))
10777 return hr;
10779 heap_free(This->tdescAlias);
10780 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10781 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10783 return S_OK;
10786 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10787 UINT index, LPOLESTR dllName, LPOLESTR procName)
10789 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10790 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10791 return E_NOTIMPL;
10794 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10795 UINT index, LPOLESTR docString)
10797 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10798 TLBFuncDesc *func_desc = &This->funcdescs[index];
10800 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10802 if(!docString)
10803 return E_INVALIDARG;
10805 if(index >= This->cFuncs)
10806 return TYPE_E_ELEMENTNOTFOUND;
10808 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10810 return S_OK;
10813 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10814 UINT index, LPOLESTR docString)
10816 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10817 TLBVarDesc *var_desc = &This->vardescs[index];
10819 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10821 if(!docString)
10822 return E_INVALIDARG;
10824 if(index >= This->cVars)
10825 return TYPE_E_ELEMENTNOTFOUND;
10827 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10829 return S_OK;
10832 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10833 UINT index, DWORD helpContext)
10835 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10836 TLBFuncDesc *func_desc = &This->funcdescs[index];
10838 TRACE("%p %u %d\n", This, index, helpContext);
10840 if(index >= This->cFuncs)
10841 return TYPE_E_ELEMENTNOTFOUND;
10843 func_desc->helpcontext = helpContext;
10845 return S_OK;
10848 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10849 UINT index, DWORD helpContext)
10851 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10852 TLBVarDesc *var_desc = &This->vardescs[index];
10854 TRACE("%p %u %d\n", This, index, helpContext);
10856 if(index >= This->cVars)
10857 return TYPE_E_ELEMENTNOTFOUND;
10859 var_desc->HelpContext = helpContext;
10861 return S_OK;
10864 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10865 UINT index, BSTR bstrMops)
10867 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10868 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10869 return E_NOTIMPL;
10872 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10873 IDLDESC *idlDesc)
10875 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10877 TRACE("%p %p\n", This, idlDesc);
10879 if (!idlDesc)
10880 return E_INVALIDARG;
10882 This->idldescType.dwReserved = idlDesc->dwReserved;
10883 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10885 return S_OK;
10888 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10890 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10891 ITypeInfo *tinfo;
10892 TLBFuncDesc *func_desc;
10893 UINT user_vft = 0, i, depth = 0;
10894 HRESULT hres = S_OK;
10896 TRACE("%p\n", This);
10898 This->needs_layout = FALSE;
10900 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10901 if (FAILED(hres))
10902 return hres;
10904 if (This->typekind == TKIND_INTERFACE) {
10905 ITypeInfo *inh;
10906 TYPEATTR *attr;
10907 HREFTYPE inh_href;
10909 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10911 if (SUCCEEDED(hres)) {
10912 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10914 if (SUCCEEDED(hres)) {
10915 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10916 if (FAILED(hres)) {
10917 ITypeInfo_Release(inh);
10918 ITypeInfo_Release(tinfo);
10919 return hres;
10921 This->cbSizeVft = attr->cbSizeVft;
10922 ITypeInfo_ReleaseTypeAttr(inh, attr);
10925 ++depth;
10926 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10927 if(SUCCEEDED(hres)){
10928 ITypeInfo *next;
10929 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10930 if(SUCCEEDED(hres)){
10931 ITypeInfo_Release(inh);
10932 inh = next;
10935 }while(SUCCEEDED(hres));
10936 hres = S_OK;
10938 ITypeInfo_Release(inh);
10939 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10940 This->cbSizeVft = 0;
10941 hres = S_OK;
10942 } else {
10943 ITypeInfo_Release(tinfo);
10944 return hres;
10946 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10947 This->cbSizeVft = 0;
10948 hres = S_OK;
10949 } else {
10950 ITypeInfo_Release(tinfo);
10951 return hres;
10953 } else if (This->typekind == TKIND_DISPATCH)
10954 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10955 else
10956 This->cbSizeVft = 0;
10958 func_desc = This->funcdescs;
10959 i = 0;
10960 while (i < This->cFuncs) {
10961 if (!(func_desc->funcdesc.oVft & 0x1))
10962 func_desc->funcdesc.oVft = This->cbSizeVft;
10964 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10965 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10967 This->cbSizeVft += This->pTypeLib->ptr_size;
10969 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10970 TLBFuncDesc *iter;
10971 UINT j = 0;
10972 BOOL reset = FALSE;
10974 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10976 iter = This->funcdescs;
10977 while (j < This->cFuncs) {
10978 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10979 if (!reset) {
10980 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10981 reset = TRUE;
10982 } else
10983 ++func_desc->funcdesc.memid;
10984 iter = This->funcdescs;
10985 j = 0;
10986 } else {
10987 ++iter;
10988 ++j;
10993 ++func_desc;
10994 ++i;
10997 if (user_vft > This->cbSizeVft)
10998 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11000 for(i = 0; i < This->cVars; ++i){
11001 TLBVarDesc *var_desc = &This->vardescs[i];
11002 if(var_desc->vardesc.memid == MEMBERID_NIL){
11003 UINT j = 0;
11004 BOOL reset = FALSE;
11005 TLBVarDesc *iter;
11007 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11009 iter = This->vardescs;
11010 while (j < This->cVars) {
11011 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11012 if (!reset) {
11013 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->cVars;
11014 reset = TRUE;
11015 } else
11016 ++var_desc->vardesc.memid;
11017 iter = This->vardescs;
11018 j = 0;
11019 } else {
11020 ++iter;
11021 ++j;
11027 ITypeInfo_Release(tinfo);
11028 return hres;
11031 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11032 UINT index)
11034 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11035 FIXME("%p %u - stub\n", This, index);
11036 return E_NOTIMPL;
11039 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11040 MEMBERID memid, INVOKEKIND invKind)
11042 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11043 FIXME("%p %x %d - stub\n", This, memid, invKind);
11044 return E_NOTIMPL;
11047 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11048 UINT index)
11050 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11051 FIXME("%p %u - stub\n", This, index);
11052 return E_NOTIMPL;
11055 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11056 MEMBERID memid)
11058 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11059 FIXME("%p %x - stub\n", This, memid);
11060 return E_NOTIMPL;
11063 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11064 UINT index)
11066 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11067 FIXME("%p %u - stub\n", This, index);
11068 return E_NOTIMPL;
11071 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11072 REFGUID guid, VARIANT *varVal)
11074 TLBGuid *tlbguid;
11076 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11078 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11080 if (!guid || !varVal)
11081 return E_INVALIDARG;
11083 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11085 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11088 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11089 UINT index, REFGUID guid, VARIANT *varVal)
11091 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11092 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11093 return E_NOTIMPL;
11096 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11097 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11099 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11100 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11101 return E_NOTIMPL;
11104 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11105 UINT index, REFGUID guid, VARIANT *varVal)
11107 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11108 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11109 return E_NOTIMPL;
11112 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11113 UINT index, REFGUID guid, VARIANT *varVal)
11115 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11116 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11117 return E_NOTIMPL;
11120 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11121 ULONG helpStringContext)
11123 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11125 TRACE("%p %u\n", This, helpStringContext);
11127 This->dwHelpStringContext = helpStringContext;
11129 return S_OK;
11132 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11133 UINT index, ULONG helpStringContext)
11135 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11136 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11137 return E_NOTIMPL;
11140 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11141 UINT index, ULONG helpStringContext)
11143 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11144 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11145 return E_NOTIMPL;
11148 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11150 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11151 FIXME("%p - stub\n", This);
11152 return E_NOTIMPL;
11155 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11156 LPOLESTR name)
11158 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11160 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11162 if (!name)
11163 return E_INVALIDARG;
11165 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11167 return S_OK;
11170 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11171 ICreateTypeInfo2_fnQueryInterface,
11172 ICreateTypeInfo2_fnAddRef,
11173 ICreateTypeInfo2_fnRelease,
11174 ICreateTypeInfo2_fnSetGuid,
11175 ICreateTypeInfo2_fnSetTypeFlags,
11176 ICreateTypeInfo2_fnSetDocString,
11177 ICreateTypeInfo2_fnSetHelpContext,
11178 ICreateTypeInfo2_fnSetVersion,
11179 ICreateTypeInfo2_fnAddRefTypeInfo,
11180 ICreateTypeInfo2_fnAddFuncDesc,
11181 ICreateTypeInfo2_fnAddImplType,
11182 ICreateTypeInfo2_fnSetImplTypeFlags,
11183 ICreateTypeInfo2_fnSetAlignment,
11184 ICreateTypeInfo2_fnSetSchema,
11185 ICreateTypeInfo2_fnAddVarDesc,
11186 ICreateTypeInfo2_fnSetFuncAndParamNames,
11187 ICreateTypeInfo2_fnSetVarName,
11188 ICreateTypeInfo2_fnSetTypeDescAlias,
11189 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11190 ICreateTypeInfo2_fnSetFuncDocString,
11191 ICreateTypeInfo2_fnSetVarDocString,
11192 ICreateTypeInfo2_fnSetFuncHelpContext,
11193 ICreateTypeInfo2_fnSetVarHelpContext,
11194 ICreateTypeInfo2_fnSetMops,
11195 ICreateTypeInfo2_fnSetTypeIdldesc,
11196 ICreateTypeInfo2_fnLayOut,
11197 ICreateTypeInfo2_fnDeleteFuncDesc,
11198 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11199 ICreateTypeInfo2_fnDeleteVarDesc,
11200 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11201 ICreateTypeInfo2_fnDeleteImplType,
11202 ICreateTypeInfo2_fnSetCustData,
11203 ICreateTypeInfo2_fnSetFuncCustData,
11204 ICreateTypeInfo2_fnSetParamCustData,
11205 ICreateTypeInfo2_fnSetVarCustData,
11206 ICreateTypeInfo2_fnSetImplTypeCustData,
11207 ICreateTypeInfo2_fnSetHelpStringContext,
11208 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11209 ICreateTypeInfo2_fnSetVarHelpStringContext,
11210 ICreateTypeInfo2_fnInvalidate,
11211 ICreateTypeInfo2_fnSetName
11214 /******************************************************************************
11215 * ClearCustData (OLEAUT32.171)
11217 * Clear a custom data type's data.
11219 * PARAMS
11220 * lpCust [I] The custom data type instance
11222 * RETURNS
11223 * Nothing.
11225 void WINAPI ClearCustData(CUSTDATA *lpCust)
11227 if (lpCust && lpCust->cCustData)
11229 if (lpCust->prgCustData)
11231 DWORD i;
11233 for (i = 0; i < lpCust->cCustData; i++)
11234 VariantClear(&lpCust->prgCustData[i].varValue);
11236 CoTaskMemFree(lpCust->prgCustData);
11237 lpCust->prgCustData = NULL;
11239 lpCust->cCustData = 0;